// Copyright (C) 2016 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.FormatUtil;
import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.NotSignedInDialog;
import com.google.gerrit.client.changes.ChangeApi;
import com.google.gerrit.client.changes.Util;
import com.google.gerrit.client.info.AccountInfo;
import com.google.gerrit.client.info.ChangeInfo;
import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gerrit.client.ui.InlineHyperlink;
import com.google.gerrit.client.ui.RemoteSuggestBox;
import com.google.gerrit.common.PageLinks;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gwt.core.client.GWT;
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.logical.shared.CloseEvent;
import com.google.gwt.event.logical.shared.CloseHandler;
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.DOM;
import com.google.gwt.user.client.EventListener;
import com.google.gwt.user.client.rpc.StatusCodeException;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.UIObject;

/** Edit assignee using auto-completion. */
public class Assignee extends Composite {
  interface Binder extends UiBinder<HTMLPanel, Assignee> {}

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

  @UiField Element show;
  @UiField InlineHyperlink assigneeLink;
  @UiField Image editAssigneeIcon;
  @UiField Element form;
  @UiField Element error;

  @UiField(provided = true)
  RemoteSuggestBox suggestBox;

  private AssigneeSuggestOracle assigneeSuggestOracle;
  private Change.Id changeId;
  private Project.NameKey project;
  private boolean canEdit;
  private AccountInfo currentAssignee;

  Assignee() {
    assigneeSuggestOracle = new AssigneeSuggestOracle();
    suggestBox = new RemoteSuggestBox(assigneeSuggestOracle);
    suggestBox.setVisibleLength(55);
    suggestBox.setHintText(Util.C.approvalTableEditAssigneeHint());
    suggestBox.addCloseHandler(
        new CloseHandler<RemoteSuggestBox>() {
          @Override
          public void onClose(CloseEvent<RemoteSuggestBox> event) {
            Assignee.this.onCancel(null);
          }
        });
    suggestBox.addSelectionHandler(
        new SelectionHandler<String>() {
          @Override
          public void onSelection(SelectionEvent<String> event) {
            editAssignee(event.getSelectedItem());
          }
        });

    initWidget(uiBinder.createAndBindUi(this));
    editAssigneeIcon.addDomHandler(
        new ClickHandler() {
          @Override
          public void onClick(ClickEvent event) {
            onOpenForm();
          }
        },
        ClickEvent.getType());
  }

  void set(ChangeInfo info) {
    this.changeId = info.legacyId();
    this.project = info.projectNameKey();
    this.canEdit = info.hasActions() && info.actions().containsKey("assignee");
    assigneeSuggestOracle.setChange(info);
    setAssignee(info.assignee());
    editAssigneeIcon.setVisible(canEdit);
    if (!canEdit) {
      show.setTitle(null);
    }
  }

  void onOpenForm() {
    UIObject.setVisible(form, true);
    UIObject.setVisible(show, false);
    UIObject.setVisible(error, false);
    editAssigneeIcon.setVisible(false);
    suggestBox.setFocus(true);
    if (currentAssignee != null) {
      suggestBox.setText(FormatUtil.nameEmail(currentAssignee));
      suggestBox.selectAll();
    } else {
      suggestBox.setText("");
    }
  }

  void onCloseForm() {
    UIObject.setVisible(form, false);
    UIObject.setVisible(show, true);
    UIObject.setVisible(error, false);
    editAssigneeIcon.setVisible(true);
    suggestBox.setFocus(false);
  }

  @UiHandler("assign")
  void onEditAssignee(@SuppressWarnings("unused") ClickEvent e) {
    if (canEdit) {
      editAssignee(suggestBox.getText());
    }
  }

  @UiHandler("cancel")
  void onCancel(@SuppressWarnings("unused") ClickEvent e) {
    onCloseForm();
  }

  private void editAssignee(String assignee) {
    if (assignee.trim().isEmpty()) {
      ChangeApi.deleteAssignee(
          project.get(),
          changeId.get(),
          new GerritCallback<AccountInfo>() {
            @Override
            public void onSuccess(AccountInfo result) {
              onCloseForm();
              setAssignee(null);
            }

            @Override
            public void onFailure(Throwable err) {
              if (isSigninFailure(err)) {
                new NotSignedInDialog().center();
              } else {
                UIObject.setVisible(error, true);
                error.setInnerText(
                    err instanceof StatusCodeException
                        ? ((StatusCodeException) err).getEncodedResponse()
                        : err.getMessage());
              }
            }
          });
    } else {
      ChangeApi.setAssignee(
          project.get(),
          changeId.get(),
          assignee,
          new GerritCallback<AccountInfo>() {
            @Override
            public void onSuccess(AccountInfo result) {
              onCloseForm();
              setAssignee(result);
              Reviewers reviewers = getReviewers();
              if (reviewers != null) {
                reviewers.updateReviewerList();
              }
            }

            @Override
            public void onFailure(Throwable err) {
              if (isSigninFailure(err)) {
                new NotSignedInDialog().center();
              } else {
                UIObject.setVisible(error, true);
                error.setInnerText(
                    err instanceof StatusCodeException
                        ? ((StatusCodeException) err).getEncodedResponse()
                        : err.getMessage());
              }
            }
          });
    }
  }

  private void setAssignee(AccountInfo assignee) {
    currentAssignee = assignee;
    assigneeLink.setText(assignee != null ? getName(assignee) : null);
    assigneeLink.setTargetHistoryToken(
        assignee != null
            ? PageLinks.toAssigneeQuery(
                assignee.name() != null
                    ? assignee.name()
                    : assignee.email() != null
                        ? assignee.email()
                        : String.valueOf(assignee._accountId()))
            : "");
  }

  private Reviewers getReviewers() {
    Element e = DOM.getParent(getElement());
    for (e = DOM.getParent(e); e != null; e = DOM.getParent(e)) {
      EventListener l = DOM.getEventListener(e);
      if (l instanceof ChangeScreen) {
        ChangeScreen screen = (ChangeScreen) l;
        return screen.reviewers;
      }
    }
    return null;
  }

  private String getName(AccountInfo info) {
    if (info.name() != null) {
      return info.name();
    }
    if (info.email() != null) {
      return info.email();
    }
    return Gerrit.info().user().anonymousCowardName();
  }
}
