// 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.change;

import static com.google.gwt.event.dom.client.KeyCodes.KEY_ENTER;
import static com.google.gwt.event.dom.client.KeyCodes.KEY_MAC_ENTER;

import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.changes.ChangeApi;
import com.google.gerrit.client.changes.CommentInfo;
import com.google.gerrit.client.changes.ReviewInput;
import com.google.gerrit.client.changes.ReviewInput.DraftHandling;
import com.google.gerrit.client.changes.Util;
import com.google.gerrit.client.info.ChangeInfo.ApprovalInfo;
import com.google.gerrit.client.info.ChangeInfo.LabelInfo;
import com.google.gerrit.client.info.ChangeInfo.MessageInfo;
import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gerrit.client.rpc.NativeMap;
import com.google.gerrit.client.rpc.Natives;
import com.google.gerrit.client.rpc.RestApi;
import com.google.gerrit.client.ui.CommentLinkProcessor;
import com.google.gerrit.common.PageLinks;
import com.google.gerrit.common.data.LabelValue;
import com.google.gerrit.reviewdb.client.Patch;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.core.client.JsArrayString;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.RepeatingCommand;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.Element;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyDownEvent;
import com.google.gwt.event.dom.client.KeyDownHandler;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.event.dom.client.MouseOutEvent;
import com.google.gwt.event.dom.client.MouseOutHandler;
import com.google.gwt.event.dom.client.MouseOverEvent;
import com.google.gwt.event.dom.client.MouseOverHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.resources.client.CssResource;
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.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.RadioButton;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.UIObject;
import com.google.gwt.user.client.ui.Widget;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

public class ReplyBox extends Composite {
  interface Binder extends UiBinder<HTMLPanel, ReplyBox> {}
  private static final Binder uiBinder = GWT.create(Binder.class);

  interface Styles extends CssResource {
    String label_name();
    String label_value();
    String label_help();
  }

  private final CommentLinkProcessor clp;
  private final PatchSet.Id psId;
  private final String revision;
  private ReviewInput in = ReviewInput.create();
  private int labelHelpColumn;
  private LocalComments lc;

  @UiField Styles style;
  @UiField TextArea message;
  @UiField Element labelsParent;
  @UiField Grid labelsTable;
  @UiField Button post;
  @UiField Button cancel;
  @UiField ScrollPanel commentsPanel;
  @UiField FlowPanel comments;

  ReplyBox(
      CommentLinkProcessor clp,
      PatchSet.Id psId,
      String revision,
      NativeMap<LabelInfo> all,
      NativeMap<JsArrayString> permitted) {
    this.clp = clp;
    this.psId = psId;
    this.revision = revision;
    this.lc = new LocalComments(psId.getParentKey());
    initWidget(uiBinder.createAndBindUi(this));

    List<String> names = new ArrayList<>(permitted.keySet());
    if (names.isEmpty()) {
      UIObject.setVisible(labelsParent, false);
    } else {
      Collections.sort(names);
      renderLabels(names, all, permitted);
    }

    addDomHandler(
      new KeyDownHandler() {
        @Override
        public void onKeyDown(KeyDownEvent e) {
          e.stopPropagation();
          if ((e.getNativeKeyCode() == KEY_ENTER
              || e.getNativeKeyCode() == KEY_MAC_ENTER)
              && (e.isControlKeyDown() || e.isMetaKeyDown())) {
            e.preventDefault();
            if (post.isEnabled()) {
              onPost(null);
            }
          }
        }
      },
      KeyDownEvent.getType());
    addDomHandler(
      new KeyPressHandler() {
        @Override
        public void onKeyPress(KeyPressEvent e) {
          e.stopPropagation();
        }
      },
      KeyPressEvent.getType());
  }

  @Override
  protected void onLoad() {
    commentsPanel.setVisible(false);
    post.setEnabled(false);
    if (lc.hasReplyComment()) {
      message.setText(lc.getReplyComment());
      lc.removeReplyComment();
    }
    ChangeApi.drafts(psId.getParentKey().get())
        .get(new AsyncCallback<NativeMap<JsArray<CommentInfo>>>() {
          @Override
          public void onSuccess(NativeMap<JsArray<CommentInfo>> result) {
            displayComments(result);
            post.setEnabled(true);
          }

          @Override
          public void onFailure(Throwable caught) {
            post.setEnabled(true);
          }
        });

    Scheduler.get().scheduleDeferred(new ScheduledCommand() {
      @Override
      public void execute() {
        message.setFocus(true);
      }
    });
    Scheduler.get().scheduleFixedDelay(new RepeatingCommand() {
      @Override
      public boolean execute() {
        String t = message.getText();
        if (t != null) {
          message.setCursorPos(t.length());
        }
        return false;
      }
    }, 0);
  }

  @UiHandler("post")
  void onPost(@SuppressWarnings("unused") ClickEvent e) {
    postReview();
  }

