// Copyright (C) 2008 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.Dispatcher;
import com.google.gerrit.client.FormatUtil;
import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.GitwebLink;
import com.google.gerrit.client.download.DownloadPanel;
import com.google.gerrit.client.patches.PatchUtil;
import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gerrit.client.ui.AccountLinkPanel;
import com.google.gerrit.client.ui.CommentedActionDialog;
import com.google.gerrit.client.ui.ComplexDisclosurePanel;
import com.google.gerrit.client.ui.ListenableAccountDiffPreference;
import com.google.gerrit.common.PageLinks;
import com.google.gerrit.common.data.ChangeDetail;
import com.google.gerrit.common.data.PatchSetDetail;
import com.google.gerrit.reviewdb.client.AccountDiffPreference;
import com.google.gerrit.reviewdb.client.AccountGeneralPreferences.DownloadCommand;
import com.google.gerrit.reviewdb.client.AccountGeneralPreferences.DownloadScheme;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.PatchSetInfo;
import com.google.gerrit.reviewdb.client.UserIdentity;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.logical.shared.OpenEvent;
import com.google.gwt.event.logical.shared.OpenHandler;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DisclosurePanel;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.FocusWidget;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
import com.google.gwt.user.client.ui.InlineLabel;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwtjsonrpc.common.VoidResult;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

