// Copyright (C) 2013 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.gerrit.client.diff;

import com.google.gerrit.client.FormatUtil;
import com.google.gerrit.client.change.LocalComments;
import com.google.gerrit.client.changes.CommentApi;
import com.google.gerrit.client.changes.CommentInfo;
import com.google.gerrit.client.rpc.CallbackGroup;
import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gerrit.client.rpc.RestApi;
import com.google.gerrit.client.ui.CommentLinkProcessor;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.Element;
import com.google.gwt.event.dom.client.BlurEvent;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.DoubleClickEvent;
import com.google.gwt.event.dom.client.DoubleClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyDownEvent;
import com.google.gwt.event.dom.client.MouseMoveEvent;
import com.google.gwt.event.dom.client.MouseMoveHandler;
import com.google.gwt.event.dom.client.MouseUpEvent;
import com.google.gwt.event.dom.client.MouseUpHandler;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.UIObject;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwtexpui.globalkey.client.NpTextArea;
import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
import net.codemirror.lib.CodeMirror;

/** An HtmlPanel for displaying and editing a draft */
class DraftBox extends CommentBox {
  interface Binder extends UiBinder<HTMLPanel, DraftBox> {}

  private static final Binder uiBinder = GWT.create(Binder.class);

  private static final int INITIAL_LINES = 5;
  private static final int MAX_LINES = 30;

  private final CommentLinkProcessor linkProcessor;
  private final PatchSet.Id psId;
  private final boolean expandAll;
  private CommentInfo comment;
  private PublishedBox replyToBox;
  private Timer expandTimer;
  private Timer resizeTimer;
  private int editAreaHeight;
  private boolean autoClosed;
  private CallbackGroup pendingGroup;

  @UiField Widget header;
  @UiField Element summary;
  @UiField Element date;

  @UiField Element p_view;
  @UiField HTML message;
  @UiField Button edit;
  @UiField Button discard1;

  @UiField Element p_edit;
  @UiField NpTextArea editArea;
  @UiField Button save;
  @UiField Button cancel;
  @UiField Button discard2;

  DraftBox(
      CommentGroup group,
      CommentLinkProcessor clp,
      PatchSet.Id id,
      CommentInfo info,
      boolean expandAllComments) {
    super(group, info.range());

    linkProcessor = clp;
    psId = id;
    expandAll = expandAllComments;
    initWidget(uiBinder.createAndBindUi(this));

    expandTimer =
        new Timer() {
          @Override
          public void run() {
            expandText();
          }
        };
    set(info);

    header.addDomHandler(
        new ClickHandler() {
          @Override
          public void onClick(ClickEvent event) {
            if (!isEdit()) {
              if (autoClosed && !isOpen()) {
                setOpen(true);
                setEdit(true);
              } else {
                setOpen(!isOpen());
              }
            }
          }
        },
        ClickEvent.getType());

    addDomHandler(
        new DoubleClickHandler() {
          @Override
          public void onDoubleClick(DoubleClickEvent event) {
            if (isEdit()) {
              editArea.setFocus(true);
            } else {
              setOpen(true);
              setEdit(true);
            }
          }
        },
        DoubleClickEvent.getType());

    initResizeHandler();
  }

  private void set(CommentInfo info) {
    autoClosed = !expandAll && info.message() != null && info.message().length() < 70;
    date.setInnerText(FormatUtil.shortFormatDayTime(info.updated()));
    if (info.message() != null) {
      String msg = info.message().trim();
      summary.setInnerText(msg);
      message.setHTML(linkProcessor.apply(new SafeHtmlBuilder().append(msg).wikify()));
    }
    comment = info;
  }

  @Override
  CommentInfo getCommentInfo() {
    return comment;
  }

  @Override
  boolean isOpen() {
    return UIObject.isVisible(p_view);
  }

  @Override
  void setOpen(boolean open) {
    UIObject.setVisible(summary, !open);
    UIObject.setVisible(p_view, open);
    super.setOpen(open);
  }

  private void expandText() {
    double cols = editArea.getCharacterWidth();
    int rows = 2;
    for (String line : editArea.getValue().split("\n")) {
      rows += Math.ceil((1.0 + line.length()) / cols);
    }
    rows = Math.max(INITIAL_LINES, Math.min(rows, MAX_LINES));
    if (editArea.getVisibleLines() != rows) {
      editArea.setVisibleLines(rows);
    }
    editAreaHeight = editArea.getOffsetHeight();
    getCommentGroup().resize();
  }

  boolean isEdit() {
    return UIObject.isVisible(p_edit);
  }

  void setEdit(boolean edit) {
    UIObject.setVisible(summary, false);
    UIObject.setVisible(p_view, !edit);
    UIObject.setVisible(p_edit, edit);

    setRangeHighlight(edit);
    if (edit) {
      String msg = comment.message() != null ? comment.message() : "";
      editArea.setValue(msg);
      cancel.setVisible(!isNew());
      expandText();
      editAreaHeight = editArea.getOffsetHeight();

      final int len = msg.length();
      Scheduler.get()
          .scheduleDeferred(
              new ScheduledCommand() {
                @Override
                public void execute() {
                  editArea.setFocus(true);
                  if (len > 0) {
                    editArea.setCursorPos(len);
                  }
                }
              });
    } else {
      expandTimer.cancel();
      resizeTimer.cancel();
    }
    getCommentManager().setUnsaved(this, edit);
    getCommentGroup().resize();
  }

  PublishedBox getReplyToBox() {
    return replyToBox;
  }

  void setReplyToBox(PublishedBox box) {
    replyToBox = box;
  }

  @Override
  protected void onUnload() {
    expandTimer.cancel();
    resizeTimer.cancel();
    super.onUnload();
  }