  void quickApprove(ReviewInput quickApproveInput) {
    in.mergeLabels(quickApproveInput);
    postReview();
  }

  boolean hasMessage() {
    return !message.getText().trim().isEmpty();
  }

  private void postReview() {
    in.message(message.getText().trim());
    // Don't send any comments in the request; just publish everything, even if
    // e.g. a draft was modified in another tab since we last looked it up.
    in.drafts(DraftHandling.PUBLISH_ALL_REVISIONS);
    in.prePost();
    ChangeApi.revision(psId.getParentKey().get(), revision)
      .view("review")
      .post(in, new GerritCallback<ReviewInput>() {
        @Override
        public void onSuccess(ReviewInput result) {
          Gerrit.display(PageLinks.toChange(psId));
        }
        @Override
        public void onFailure(final Throwable caught) {
          if (RestApi.isNotSignedIn(caught)) {
            lc.setReplyComment(message.getText());
          }
          super.onFailure(caught);
        }
      });
    hide();
  }

  @UiHandler("cancel")
  void onCancel(@SuppressWarnings("unused") ClickEvent e) {
    message.setText("");
    hide();
  }

  void replyTo(MessageInfo msg) {
    if (msg.message() != null) {
      String t = message.getText();
      String m = quote(removePatchSetHeaderLine(msg.message()));
      if (t == null || t.isEmpty()) {
        t = m;
      } else if (t.endsWith("\n\n")) {
        t += m;
      } else if (t.endsWith("\n")) {
        t += "\n" + m;
      } else {
        t += "\n\n" + m;
      }
      message.setText(t);
    }
  }

  private static String removePatchSetHeaderLine(String msg) {
    msg = msg.trim();
    if (msg.startsWith("Patch Set ")) {
      int i = msg.indexOf('\n');
      if (i > 0) {
        msg = msg.substring(i + 1).trim();
      }
    }
    return msg;
  }

  public static String quote(String msg) {
    msg = msg.trim();
    StringBuilder quotedMsg = new StringBuilder();
    for (String line : msg.split("\\n")) {
      line = line.trim();
      while (line.length() > 67) {
        int i = line.lastIndexOf(' ', 67);
        if (i < 50) {
          i = line.indexOf(' ', 67);
        }
        if (i > 0) {
          quotedMsg.append(" > ").append(line.substring(0, i)).append("\n");
          line = line.substring(i + 1);
        } else {
          break;
        }
      }
      quotedMsg.append(" > ").append(line).append("\n");
    }
    quotedMsg.append("\n");
    return quotedMsg.toString();
  }

  private void hide() {
    for (Widget w = getParent(); w != null; w = w.getParent()) {
      if (w instanceof PopupPanel) {
        ((PopupPanel) w).hide();
        break;
      }
    }
  }

  private void renderLabels(
      List<String> names,
      NativeMap<LabelInfo> all,
      NativeMap<JsArrayString> permitted) {
    TreeSet<Short> values = new TreeSet<>();
    List<LabelAndValues> labels = new ArrayList<>(permitted.size());
    for (String id : names) {
      JsArrayString p = permitted.get(id);
      if (p != null) {
        Set<Short> a = new TreeSet<>();
        for (int i = 0; i < p.length(); i++) {
          a.add(LabelInfo.parseValue(p.get(i)));
        }
        labels.add(new LabelAndValues(all.get(id), a));
        values.addAll(a);
      }
    }
    List<Short> columns = new ArrayList<>(values);

    labelsTable.resize(1 + labels.size(), 2 + values.size());
    for (int c = 0; c < columns.size(); c++) {
      labelsTable.setText(0, 1 + c, LabelValue.formatValue(columns.get(c)));
      labelsTable.getCellFormatter().setStyleName(0, 1 + c, style.label_value());
    }

    List<LabelAndValues> checkboxes = new ArrayList<>(labels.size());
    int row = 1;
    for (LabelAndValues lv : labels) {
      if (isCheckBox(lv.info.valueSet())) {
        checkboxes.add(lv);
      } else {
        renderRadio(row++, columns, lv);
      }
    }
    for (LabelAndValues lv : checkboxes) {
      renderCheckBox(row++, lv);
    }
  }

  private Short normalizeDefaultValue(Short defaultValue, Set<Short> permittedValues) {
    Short pmin = Collections.min(permittedValues);
    Short pmax = Collections.max(permittedValues);
    Short dv = defaultValue;
    if (dv > pmax) {
      dv = pmax;
    } else if (dv < pmin) {
      dv = pmin;
    }
    return dv;
  }

