// 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()
        : "");
  }
}
