// 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.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 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.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(final String assignee) {
    if (assignee.trim().isEmpty()) {
      ChangeApi.deleteAssignee(
          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(
          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();
  }
}