  private void renderRadio(int row,
      List<Short> columns,
      LabelAndValues lv) {
    String id = lv.info.name();
    Short dv = normalizeDefaultValue(lv.info.defaultValue(), lv.permitted);

    labelHelpColumn = 1 + columns.size();
    labelsTable.setText(row, 0, id);

    CellFormatter fmt = labelsTable.getCellFormatter();
    fmt.setStyleName(row, 0, style.label_name());
    fmt.setStyleName(row, labelHelpColumn, style.label_help());

    ApprovalInfo self = Gerrit.isSignedIn()
        ? lv.info.forUser(Gerrit.getUserAccount().getId().get())
        : null;

    final LabelRadioGroup group =
        new LabelRadioGroup(row, id, lv.permitted.size());
    for (int i = 0; i < columns.size(); i++) {
      Short v = columns.get(i);
      if (lv.permitted.contains(v)) {
        String text = lv.info.valueText(LabelValue.formatValue(v));
        LabelRadioButton b = new LabelRadioButton(group, text, v);
        if ((self != null && v == self.value()) || (self == null && v.equals(dv))) {
          b.setValue(true);
          group.select(b);
          in.label(group.label, v);
          labelsTable.setText(row, labelHelpColumn, b.text);
        }
        group.buttons.add(b);
        labelsTable.setWidget(row, 1 + i, b);
      }
    }
  }

  private void renderCheckBox(int row, LabelAndValues lv) {
    ApprovalInfo self = Gerrit.isSignedIn()
        ? lv.info.forUser(Gerrit.getUserAccount().getId().get())
        : null;

    final String id = lv.info.name();
    final CheckBox b = new CheckBox();
    b.setText(id);
    b.setEnabled(lv.permitted.contains((short) 1));
    if (self != null && self.value() == 1) {
      b.setValue(true);
    }
    b.addValueChangeHandler(new ValueChangeHandler<Boolean>() {
      @Override
      public void onValueChange(ValueChangeEvent<Boolean> event) {
        in.label(id, event.getValue() ? (short) 1 : (short) 0);
      }
    });
    b.setStyleName(style.label_name());
    labelsTable.setWidget(row, 0, b);

    CellFormatter fmt = labelsTable.getCellFormatter();
    fmt.setStyleName(row, labelHelpColumn, style.label_help());
    labelsTable.setText(row, labelHelpColumn, lv.info.valueText("+1"));
  }

  private static boolean isCheckBox(Set<Short> values) {
    return values.size() == 2
        && values.contains((short) 0)
        && values.contains((short) 1);
  }

  private void displayComments(NativeMap<JsArray<CommentInfo>> m) {
    comments.clear();

    JsArray<CommentInfo> l = m.get(Patch.COMMIT_MSG);
    if (l != null) {
      comments.add(new FileComments(clp, psId,
          Util.C.commitMessage(), copyPath(Patch.COMMIT_MSG, l)));
    }

    List<String> paths = new ArrayList<>(m.keySet());
    Collections.sort(paths);

    for (String path : paths) {
      if (!path.equals(Patch.COMMIT_MSG)) {
        comments.add(new FileComments(clp, psId,
            path, copyPath(path, m.get(path))));
      }
    }

    commentsPanel.setVisible(comments.getWidgetCount() > 0);
  }

  private static List<CommentInfo> copyPath(String path, JsArray<CommentInfo> l) {
    for (int i = 0; i < l.length(); i++) {
      l.get(i).path(path);
    }
    return Natives.asList(l);
  }

  private static class LabelAndValues {
    final LabelInfo info;
    final Set<Short> permitted;

    LabelAndValues(LabelInfo info, Set<Short> permitted) {
      this.info = info;
      this.permitted = permitted;
    }
  }

  private class LabelRadioGroup {
    final int row;
    final String label;
    final List<LabelRadioButton> buttons;
    LabelRadioButton selected;

    LabelRadioGroup(int row, String label, int cnt) {
      this.row = row;
      this.label = label;
      this.buttons = new ArrayList<>(cnt);
    }

    void select(LabelRadioButton b) {
      selected = b;
      labelsTable.setText(row, labelHelpColumn, b.text);
    }
  }

  private class LabelRadioButton extends RadioButton implements
      ValueChangeHandler<Boolean>, ClickHandler, MouseOverHandler,
      MouseOutHandler {
    private final LabelRadioGroup group;
    private final String text;
    private final short value;

    LabelRadioButton(LabelRadioGroup group, String text, short value) {
      super(group.label);
      this.group = group;
      this.text = text;
      this.value = value;
      addValueChangeHandler(this);
      addClickHandler(this);
      addMouseOverHandler(this);
      addMouseOutHandler(this);
    }

    @Override
    public void onValueChange(ValueChangeEvent<Boolean> event) {
      if (event.getValue()) {
        select();
      }
    }

    @Override
    public void onClick(ClickEvent event) {
      select();
    }

    void select() {
      group.select(this);
      in.label(group.label, value);
    }

    @Override
    public void onMouseOver(MouseOverEvent event) {
      labelsTable.setText(group.row, labelHelpColumn, text);
    }

    @Override
    public void onMouseOut(MouseOutEvent event) {
      LabelRadioButton b = group.selected;
      String s = b != null ? b.text : "";
      labelsTable.setText(group.row, labelHelpColumn, s);
    }
  }
}