class PatchSetComplexDisclosurePanel extends ComplexDisclosurePanel
    implements OpenHandler<DisclosurePanel> {
  private static final int R_AUTHOR = 0;
  private static final int R_COMMITTER = 1;
  private static final int R_PARENTS = 2;
  private static final int R_DOWNLOAD = 3;
  private static final int R_CNT = 4;

  private final ChangeDetailCache detailCache;
  private final ChangeDetail changeDetail;
  private final PatchSet patchSet;
  private final FlowPanel body;

  private Grid infoTable;
  private Panel actionsPanel;
  private PatchTable patchTable;
  private final Set<ClickHandler> registeredClickHandler =  new HashSet<ClickHandler>();

  private PatchSet.Id diffBaseId;

  /**
   * Creates a closed complex disclosure panel for a patch set.
   * The patch set details are loaded when the complex disclosure panel is opened.
   */
  public PatchSetComplexDisclosurePanel(final PatchSet ps, boolean isOpen,
      boolean hasDraftComments) {
    super(Util.M.patchSetHeader(ps.getPatchSetId()), isOpen);
    detailCache = ChangeCache.get(ps.getId().getParentKey()).getChangeDetailCache();
    changeDetail = detailCache.get();
    patchSet = ps;

    body = new FlowPanel();
    setContent(body);

    if (hasDraftComments) {
      final Image draftComments = new Image(Gerrit.RESOURCES.draftComments());
      draftComments.setTitle(Util.C.patchSetWithDraftCommentsToolTip());
      getHeader().add(draftComments);
    }

    final GitwebLink gw = Gerrit.getGitwebLink();
    final InlineLabel revtxt = new InlineLabel(ps.getRevision().get() + " ");
    revtxt.addStyleName(Gerrit.RESOURCES.css().patchSetRevision());
    getHeader().add(revtxt);
    if (gw != null && gw.canLink(ps)) {
      final Anchor revlink =
          new Anchor(gw.getLinkName(), false, gw.toRevision(changeDetail.getChange()
              .getProject(), ps));
      revlink.addStyleName(Gerrit.RESOURCES.css().patchSetLink());
      getHeader().add(revlink);
    }

    if (ps.isDraft()) {
      final InlineLabel draftLabel = new InlineLabel(Util.C.draftPatchSetLabel());
      draftLabel.addStyleName(Gerrit.RESOURCES.css().patchSetRevision());
      getHeader().add(draftLabel);
    }

    if (isOpen) {
      ensureLoaded(changeDetail.getCurrentPatchSetDetail());
    } else {
      addOpenHandler(this);
    }

  }

  public void setDiffBaseId(PatchSet.Id diffBaseId) {
    this.diffBaseId = diffBaseId;
  }

  /**
   * Display the table showing the Author, Committer and Download links,
   * followed by the action buttons.
   */
  public void ensureLoaded(final PatchSetDetail detail) {
    loadInfoTable(detail);
    loadActionPanel(detail);
    loadPatchTable(detail);
  }

  public void loadInfoTable(final PatchSetDetail detail) {
    infoTable = new Grid(R_CNT, 2);
    infoTable.setStyleName(Gerrit.RESOURCES.css().infoBlock());
    infoTable.addStyleName(Gerrit.RESOURCES.css().patchSetInfoBlock());

    initRow(R_AUTHOR, Util.C.patchSetInfoAuthor());
    initRow(R_COMMITTER, Util.C.patchSetInfoCommitter());
    initRow(R_PARENTS, Util.C.patchSetInfoParents());
    initRow(R_DOWNLOAD, Util.C.patchSetInfoDownload());

    final CellFormatter itfmt = infoTable.getCellFormatter();
    itfmt.addStyleName(0, 0, Gerrit.RESOURCES.css().topmost());
    itfmt.addStyleName(0, 1, Gerrit.RESOURCES.css().topmost());
    itfmt.addStyleName(R_CNT - 1, 0, Gerrit.RESOURCES.css().bottomheader());
    itfmt.addStyleName(R_AUTHOR, 1, Gerrit.RESOURCES.css().useridentity());
    itfmt.addStyleName(R_COMMITTER, 1, Gerrit.RESOURCES.css().useridentity());
    itfmt.addStyleName(R_DOWNLOAD, 1, Gerrit.RESOURCES.css()
        .downloadLinkListCell());

    final PatchSetInfo info = detail.getInfo();
    displayUserIdentity(R_AUTHOR, info.getAuthor());
    displayUserIdentity(R_COMMITTER, info.getCommitter());
    displayParents(info.getParents());
    displayDownload();

    body.add(infoTable);
  }

  public void loadActionPanel(final PatchSetDetail detail) {
    if (!patchSet.getId().equals(diffBaseId)) {
      actionsPanel = new FlowPanel();
      actionsPanel.setStyleName(Gerrit.RESOURCES.css().patchSetActions());
      actionsPanel.setVisible(true);
      if (Gerrit.isSignedIn()) {
        if (changeDetail.canEdit()) {
          populateReviewAction();
          if (changeDetail.isCurrentPatchSet(detail)) {
            populateActions(detail);
          }
        }
        if (detail.getPatchSet().isDraft()) {
          if (changeDetail.canPublish()) {
            populatePublishAction();
          }
          if (changeDetail.canDeleteDraft()
              && changeDetail.getPatchSets().size() > 1) {
            populateDeleteDraftPatchSetAction();
          }
        }
      }
      body.add(actionsPanel);
    }
  }

  public void loadPatchTable(final PatchSetDetail detail) {
    if (!patchSet.getId().equals(diffBaseId)) {
      patchTable = new PatchTable();
      patchTable.setSavePointerId("PatchTable " + patchSet.getId());
      patchTable.display(diffBaseId, detail);
      for (ClickHandler clickHandler : registeredClickHandler) {
        patchTable.addClickHandler(clickHandler);
      }
      patchTable.setRegisterKeys(true);
      setActive(true);
      body.add(patchTable);
    }
  }

  public class ChangeDownloadPanel extends DownloadPanel {
    public ChangeDownloadPanel(String project, String ref, boolean allowAnonymous) {
      super(project, ref, allowAnonymous);
    }

    @Override
    public void populateDownloadCommandLinks() {
      // This site prefers usage of the 'repo' tool, so suggest
      // that for easy fetch.
      //
      if (allowedSchemes.contains(DownloadScheme.REPO_DOWNLOAD)) {
        commands.add(cmdLinkfactory.new RepoCommandLink(projectName,
            changeDetail.getChange().getChangeId() + "/"
            + patchSet.getPatchSetId()));
      }

      if (!urls.isEmpty()) {
        if (allowedCommands.contains(DownloadCommand.CHECKOUT)
            || allowedCommands.contains(DownloadCommand.DEFAULT_DOWNLOADS)) {
          commands.add(cmdLinkfactory.new CheckoutCommandLink());
        }
        if (allowedCommands.contains(DownloadCommand.PULL)
            || allowedCommands.contains(DownloadCommand.DEFAULT_DOWNLOADS)) {
          commands.add(cmdLinkfactory.new PullCommandLink());
        }
        if (allowedCommands.contains(DownloadCommand.CHERRY_PICK)
            || allowedCommands.contains(DownloadCommand.DEFAULT_DOWNLOADS)) {
          commands.add(cmdLinkfactory.new CherryPickCommandLink());
        }
        if (allowedCommands.contains(DownloadCommand.FORMAT_PATCH)
            || allowedCommands.contains(DownloadCommand.DEFAULT_DOWNLOADS)) {
          commands.add(cmdLinkfactory.new FormatPatchCommandLink());
        }
      }
    }
  }

  private void displayDownload() {
    ChangeDownloadPanel dp = new ChangeDownloadPanel(
      changeDetail.getChange().getProject().get(),
      patchSet.getRefName(),
      changeDetail.isAllowsAnonymous());

    infoTable.setWidget(R_DOWNLOAD, 1, dp);
  }

  private void displayUserIdentity(final int row, final UserIdentity who) {
    if (who == null) {
      infoTable.clearCell(row, 1);
      return;
    }

    final FlowPanel fp = new FlowPanel();
    fp.setStyleName(Gerrit.RESOURCES.css().patchSetUserIdentity());
    if (who.getName() != null) {
      if (who.getAccount() != null) {
        fp.add(new AccountLinkPanel(who));
      } else {
        final InlineLabel lbl = new InlineLabel(who.getName());
        lbl.setStyleName(Gerrit.RESOURCES.css().accountName());
        fp.add(lbl);
      }
    }
    if (who.getEmail() != null) {
      fp.add(new InlineLabel("<" + who.getEmail() + ">"));
    }
    if (who.getDate() != null) {
      fp.add(new InlineLabel(FormatUtil.mediumFormat(who.getDate())));
    }
    infoTable.setWidget(row, 1, fp);
  }

  private void displayParents(final List<PatchSetInfo.ParentInfo> parents) {
    if (parents.size() == 0) {
      infoTable.setWidget(R_PARENTS, 1, new InlineLabel(Util.C.initialCommit()));
      return;
    }
    final Grid parentsTable = new Grid(parents.size(), 2);

    parentsTable.setStyleName(Gerrit.RESOURCES.css().parentsTable());
    parentsTable.addStyleName(Gerrit.RESOURCES.css().noborder());
    final CellFormatter ptfmt = parentsTable.getCellFormatter();
    int row = 0;
    for (PatchSetInfo.ParentInfo parent : parents) {
      parentsTable.setWidget(row, 0, new InlineLabel(parent.id.get()));
      ptfmt.addStyleName(row, 0, Gerrit.RESOURCES.css().noborder());
      ptfmt.addStyleName(row, 0, Gerrit.RESOURCES.css().monospace());
      parentsTable.setWidget(row, 1,
          new InlineLabel(Util.cropSubject(parent.shortMessage)));
      ptfmt.addStyleName(row, 1, Gerrit.RESOURCES.css().noborder());
      row++;
    }
    infoTable.setWidget(R_PARENTS, 1, parentsTable);
  }

  private void populateActions(final PatchSetDetail detail) {
    final boolean isOpen = changeDetail.getChange().getStatus().isOpen();

    if (isOpen && changeDetail.canSubmit()) {
      final Button b =
          new Button(Util.M
              .submitPatchSet(detail.getPatchSet().getPatchSetId()));
      if (Gerrit.getConfig().testChangeMerge()) {
        b.setEnabled(changeDetail.getChange().isMergeable());
      }

      b.addClickHandler(new ClickHandler() {
        @Override
        public void onClick(final ClickEvent event) {
          b.setEnabled(false);
          ChangeApi.submit(
              patchSet.getId().getParentKey().get(),
              patchSet.getRevision().get(),
              new GerritCallback<SubmitInfo>() {
                  public void onSuccess(SubmitInfo result) {
                    redisplay();
                  }

                  public void onFailure(Throwable err) {
                    if (SubmitFailureDialog.isConflict(err)) {
                      new SubmitFailureDialog(err.getMessage()).center();
                      redisplay();
                    } else {
                      b.setEnabled(true);
                      super.onFailure(err);
                    }
                  }

                  private void redisplay() {
                    Gerrit.display(
                        PageLinks.toChange(patchSet.getId().getParentKey()),
                        new ChangeScreen(patchSet.getId().getParentKey()));
                  }
              });
        }
      });
      actionsPanel.add(b);
    }

    if (changeDetail.canRevert()) {
      final Button b = new Button(Util.C.buttonRevertChangeBegin());
      b.addClickHandler(new ClickHandler() {
        @Override
        public void onClick(final ClickEvent event) {
          b.setEnabled(false);
          new ActionDialog(b, true, Util.C.revertChangeTitle(),
              Util.C.headingRevertMessage()) {
            {
              sendButton.setText(Util.C.buttonRevertChangeSend());
              message.setText(Util.M.revertChangeDefaultMessage(
                  detail.getInfo().getSubject(),
                  detail.getPatchSet().getRevision().get())
              );
            }

            @Override
            public void onSend() {
              ChangeApi.revert(changeDetail.getChange().getChangeId(),
                  getMessageText(), new GerritCallback<ChangeInfo>() {
                    @Override
                    public void onSuccess(ChangeInfo result) {
                      sent = true;
                      Gerrit.display(PageLinks.toChange(new Change.Id(result
                          ._number())));
                      hide();
                    }

                    @Override
                    public void onFailure(Throwable caught) {
                      enableButtons(true);
                      super.onFailure(caught);
                    }
                  });
            }
          }.center();
        }
      });
      actionsPanel.add(b);
    }

    if (changeDetail.canAbandon()) {
      final Button b = new Button(Util.C.buttonAbandonChangeBegin());
      b.addClickHandler(new ClickHandler() {
        @Override
        public void onClick(final ClickEvent event) {
          b.setEnabled(false);
          new ActionDialog(b, false, Util.C.abandonChangeTitle(),
              Util.C.headingAbandonMessage()) {
            {
              sendButton.setText(Util.C.buttonAbandonChangeSend());
            }

            @Override
            public void onSend() {
              // TODO: once the other users of ActionDialog have converted to
              // REST APIs, we can use createCallback() rather than providing
              // them directly.
              ChangeApi.abandon(changeDetail.getChange().getChangeId(),
                  getMessageText(), new GerritCallback<ChangeInfo>() {
                    @Override
                    public void onSuccess(ChangeInfo result) {
                      sent = true;
                      Gerrit.display(PageLinks.toChange(new Change.Id(result
                          ._number())));
                      hide();
                    }

                    @Override
                    public void onFailure(Throwable caught) {
                      enableButtons(true);
                      super.onFailure(caught);
                    }
                  });
            }
          }.center();
        }
      });
      actionsPanel.add(b);
    }

    if (changeDetail.getChange().getStatus() == Change.Status.DRAFT
        && changeDetail.canDeleteDraft()) {
      final Button b = new Button(Util.C.buttonDeleteDraftChange());
      b.addClickHandler(new ClickHandler() {
        @Override
        public void onClick(final ClickEvent event) {
          b.setEnabled(false);
          Util.MANAGE_SVC.deleteDraftChange(patchSet.getId(),
              new GerritCallback<VoidResult>() {
                public void onSuccess(VoidResult result) {
                  Gerrit.display(PageLinks.MINE);
                }

                @Override
                public void onFailure(Throwable caught) {
                  b.setEnabled(true);
                  super.onFailure(caught);
                }
              });
        }
      });
      actionsPanel.add(b);
    }

    if (changeDetail.canRestore()) {
      final Button b = new Button(Util.C.buttonRestoreChangeBegin());
      b.addClickHandler(new ClickHandler() {
        @Override
        public void onClick(final ClickEvent event) {
          b.setEnabled(false);
          new ActionDialog(b, false, Util.C.restoreChangeTitle(),
              Util.C.headingRestoreMessage()) {
            {
              sendButton.setText(Util.C.buttonRestoreChangeSend());
            }

            @Override
            public void onSend() {
              ChangeApi.restore(changeDetail.getChange().getChangeId(),
                  getMessageText(), new GerritCallback<ChangeInfo>() {
                    @Override
                    public void onSuccess(ChangeInfo result) {
                      sent = true;
                      Gerrit.display(PageLinks.toChange(new Change.Id(result
                          ._number())));
                      hide();
                    }

                    @Override
                    public void onFailure(Throwable caught) {
                      enableButtons(true);
                      super.onFailure(caught);
                    }
                  });
            }
          }.center();
        }
      });
      actionsPanel.add(b);
    }

    if (changeDetail.canRebase()) {
      final Button b = new Button(Util.C.buttonRebaseChange());
      b.addClickHandler(new ClickHandler() {
        @Override
        public void onClick(final ClickEvent event) {
          b.setEnabled(false);
          Util.MANAGE_SVC.rebaseChange(patchSet.getId(),
              new ChangeDetailCache.GerritWidgetCallback(b));
        }
      });
      actionsPanel.add(b);
    }
  }

  private void populateReviewAction() {
    final Button b = new Button(Util.C.buttonReview());
    b.addClickHandler(new ClickHandler() {
      @Override
      public void onClick(final ClickEvent event) {
        Gerrit.display(Dispatcher.toPublish(patchSet.getId()));
      }
    });
    actionsPanel.add(b);
  }

  private void populatePublishAction() {
    final Button b = new Button(Util.C.buttonPublishPatchSet());
    b.addClickHandler(new ClickHandler() {
      @Override
      public void onClick(final ClickEvent event) {
        b.setEnabled(false);
        Util.MANAGE_SVC.publish(patchSet.getId(),
            new ChangeDetailCache.GerritWidgetCallback(b));
      }
    });
    actionsPanel.add(b);
  }

  private void populateDeleteDraftPatchSetAction() {
    final Button b = new Button(Util.C.buttonDeleteDraftPatchSet());
    b.addClickHandler(new ClickHandler() {
      @Override
      public void onClick(final ClickEvent event) {
        b.setEnabled(false);
        PatchUtil.DETAIL_SVC.deleteDraftPatchSet(patchSet.getId(),
            new ChangeDetailCache.GerritWidgetCallback(b) {
              public void onSuccess(final ChangeDetail result) {
                if (result != null) {
                  detailCache.set(result);
                } else {
                  Gerrit.display(PageLinks.MINE);
                }
              }
            });
      }
    });
    actionsPanel.add(b);
  }

  public void refresh() {
    if (patchSet.getId().equals(diffBaseId)) {
      if (patchTable != null) {
        patchTable.setVisible(false);
      }
      if (actionsPanel != null) {
        actionsPanel.setVisible(false);
      }
    } else {
      if (patchTable != null) {
        if (patchTable.getBase() == null && diffBaseId == null
            || patchTable.getBase() != null
            && patchTable.getBase().equals(diffBaseId)) {
          actionsPanel.setVisible(true);
          patchTable.setVisible(true);
          return;
        }
      }

      AccountDiffPreference diffPrefs;
      if (patchTable == null) {
        diffPrefs = new ListenableAccountDiffPreference().get();
      } else {
        diffPrefs = patchTable.getPreferences().get();
        patchTable.setVisible(false);
      }

      Util.DETAIL_SVC.patchSetDetail2(diffBaseId, patchSet.getId(), diffPrefs,
          new GerritCallback<PatchSetDetail>() {
            @Override
            public void onSuccess(PatchSetDetail result) {
              if (actionsPanel != null) {
                actionsPanel.setVisible(true);
              } else {
                loadActionPanel(result);
              }
              loadPatchTable(result);
            }
          });
    }
  }

  @Override
  public void onOpen(final OpenEvent<DisclosurePanel> event) {
    if (infoTable == null) {
      AccountDiffPreference diffPrefs;
      if (diffBaseId == null) {
        diffPrefs = null;
      } else {
        diffPrefs = new ListenableAccountDiffPreference().get();
      }

      Util.DETAIL_SVC.patchSetDetail2(diffBaseId, patchSet.getId(), diffPrefs,
          new GerritCallback<PatchSetDetail>() {
            public void onSuccess(final PatchSetDetail result) {
              loadInfoTable(result);
              loadActionPanel(result);
            }
          });
    }
  }

  private void initRow(final int row, final String name) {
    infoTable.setText(row, 0, name);
    infoTable.getCellFormatter().addStyleName(row, 0,
        Gerrit.RESOURCES.css().header());
  }

  public PatchSet getPatchSet() {
    return patchSet;
  }

  /**
   * Adds a click handler to the patch table.
   * If the patch table is not yet initialized it is guaranteed that the click handler
   * is added to the patch table after initialization.
   */
  public void addClickHandler(final ClickHandler clickHandler) {
    registeredClickHandler.add(clickHandler);
    if (patchTable != null) {
      patchTable.addClickHandler(clickHandler);
    }
  }

  /** Activates / Deactivates the key navigation and the highlighting of the current row for the patch table */
  public void setActive(boolean active) {
    if (patchTable != null) {
      patchTable.setActive(active);
    }
  }

  private abstract class ActionDialog extends CommentedActionDialog<ChangeDetail> {
    public ActionDialog(final FocusWidget enableOnFailure, final boolean redirect,
        String dialogTitle, String dialogHeading) {
      super(dialogTitle, dialogHeading, new ChangeDetailCache.IgnoreErrorCallback() {
          @Override
          public void onSuccess(ChangeDetail result) {
            if (redirect) {
              Gerrit.display(PageLinks.toChange(result.getChange().getId()));
            } else {
              super.onSuccess(result);
            }
          }

          @Override
          public void onFailure(Throwable caught) {
            enableOnFailure.setEnabled(true);
          }
        });
    }
  }
}