  private void removeUI() {
    if (replyToBox != null) {
      replyToBox.unregisterReplyBox();
    }

    getCommentManager().setUnsaved(this, false);
    setRangeHighlight(false);
    clearRange();
    getAnnotation().remove();
    getCommentGroup().remove(this);
    getCm().focus();
  }

  private void restoreSelection() {
    if (getFromTo() != null && comment.inReplyTo() == null) {
      getCm().setSelection(getFromTo().from(), getFromTo().to());
    }
  }

  @UiHandler("message")
  void onMessageClick(ClickEvent e) {
    e.stopPropagation();
  }

  @UiHandler("message")
  void onMessageDoubleClick(@SuppressWarnings("unused") DoubleClickEvent e) {
    setEdit(true);
  }

  @UiHandler("edit")
  void onEdit(ClickEvent e) {
    e.stopPropagation();
    setEdit(true);
  }

  @UiHandler("save")
  void onSave(ClickEvent e) {
    e.stopPropagation();
    CallbackGroup group = new CallbackGroup();
    save(group);
    group.done();
  }

  void save(CallbackGroup group) {
    if (pendingGroup != null) {
      pendingGroup.addListener(group);
      return;
    }

    String message = editArea.getValue().trim();
    if (message.length() == 0) {
      return;
    }

    CommentInfo input = CommentInfo.copy(comment);
    input.message(message);
    enableEdit(false);

    pendingGroup = group;
    final LocalComments lc = new LocalComments(psId);
    GerritCallback<CommentInfo> cb =
        new GerritCallback<CommentInfo>() {
          @Override
          public void onSuccess(CommentInfo result) {
            enableEdit(true);
            pendingGroup = null;
            set(result);
            setEdit(false);
            if (autoClosed) {
              setOpen(false);
            }
            getCommentManager().setUnsaved(DraftBox.this, false);
          }

          @Override
          public void onFailure(Throwable e) {
            enableEdit(true);
            pendingGroup = null;
            if (RestApi.isNotSignedIn(e)) {
              CommentInfo saved = CommentInfo.copy(comment);
              saved.message(editArea.getValue().trim());
              lc.setInlineComment(saved);
            }
            super.onFailure(e);
          }
        };
    if (input.id() == null) {
      CommentApi.createDraft(psId, input, group.add(cb));
    } else {
      CommentApi.updateDraft(psId, input.id(), input, group.add(cb));
    }
    CodeMirror cm = getCm();
    cm.vim().handleKey("<Esc>");
    cm.focus();
  }

  private void enableEdit(boolean on) {
    editArea.setEnabled(on);
    save.setEnabled(on);
    cancel.setEnabled(on);
    discard2.setEnabled(on);
  }

  @UiHandler("cancel")
  void onCancel(ClickEvent e) {
    e.stopPropagation();
    if (isNew() && !isDirty()) {
      removeUI();
      restoreSelection();
    } else {
      setEdit(false);
      if (autoClosed) {
        setOpen(false);
      }
      getCm().focus();
    }
  }

  @UiHandler({"discard1", "discard2"})
  void onDiscard(ClickEvent e) {
    e.stopPropagation();
    if (isNew()) {
      removeUI();
      restoreSelection();
    } else {
      setEdit(false);
      pendingGroup = new CallbackGroup();
      CommentApi.deleteDraft(
          psId,
          comment.id(),
          pendingGroup.addFinal(
              new GerritCallback<JavaScriptObject>() {
                @Override
                public void onSuccess(JavaScriptObject result) {
                  pendingGroup = null;
                  removeUI();
                }
              }));
    }
  }

  @UiHandler("editArea")
  void onKeyDown(KeyDownEvent e) {
    resizeTimer.cancel();
    if ((e.isControlKeyDown() || e.isMetaKeyDown()) && !e.isAltKeyDown() && !e.isShiftKeyDown()) {
      switch (e.getNativeKeyCode()) {
        case 's':
        case 'S':
          e.preventDefault();
          CallbackGroup group = new CallbackGroup();
          save(group);
          group.done();
          return;
      }
    } else if (e.getNativeKeyCode() == KeyCodes.KEY_ESCAPE && !isDirty()) {
      if (isNew()) {
        removeUI();
        restoreSelection();
        return;
      }
      setEdit(false);
      if (autoClosed) {
        setOpen(false);
      }
      getCm().focus();
      return;
    }
    expandTimer.schedule(250);
  }

  @UiHandler("editArea")
  void onBlur(@SuppressWarnings("unused") BlurEvent e) {
    resizeTimer.cancel();
  }

  private void initResizeHandler() {
    resizeTimer =
        new Timer() {
          @Override
          public void run() {
            getCommentGroup().resize();
          }
        };

    addDomHandler(
        new MouseMoveHandler() {
          @Override
          public void onMouseMove(MouseMoveEvent event) {
            int h = editArea.getOffsetHeight();
            if (isEdit() && h != editAreaHeight) {
              getCommentGroup().resize();
              resizeTimer.scheduleRepeating(50);
              editAreaHeight = h;
            }
          }
        },
        MouseMoveEvent.getType());

    addDomHandler(
        new MouseUpHandler() {
          @Override
          public void onMouseUp(MouseUpEvent event) {
            resizeTimer.cancel();
            getCommentGroup().resize();
          }
        },
        MouseUpEvent.getType());
  }

  private boolean isNew() {
    return comment.id() == null;
  }

  private boolean isDirty() {
    String msg = editArea.getValue().trim();
    if (isNew()) {
      return msg.length() > 0;
    }
    return !msg.equals(comment.message() != null ? comment.message().trim() : "");
  }
}
