// Copyright (C) 2009 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.changes;

import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.changes.ChangeInfo.ApprovalInfo;
import com.google.gerrit.client.changes.ChangeInfo.LabelInfo;
import com.google.gerrit.client.patches.AbstractPatchContentTable;
import com.google.gerrit.client.patches.CommentEditorContainer;
import com.google.gerrit.client.patches.CommentEditorPanel;
import com.google.gerrit.client.projects.ConfigInfoCache;
import com.google.gerrit.client.rpc.CallbackGroup;
import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gerrit.client.rpc.NativeMap;
import com.google.gerrit.client.rpc.NativeString;
import com.google.gerrit.client.rpc.Natives;
import com.google.gerrit.client.rpc.RestApi;
import com.google.gerrit.client.rpc.ScreenLoadCallback;
import com.google.gerrit.client.ui.AccountScreen;
import com.google.gerrit.client.ui.CommentLinkProcessor;
import com.google.gerrit.client.ui.PatchLink;
import com.google.gerrit.client.ui.SmallHeading;
import com.google.gerrit.common.PageLinks;
import com.google.gerrit.common.data.ChangeDetail;
import com.google.gerrit.common.data.SubmitTypeRecord;
import com.google.gerrit.extensions.common.ListChangesOption;
import com.google.gerrit.extensions.common.SubmitType;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Patch;
import com.google.gerrit.reviewdb.client.PatchLineComment;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.core.client.JsArrayString;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.FormPanel;
import com.google.gwt.user.client.ui.FormPanel.SubmitEvent;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.RadioButton;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwtexpui.globalkey.client.NpTextArea;
import com.google.gwtexpui.safehtml.client.SafeHtml;
import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
import com.google.gwtjsonrpc.common.VoidResult;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class PublishCommentScreen extends AccountScreen implements
    ClickHandler, CommentEditorContainer {
  private static SavedState lastState;

  private final PatchSet.Id patchSetId;
  private Collection<ValueRadioButton> approvalButtons;
  private ChangeDescriptionBlock descBlock;
  private ApprovalTable approvals;
  private Panel approvalPanel;
  private NpTextArea message;
  private FlowPanel draftsPanel;
  private Button send;
  private Button cancel;
  private boolean saveStateOnUnload = true;
  private List<CommentEditorPanel> commentEditors;
  private ChangeInfo change;
  private ChangeInfo detail;
  private NativeMap<JsArray<CommentInfo>> drafts;
  private SubmitTypeRecord submitTypeRecord;
  private CommentLinkProcessor commentLinkProcessor;

  public PublishCommentScreen(final PatchSet.Id psi) {
    patchSetId = psi;
  }

  @Override
  protected void onInitUI() {
    super.onInitUI();
    addStyleName(Gerrit.RESOURCES.css().publishCommentsScreen());

    approvalButtons = new ArrayList<>();
    descBlock = new ChangeDescriptionBlock(null);
    add(descBlock);

    approvals = new ApprovalTable();
    add(approvals);

    final FormPanel form = new FormPanel();
    final FlowPanel body = new FlowPanel();
    form.setWidget(body);
    form.addSubmitHandler(new FormPanel.SubmitHandler() {
      @Override
      public void onSubmit(final SubmitEvent event) {
        event.cancel();
      }
    });
    add(form);

    approvalPanel = new FlowPanel();
    body.add(approvalPanel);
    initMessage(body);

    draftsPanel = new FlowPanel();
    body.add(draftsPanel);

    final FlowPanel buttonRow = new FlowPanel();
    buttonRow.setStyleName(Gerrit.RESOURCES.css().patchSetActions());
    body.add(buttonRow);

    send = new Button(Util.C.buttonPublishCommentsSend());
    send.addClickHandler(this);
    buttonRow.add(send);

    cancel = new Button(Util.C.buttonPublishCommentsCancel());
    cancel.addClickHandler(this);
    buttonRow.add(cancel);
  }

  private void enableForm(final boolean enabled) {
    for (final ValueRadioButton approvalButton : approvalButtons) {
      approvalButton.setEnabled(enabled);
    }
    message.setEnabled(enabled);
    for (final CommentEditorPanel commentEditor : commentEditors) {
      commentEditor.enableButtons(enabled);
    }
    send.setEnabled(enabled);
    cancel.setEnabled(enabled);
  }

  @Override
  protected void onLoad() {
    super.onLoad();

    CallbackGroup group = new CallbackGroup();
    RestApi call = ChangeApi.detail(patchSetId.getParentKey().get());
    ChangeList.addOptions(call, EnumSet.of(
      ListChangesOption.CURRENT_ACTIONS,
      ListChangesOption.ALL_REVISIONS,
      ListChangesOption.ALL_COMMITS));
    call.get(group.add(new GerritCallback<ChangeInfo>() {
        @Override
        public void onSuccess(ChangeInfo result) {
          detail = result;
        }
      }));
    ChangeApi.revision(patchSetId)
      .view("submit_type")
      .get(group.add(new GerritCallback<NativeString>() {
        @Override
        public void onSuccess(NativeString result) {
          submitTypeRecord = SubmitTypeRecord.OK(
              SubmitType.valueOf(result.asString()));
        }
        public void onFailure(Throwable caught) {}
      }));
    ChangeApi.revision(patchSetId.getParentKey().get(), "" + patchSetId.get())
      .view("drafts")
      .get(group.add(new AsyncCallback<NativeMap<JsArray<CommentInfo>>>() {
        @Override
        public void onSuccess(NativeMap<JsArray<CommentInfo>> result) {
          drafts = result;
        }
        public void onFailure(Throwable caught) {}
      }));
    ChangeApi.revision(patchSetId).view("review")
      .get(group.addFinal(new GerritCallback<ChangeInfo>() {
        @Override
        public void onSuccess(ChangeInfo result) {
          result.init();
          change = result;
          preDisplay(result);
        }
      }));
  }

  private void preDisplay(final ChangeInfo info) {
    ConfigInfoCache.get(info.project_name_key(),
        new ScreenLoadCallback<ConfigInfoCache.Entry>(this) {
          @Override
          protected void preDisplay(ConfigInfoCache.Entry result) {
            send.setEnabled(true);
            commentLinkProcessor = result.getCommentLinkProcessor();
            setTheme(result.getTheme());
            displayScreen();
          }

          @Override
          protected void postDisplay() {
            message.setFocus(true);
          }
        });
  }

  @Override
  protected void onUnload() {
    super.onUnload();
    lastState = saveStateOnUnload ? new SavedState(this) : null;
  }

  @Override
  public void onClick(final ClickEvent event) {
    final Widget sender = (Widget) event.getSource();
    if (send == sender) {
      onSend(false);
    } else if (cancel == sender) {
      saveStateOnUnload = false;
      goChange();
    }
  }

  @Override
  public void notifyDraftDelta(int delta) {
  }

  @Override
  public void remove(CommentEditorPanel editor) {
    commentEditors.remove(editor);

    // The editor should be embedded into a panel holding all
    // editors for the same file.
    //
    FlowPanel parent = (FlowPanel) editor.getParent();
    parent.remove(editor);

    // If the panel now holds no editors, remove it.
    //
    int editorCount = 0;
    for (Widget w : parent) {
      if (w instanceof CommentEditorPanel) {
        editorCount++;
      }
    }
    if (editorCount == 0) {
      parent.removeFromParent();
    }

    // If that was the last file with a draft, remove the heading.
    //
    if (draftsPanel.getWidgetCount() == 1) {
      draftsPanel.clear();
    }
  }

  private void initMessage(final Panel body) {
    body.add(new SmallHeading(Util.C.headingCoverMessage()));

    final VerticalPanel mwrap = new VerticalPanel();
    mwrap.setStyleName(Gerrit.RESOURCES.css().coverMessage());
    body.add(mwrap);

    message = new NpTextArea();
    message.setCharacterWidth(60);
    message.setVisibleLines(10);
    message.setSpellCheck(true);
    mwrap.add(message);
  }

  private void initApprovals(Panel body) {
    for (String labelName : change.labels()) {
      initLabel(labelName, body);
    }
  }

  private void initLabel(String labelName, Panel body) {
    if (!change.has_permitted_labels()) {
      return;
    }
    JsArrayString nativeValues = change.permitted_values(labelName);
    if (nativeValues == null || nativeValues.length() == 0) {
      return;
    }
    List<String> values = new ArrayList<>(nativeValues.length());
    for (int i = 0; i < nativeValues.length(); i++) {
      values.add(nativeValues.get(i));
    }
    Collections.reverse(values);
    LabelInfo label = change.label(labelName);

    body.add(new SmallHeading(label.name() + ":"));

    VerticalPanel vp = new VerticalPanel();
    vp.setStyleName(Gerrit.RESOURCES.css().labelList());

    Short prior = null;
    if (label.all() != null) {
      for (ApprovalInfo app : Natives.asList(label.all())) {
        if (app._account_id() == Gerrit.getUserAccount().getId().get()) {
          prior = app.value();
          break;
        }
      }
    }

    for (String value : values) {
      ValueRadioButton b = new ValueRadioButton(label, value);
      SafeHtml buf = new SafeHtmlBuilder().append(b.format());
      buf = commentLinkProcessor.apply(buf);
      SafeHtml.set(b, buf);

      if (lastState != null && patchSetId.equals(lastState.patchSetId)
          && lastState.approvals.containsKey(label.name())) {
        b.setValue(lastState.approvals.get(label.name()).equals(value));
      } else {
        b.setValue(b.parseValue() == (prior != null ? prior : 0));
      }

      approvalButtons.add(b);
      vp.add(b);
    }
    body.add(vp);
  }

  private void displayScreen() {
    ChangeDetail r = ChangeDetailCache.reverse(detail);

    setPageTitle(Util.M.publishComments(r.getChange().getKey().abbreviate(),
        patchSetId.get()));
    descBlock.display(r, null, false, r.getCurrentPatchSetDetail().getInfo(),
        r.getAccounts(), submitTypeRecord, commentLinkProcessor);

    if (r.getChange().getStatus().isOpen()) {
      initApprovals(approvalPanel);
      approvals.display(change);
    } else {
      approvals.setVisible(false);
    }

    if (lastState != null && patchSetId.equals(lastState.patchSetId)) {
      message.setText(lastState.message);
    }

    draftsPanel.clear();
    commentEditors = new ArrayList<>();

    if (!drafts.isEmpty()) {
      draftsPanel.add(new SmallHeading(Util.C.headingPatchComments()));

      Panel panel = null;
      String priorFile = "";
      for (final PatchLineComment c : draftList()) {
        final Patch.Key patchKey = c.getKey().getParentKey();
        final String fn = patchKey.get();
        if (!fn.equals(priorFile)) {
          panel = new FlowPanel();
          panel.addStyleName(Gerrit.RESOURCES.css().patchComments());
          draftsPanel.add(panel);
          // Parent table can be null here since we are not showing any
          // next/previous links
          panel.add(new PatchLink.SideBySide(
              PatchTable.getDisplayFileName(patchKey), null, patchKey, 0, null, null));
          priorFile = fn;
        }

        final CommentEditorPanel editor =
            new CommentEditorPanel(c, commentLinkProcessor);
        if (c.getLine() == AbstractPatchContentTable.R_HEAD) {
          editor.setAuthorNameText(Gerrit.getUserAccountInfo(),
              Util.C.fileCommentHeader());
        } else {
          editor.setAuthorNameText(Gerrit.getUserAccountInfo(),
              Util.M.lineHeader(c.getLine()));
        }
        editor.setOpen(true);
        commentEditors.add(editor);
        panel.add(editor);
      }
    }
  }

  private void onSend(final boolean submit) {
    if (commentEditors.isEmpty()) {
      onSend2(submit);
    } else {
      final GerritCallback<VoidResult> afterSaveDraft =
          new GerritCallback<VoidResult>() {
            private int done;

            @Override
            public void onSuccess(final VoidResult result) {
              if (++done == commentEditors.size()) {
                onSend2(submit);
              }
            }
          };
      for (final CommentEditorPanel p : commentEditors) {
        p.saveDraft(afterSaveDraft);
      }
    }
  }

  private void onSend2(final boolean submit) {
    ReviewInput data = ReviewInput.create();
    data.message(ChangeApi.emptyToNull(message.getText().trim()));
    for (final ValueRadioButton b : approvalButtons) {
      if (b.getValue()) {
        data.label(b.label.name(), b.parseValue());
      }
    }

    enableForm(false);
    new RestApi("/changes/")
      .id(String.valueOf(patchSetId.getParentKey().get()))
      .view("revisions").id(patchSetId.get()).view("review")
      .post(data, new GerritCallback<ReviewInput>() {
          @Override
          public void onSuccess(ReviewInput result) {
            if (submit) {
              submit();
            } else {
              saveStateOnUnload = false;
              goChange();
            }
          }

          @Override
          public void onFailure(Throwable caught) {
            super.onFailure(caught);
            enableForm(true);
          }
        });
  }

  private void submit() {
    ChangeApi.submit(
      patchSetId.getParentKey().get(),
      "" + patchSetId.get(),
      new GerritCallback<SubmitInfo>() {
          public void onSuccess(SubmitInfo result) {
            saveStateOnUnload = false;
            goChange();
          }

          @Override
          public void onFailure(Throwable err) {
            if (SubmitFailureDialog.isConflict(err)) {
              new SubmitFailureDialog(err.getMessage()).center();
            } else {
              super.onFailure(err);
            }
            goChange();
          }
        });
  }

  private void goChange() {
    final Change.Id ck = patchSetId.getParentKey();
    Gerrit.display(PageLinks.toChange(ck), new ChangeScreen(ck));
  }

  private List<PatchLineComment> draftList() {
    List<PatchLineComment> d = new ArrayList<>();
    List<String> paths = new ArrayList<>(drafts.keySet());
    Collections.sort(paths);
    for (String path : paths) {
      JsArray<CommentInfo> comments = drafts.get(path);
      for (int i = 0; i < comments.length(); i++) {
        d.add(CommentEditorPanel.toComment(patchSetId, path, comments.get(i)));
      }
    }
    return d;
  }

  private static class ValueRadioButton extends RadioButton {
    final LabelInfo label;
    final String value;

    ValueRadioButton(LabelInfo label, String value) {
      super(label.name());
      this.label = label;
      this.value = value;
    }

    String format() {
      return new StringBuilder().append(value).append(' ')
          .append(label.value_text(value)).toString();
    }

    short parseValue() {
      String value = this.value;
      if (value.startsWith(" ") || value.startsWith("+")) {
        value = value.substring(1);
      }
      return Short.parseShort(value);
    }
  }

  private static class SavedState {
    final PatchSet.Id patchSetId;
    final String message;
    final Map<String, String> approvals;

    SavedState(final PublishCommentScreen p) {
      patchSetId = p.patchSetId;
      message = p.message.getText();
      approvals = new HashMap<>();
      for (final ValueRadioButton b : p.approvalButtons) {
        if (b.getValue()) {
          approvals.put(b.label.name(), b.value);
        }
      }
    }
  }
}
