// 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.Gerrit;
import com.google.gerrit.client.actions.ActionButton;
import com.google.gerrit.client.info.ActionInfo;
import com.google.gerrit.client.info.ChangeInfo;
import com.google.gerrit.client.info.ChangeInfo.CommitInfo;
import com.google.gerrit.client.info.ChangeInfo.RevisionInfo;
import com.google.gerrit.client.rpc.NativeMap;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
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.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
import java.util.TreeSet;

class Actions extends Composite {
  private static final String[] CORE = {
    "abandon",
    "assignee",
    "cherrypick",
    "description",
    "followup",
    "hashtags",
    "publish",
    "rebase",
    "restore",
    "revert",
    "submit",
    "topic",
    "private",
    "/",
  };

  interface Binder extends UiBinder<FlowPanel, Actions> {}

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

  @UiField Button cherrypick;
  @UiField Button rebase;
  @UiField Button revert;
  @UiField Button submit;

  @UiField Button abandon;
  private AbandonAction abandonAction;

  @UiField Button deleteChange;

  @UiField Button markPrivate;
  @UiField Button unmarkPrivate;

  @UiField Button restore;
  private RestoreAction restoreAction;

  @UiField Button followUp;
  private FollowUpAction followUpAction;

  private Change.Id changeId;
  private ChangeInfo changeInfo;
  private String revision;
  private String project;
  private String topic;
  private String subject;
  private String message;
  private String branch;
  private String key;

  private boolean rebaseParentNotCurrent = true;

  Actions() {
    initWidget(uiBinder.createAndBindUi(this));
    getElement().setId("change_actions");
  }

  void display(ChangeInfo info, String revision) {
    this.revision = revision;

    boolean hasUser = Gerrit.isSignedIn();
    RevisionInfo revInfo = info.revision(revision);
    CommitInfo commit = revInfo.commit();
    changeId = info.legacyId();
    project = info.project();
    topic = info.topic();
    subject = commit.subject();
    message = commit.message();
    branch = info.branch();
    key = info.changeId();
    changeInfo = info;

    initChangeActions(info, hasUser);

    NativeMap<ActionInfo> actionMap =
        revInfo.hasActions() ? revInfo.actions() : NativeMap.<ActionInfo>create();
    actionMap.copyKeysIntoChildren("id");
    reloadRevisionActions(actionMap);
  }

  private void initChangeActions(ChangeInfo info, boolean hasUser) {
    NativeMap<ActionInfo> actions =
        info.hasActions() ? info.actions() : NativeMap.<ActionInfo>create();
    actions.copyKeysIntoChildren("id");

    if (hasUser) {
      a2b(actions, "abandon", abandon);
      a2b(actions, "/", deleteChange);
      a2b(actions, "restore", restore);
      a2b(actions, "revert", revert);
      a2b(actions, "followup", followUp);
      if (info.isPrivate()) {
        a2b(actions, "private", unmarkPrivate);
      } else {
        a2b(actions, "private", markPrivate);
      }
      for (String id : filterNonCore(actions)) {
        add(new ActionButton(info, actions.get(id)));
      }
    }
  }

  void reloadRevisionActions(NativeMap<ActionInfo> actions) {
    if (!Gerrit.isSignedIn()) {
      return;
    }
    boolean canSubmit = actions.containsKey("submit");
    if (canSubmit) {
      ActionInfo action = actions.get("submit");
      submit.setTitle(action.title());
      submit.setEnabled(action.enabled());
      submit.setHTML(new SafeHtmlBuilder().openDiv().append(action.label()).closeDiv());
      submit.setEnabled(action.enabled());
    }
    submit.setVisible(canSubmit);

    a2b(actions, "cherrypick", cherrypick);
    a2b(actions, "rebase", rebase);

    // The rebase button on change screen is always enabled.
    // It is the "Rebase" button in the RebaseDialog that might be disabled.
    rebaseParentNotCurrent = rebase.isEnabled();
    if (rebase.isVisible()) {
      rebase.setEnabled(true);
    }
    RevisionInfo revInfo = changeInfo.revision(revision);
    for (String id : filterNonCore(actions)) {
      add(new ActionButton(changeInfo, revInfo, actions.get(id)));
    }
  }

  private void add(ActionButton b) {
    ((FlowPanel) getWidget()).add(b);
  }

  private static TreeSet<String> filterNonCore(NativeMap<ActionInfo> m) {
    TreeSet<String> ids = new TreeSet<>(m.keySet());
    for (String id : CORE) {
      ids.remove(id);
    }
    return ids;
  }

  @UiHandler("followUp")
  void onFollowUp(@SuppressWarnings("unused") ClickEvent e) {
    if (followUpAction == null) {
      followUpAction = new FollowUpAction(followUp, project, branch, topic, key);
    }
    followUpAction.show();
  }

  @UiHandler("abandon")
  void onAbandon(@SuppressWarnings("unused") ClickEvent e) {
    if (abandonAction == null) {
      abandonAction = new AbandonAction(abandon, changeId);
    }
    abandonAction.show();
  }

  @UiHandler("deleteChange")
  void onDeleteChange(@SuppressWarnings("unused") ClickEvent e) {
    if (Window.confirm(Resources.C.deleteChange())) {
      ChangeActions.delete(changeId, deleteChange);
    }
  }

  @UiHandler("markPrivate")
  void onMarkPrivate(@SuppressWarnings("unused") ClickEvent e) {
    ChangeActions.markPrivate(changeId, markPrivate);
  }

  @UiHandler("unmarkPrivate")
  void onUnmarkPrivate(@SuppressWarnings("unused") ClickEvent e) {
    ChangeActions.unmarkPrivate(changeId, unmarkPrivate);
  }

  @UiHandler("restore")
  void onRestore(@SuppressWarnings("unused") ClickEvent e) {
    if (restoreAction == null) {
      restoreAction = new RestoreAction(restore, changeId);
    }
    restoreAction.show();
  }

  @UiHandler("rebase")
  void onRebase(@SuppressWarnings("unused") ClickEvent e) {
    RebaseAction.call(
        rebase, project, changeInfo.branch(), changeId, revision, rebaseParentNotCurrent);
  }

  @UiHandler("submit")
  void onSubmit(@SuppressWarnings("unused") ClickEvent e) {
    SubmitAction.call(changeInfo, changeInfo.revision(revision));
  }

  @UiHandler("cherrypick")
  void onCherryPick(@SuppressWarnings("unused") ClickEvent e) {
    CherryPickAction.call(cherrypick, changeInfo, revision, project, message);
  }

  @UiHandler("revert")
  void onRevert(@SuppressWarnings("unused") ClickEvent e) {
    RevertAction.call(revert, changeId, revision, subject);
  }

  private static void a2b(NativeMap<ActionInfo> actions, String a, Button b) {
    if (actions.containsKey(a)) {
      b.setVisible(true);
      ActionInfo actionInfo = actions.get(a);
      b.setTitle(actionInfo.title());
      b.setEnabled(actionInfo.enabled());
    }
  }
}
