// 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.AccountLink;
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.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) {
    super(Util.M.patchSetHeader(ps.getPatchSetId()), isOpen);
    detailCache = ChangeCache.get(ps.getId().getParentKey()).getChangeDetailCache();
    changeDetail = detailCache.get();
    patchSet = ps;

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

    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) {
      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 AccountLink(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);
          }
        });
    }
  }
}
