// 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 com.google.gerrit.client.ConfirmationCallback;
import com.google.gerrit.client.ConfirmationDialog;
import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.account.AccountInfo;
import com.google.gerrit.client.changes.ChangeApi;
import com.google.gerrit.client.changes.ChangeInfo;
import com.google.gerrit.client.changes.ChangeInfo.ApprovalInfo;
import com.google.gerrit.client.changes.ChangeInfo.LabelInfo;
import com.google.gerrit.client.changes.Util;
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.ui.HintTextBox;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.dom.client.Element;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyDownEvent;
import com.google.gwt.event.dom.client.KeyDownHandler;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.event.logical.shared.SelectionHandler;
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.StatusCodeException;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.SuggestBox;
import com.google.gwt.user.client.ui.SuggestBox.DefaultSuggestionDisplay;
import com.google.gwt.user.client.ui.SuggestOracle.Suggestion;
import com.google.gwt.user.client.ui.UIObject;
import com.google.gwtexpui.safehtml.client.SafeHtml;
import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

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

  @UiField Element reviewersText;
  @UiField Button openForm;
  @UiField Element form;
  @UiField Element error;
  @UiField(provided = true)
  SuggestBox suggestBox;

  private ChangeScreen2.Style style;
  private Element ccText;

  private RestReviewerSuggestOracle reviewerSuggestOracle;
  private HintTextBox nameTxtBox;
  private Change.Id changeId;
  private boolean submitOnSelection;

  Reviewers() {
    reviewerSuggestOracle = new RestReviewerSuggestOracle();
    nameTxtBox = new HintTextBox();
    suggestBox = new SuggestBox(reviewerSuggestOracle, nameTxtBox);
    initWidget(uiBinder.createAndBindUi(this));

    nameTxtBox.setVisibleLength(55);
    nameTxtBox.setHintText(Util.C.approvalTableAddReviewerHint());
    nameTxtBox.addKeyDownHandler(new KeyDownHandler() {
      @Override
      public void onKeyDown(KeyDownEvent e) {
        submitOnSelection = false;

        if (e.getNativeEvent().getKeyCode() == KeyCodes.KEY_ESCAPE) {
          onCancel(null);
        } else if (e.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
          if (((DefaultSuggestionDisplay) suggestBox.getSuggestionDisplay())
              .isSuggestionListShowing()) {
            submitOnSelection = true;
          } else {
            onAdd(null);
          }
        }
      }
    });
    suggestBox.addSelectionHandler(new SelectionHandler<Suggestion>() {
      @Override
      public void onSelection(SelectionEvent<Suggestion> event) {
        nameTxtBox.setFocus(true);
        if (submitOnSelection) {
          onAdd(null);
        }
      }
    });
  }

  void init(ChangeScreen2.Style style, Element ccText) {
    this.style = style;
    this.ccText = ccText;
  }

  void set(ChangeInfo info) {
    this.changeId = info.legacy_id();
    display(info);
    reviewerSuggestOracle.setChange(changeId);
    openForm.setVisible(Gerrit.isSignedIn());
  }

  @UiHandler("openForm")
  void onOpenForm(ClickEvent e) {
    onOpenForm();
  }

  void onOpenForm() {
    UIObject.setVisible(form, true);
    UIObject.setVisible(error, false);
    openForm.setVisible(false);
    suggestBox.setFocus(true);
  }

  @UiHandler("add")
  void onAdd(ClickEvent e) {
    String reviewer = suggestBox.getText();
    if (!reviewer.isEmpty()) {
      addReviewer(reviewer, false);
    }
  }

  @UiHandler("cancel")
  void onCancel(ClickEvent e) {
    openForm.setVisible(true);
    UIObject.setVisible(form, false);
    suggestBox.setFocus(false);
  }

  private void addReviewer(final String reviewer, boolean confirmed) {
    ChangeApi.reviewers(changeId.get()).post(
        PostInput.create(reviewer, confirmed),
        new GerritCallback<PostResult>() {
          public void onSuccess(PostResult result) {
            nameTxtBox.setEnabled(true);

            if (result.confirm()) {
              askForConfirmation(result.error());
            } else if (result.error() != null) {
              UIObject.setVisible(error, true);
              error.setInnerText(result.error());
            } else {
              UIObject.setVisible(error, false);
              error.setInnerText("");
              nameTxtBox.setText("");

              if (result.reviewers() != null
                  && result.reviewers().length() > 0) {
                updateReviewerList();
              }
            }
          }

          private void askForConfirmation(String text) {
            new ConfirmationDialog(
                Util.C.approvalTableAddManyReviewersConfirmationDialogTitle(),
                new SafeHtmlBuilder().append(text),
                new ConfirmationCallback() {
                  @Override
                  public void onOk() {
                    addReviewer(reviewer, true);
                  }
                }).center();
          }

          @Override
          public void onFailure(Throwable err) {
            UIObject.setVisible(error, true);
            error.setInnerText(err instanceof StatusCodeException
                ? ((StatusCodeException) err).getEncodedResponse()
                : err.getMessage());
            nameTxtBox.setEnabled(true);
          }
        });
  }

  private void updateReviewerList() {
    ChangeApi.detail(changeId.get(),
        new GerritCallback<ChangeInfo>() {
          @Override
          public void onSuccess(ChangeInfo result) {
            display(result);
          }
        });
  }

  private void display(ChangeInfo info) {
    Map<Integer, AccountInfo> r = new HashMap<>();
    Map<Integer, AccountInfo> cc = new HashMap<>();
    for (LabelInfo label : Natives.asList(info.all_labels().values())) {
      if (label.all() != null) {
        for (ApprovalInfo ai : Natives.asList(label.all())) {
          (ai.value() != 0 ? r : cc).put(ai._account_id(), ai);
        }
      }
    }
    for (Integer i : r.keySet()) {
      cc.remove(i);
    }
    r.remove(info.owner()._account_id());
    cc.remove(info.owner()._account_id());

    Set<Integer> removable = new HashSet<>();
    if (info.removable_reviewers() != null) {
      for (AccountInfo a : Natives.asList(info.removable_reviewers())) {
        removable.add(a._account_id());
      }
    }

    Map<Integer, VotableInfo> votable = votable(info);

    SafeHtml rHtml = Labels.formatUserList(style,
        r.values(), removable, votable);
    SafeHtml ccHtml = Labels.formatUserList(style,
        cc.values(), removable, votable);

    reviewersText.setInnerSafeHtml(rHtml);
    ccText.setInnerSafeHtml(ccHtml);
  }

  private static Map<Integer, VotableInfo> votable(ChangeInfo change) {
    Map<Integer, VotableInfo> d = new HashMap<>();
    for (String name : change.labels()) {
      LabelInfo label = change.label(name);
      if (label.all() != null) {
        for (ApprovalInfo ai : Natives.asList(label.all())) {
          int id = ai._account_id();
          VotableInfo ad = d.get(id);
          if (ad == null) {
            ad = new VotableInfo();
            d.put(id, ad);
          }
          if (ai.has_value()) {
            ad.votable(name);
          }
        }
      }
    }
    return d;
  }


  public static class PostInput extends JavaScriptObject {
    public static PostInput create(String reviewer, boolean confirmed) {
      PostInput input = createObject().cast();
      input.init(reviewer, confirmed);
      return input;
    }

    private native void init(String reviewer, boolean confirmed) /*-{
      this.reviewer = reviewer;
      if (confirmed) {
        this.confirmed = true;
      }
    }-*/;

    protected PostInput() {
    }
  }

  public static class ReviewerInfo extends AccountInfo {
    final Set<String> approvals() {
      return Natives.keys(_approvals());
    }
    final native String approval(String l) /*-{ return this.approvals[l]; }-*/;
    private final native NativeMap<NativeString> _approvals() /*-{ return this.approvals; }-*/;

    protected ReviewerInfo() {
    }
  }

  public static class PostResult extends JavaScriptObject {
    public final native JsArray<ReviewerInfo> reviewers() /*-{ return this.reviewers; }-*/;
    public final native boolean confirm() /*-{ return this.confirm || false; }-*/;
    public final native String error() /*-{ return this.error; }-*/;

    protected PostResult() {
    }
  }
}
