// 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.AvatarImage;
import com.google.gerrit.client.DiffObject;
import com.google.gerrit.client.ErrorDialog;
import com.google.gerrit.client.FormatUtil;
import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.GerritUiExtensionPoint;
import com.google.gerrit.client.NotFoundScreen;
import com.google.gerrit.client.api.ChangeGlue;
import com.google.gerrit.client.api.ExtensionPanel;
import com.google.gerrit.client.changes.ChangeApi;
import com.google.gerrit.client.changes.ChangeList;
import com.google.gerrit.client.changes.CommentInfo;
import com.google.gerrit.client.changes.RevisionInfoCache;
import com.google.gerrit.client.changes.StarredChanges;
import com.google.gerrit.client.changes.Util;
import com.google.gerrit.client.diff.DiffApi;
import com.google.gerrit.client.info.AccountInfo;
import com.google.gerrit.client.info.AccountInfo.AvatarInfo;
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.EditInfo;
import com.google.gerrit.client.info.ChangeInfo.LabelInfo;
import com.google.gerrit.client.info.ChangeInfo.MessageInfo;
import com.google.gerrit.client.info.ChangeInfo.RevisionInfo;
import com.google.gerrit.client.info.FileInfo;
import com.google.gerrit.client.info.GpgKeyInfo;
import com.google.gerrit.client.info.PushCertificateInfo;
import com.google.gerrit.client.projects.ConfigInfoCache;
import com.google.gerrit.client.projects.ConfigInfoCache.Entry;
import com.google.gerrit.client.rpc.CallbackGroup;
import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gerrit.client.rpc.NativeMap;
import com.google.gerrit.client.rpc.Natives;
import com.google.gerrit.client.rpc.RestApi;
import com.google.gerrit.client.rpc.ScreenLoadCallback;
import com.google.gerrit.client.ui.BranchLink;
import com.google.gerrit.client.ui.ChangeLink;
import com.google.gerrit.client.ui.CommentLinkProcessor;
import com.google.gerrit.client.ui.Hyperlink;
import com.google.gerrit.client.ui.InlineHyperlink;
import com.google.gerrit.client.ui.Screen;
import com.google.gerrit.client.ui.UserActivityMonitor;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.common.PageLinks;
import com.google.gerrit.extensions.client.ListChangesOption;
import com.google.gerrit.extensions.client.SubmitType;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Change.Status;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.core.client.JsArrayString;
import com.google.gwt.dom.client.AnchorElement;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.dom.client.SelectElement;
import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.resources.client.CssResource;
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.Event;
import com.google.gwt.user.client.EventListener;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.InlineLabel;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.ToggleButton;
import com.google.gwtexpui.globalkey.client.GlobalKey;
import com.google.gwtexpui.globalkey.client.KeyCommand;
import com.google.gwtexpui.globalkey.client.KeyCommandSet;
import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
import com.google.gwtorm.client.KeyUtil;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.codemirror.lib.CodeMirror;

public class ChangeScreen extends Screen {
  private static final Logger logger = Logger.getLogger(ChangeScreen.class.getName());

  interface Binder extends UiBinder<HTMLPanel, ChangeScreen> {}

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

  interface Style extends CssResource {
    String avatar();

    String hashtagName();

    String hashtagIcon();

    String highlight();

    String labelName();

    String label_may();

    String label_need();

    String label_ok();

    String label_reject();

    String label_user();

    String pushCertStatus();

    String replyBox();

    String selected();

    String notCurrentPatchSet();
  }

  static ChangeScreen get(NativeEvent in) {
    Element e = in.getEventTarget().cast();
    for (e = DOM.getParent(e); e != null; e = DOM.getParent(e)) {
      EventListener l = DOM.getEventListener(e);
      if (l instanceof ChangeScreen) {
        return (ChangeScreen) l;
      }
    }
    return null;
  }

  private final Change.Id changeId;
  @Nullable private Project.NameKey project;
  private DiffObject base;
  private String revision;
  private ChangeInfo changeInfo;
  private boolean hasDraftComments;
  private CommentLinkProcessor commentLinkProcessor;
  private EditInfo edit;
  private LocalComments lc;

  private List<HandlerRegistration> handlers = new ArrayList<>(4);
  private UpdateCheckTimer updateCheck;
  private Timestamp lastDisplayedUpdate;
  private UpdateAvailableBar updateAvailable;
  private boolean openReplyBox;
  private boolean loaded;
  private FileTable.Mode fileTableMode;

  @UiField HTMLPanel headerLine;
  @UiField SimplePanel headerExtension;
  @UiField SimplePanel headerExtensionMiddle;
  @UiField SimplePanel headerExtensionRight;
  @UiField Style style;
  @UiField ToggleButton star;
  @UiField Anchor permalink;

  @UiField Assignee assignee;
  @UiField Element assigneeRow;
  @UiField Element ccText;
  @UiField Reviewers reviewers;
  @UiField Hashtags hashtags;
  @UiField Element hashtagTableRow;

  @UiField FlowPanel ownerPanel;
  @UiField InlineHyperlink ownerLink;

  @UiField Element uploaderRow;
  @UiField FlowPanel uploaderPanel;
  @UiField InlineLabel uploaderName;

  @UiField Element statusText;
  @UiField Element privateText;
  @UiField Element wipText;
  @UiField Image projectSettings;
  @UiField AnchorElement projectSettingsLink;
  @UiField InlineHyperlink projectDashboard;
  @UiField InlineHyperlink branchLink;
  @UiField Element strategy;
  @UiField Element submitActionText;
  @UiField Element notMergeable;
  @UiField Topic topic;
  @UiField Element actionText;
  @UiField Element actionDate;
  @UiField SimplePanel changeExtension;
  @UiField SimplePanel relatedExtension;
  @UiField SimplePanel commitExtension;

  @UiField Actions actions;
  @UiField Labels labels;
  @UiField CommitBox commit;
  @UiField RelatedChanges related;
  @UiField FileTable files;
  @UiField ListBox diffBase;
  @UiField History history;
  @UiField SimplePanel historyExtensionRight;

  @UiField Button includedIn;
  @UiField Button patchSets;
  @UiField Element patchSetsText;
  @UiField Button download;
  @UiField Button reply;
  @UiField Button publishEdit;
  @UiField Button rebaseEdit;
  @UiField Button deleteEdit;
  @UiField Button openAll;
  @UiField Button editMode;
  @UiField Button reviewMode;
  @UiField Button addFile;
  @UiField Button deleteFile;
  @UiField Button renameFile;
  @UiField Button expandAll;
  @UiField Button collapseAll;
  @UiField Button hideTaggedComments;
  @UiField Button showTaggedComments;
  @UiField QuickApprove quickApprove;

  private ReplyAction replyAction;
  private IncludedInAction includedInAction;
  private PatchSetsAction patchSetsAction;
  private DownloadAction downloadAction;
  private AddFileAction addFileAction;
  private DeleteFileAction deleteFileAction;
  private RenameFileAction renameFileAction;

  public ChangeScreen(
      @Nullable Project.NameKey project,
      Change.Id changeId,
      DiffObject base,
      String revision,
      boolean openReplyBox,
      FileTable.Mode mode) {
    this.project = project;
    this.changeId = changeId;
    this.base = base;
    this.revision = normalize(revision);
    this.openReplyBox = openReplyBox;
    this.fileTableMode = mode;
    this.lc = new LocalComments(project, changeId);
    add(uiBinder.createAndBindUi(this));
  }

  public Project.NameKey getProject() {
    return project;
  }

  PatchSet.Id getPatchSetId() {
    return new PatchSet.Id(changeInfo.legacyId(), changeInfo.revisions().get(revision)._number());
  }

  @Override
  protected void onLoad() {
    super.onLoad();
    CallbackGroup group = new CallbackGroup();
    if (Gerrit.isSignedIn()) {
      ChangeList.query(
          "change:" + changeId.get() + " has:draft",
          Collections.<ListChangesOption>emptySet(),
          group.add(
              new AsyncCallback<ChangeList>() {
                @Override
                public void onSuccess(ChangeList result) {
                  hasDraftComments = result.length() > 0;
                }

                @Override
                public void onFailure(Throwable caught) {}
              }));
      ChangeApi.editWithFiles(
          Project.NameKey.asStringOrNull(project),
          changeId.get(),
          group.add(
              new AsyncCallback<EditInfo>() {
                @Override
                public void onSuccess(EditInfo result) {
                  edit = result;
                }

                @Override
                public void onFailure(Throwable caught) {}
              }));
    }
    loadChangeInfo(
        true,
        group.addFinal(
            new GerritCallback<ChangeInfo>() {
              @Override
              public void onSuccess(ChangeInfo info) {
                info.init();
                if (project == null) {
                  // Update Project when the first API call succeeded if it wasn't already present.
                  // This is the case when the user used a URL that doesn't include the project.
                  // Setting it here will rewrite the URL token to include the project (visible to
                  // the user) and all future API calls made from the change screen will use
                  // project/+/changeId to identify the change.
                  project = info.projectNameKey();
                }

                initCurrentRevision(info);
                final RevisionInfo rev = info.revision(revision);
                CallbackGroup group = new CallbackGroup();
                loadCommit(rev, group);

                group.addListener(
                    new GerritCallback<Void>() {
                      @Override
                      public void onSuccess(Void result) {
                        if (base.isBase() && rev.isMerge()) {
                          base =
                              DiffObject.parse(
                                  info.legacyId(),
                                  Gerrit.getUserPreferences().defaultBaseForMerges().getBase());
                        }
                        loadConfigInfo(info, base);
                        JsArray<MessageInfo> mAr = info.messages();
                        for (int i = 0; i < mAr.length(); i++) {
                          if (mAr.get(i).tag() != null) {
                            hideTaggedComments.setVisible(true);
                            break;
                          }
                        }
                      }
                    });
                group.done();
              }
            }));
  }

  private RevisionInfo initCurrentRevision(ChangeInfo info) {
    info.revisions().copyKeysIntoChildren("name");
    if (edit != null) {
      edit.setName(edit.commit().commit());
      info.setEdit(edit);
      if (edit.hasFiles()) {
        edit.files().copyKeysIntoChildren("path");
      }
      info.revisions().put(edit.name(), RevisionInfo.fromEdit(edit));
      JsArray<RevisionInfo> list = info.revisions().values();

      // Edit is converted to a regular revision (with number = 0) and
      // added to the list of revisions. Additionally under certain
      // circumstances change edit is assigned to be the current revision
      // and is selected to be shown on the change screen.
      // We have two different strategies to assign edit to the current ps:
      // 1. revision == null: no revision is selected, so use the edit only
      //    if it is based on the latest patch set
      // 2. edit was selected explicitly from ps drop down:
      //    use the edit regardless of which patch set it is based on
      if (revision == null) {
        RevisionInfo.sortRevisionInfoByNumber(list);
        RevisionInfo rev = list.get(list.length() - 1);
        if (rev.isEdit()) {
          info.setCurrentRevision(rev.name());
        }
      } else if (revision.equals("edit") || revision.equals("0")) {
        for (int i = 0; i < list.length(); i++) {
          RevisionInfo r = list.get(i);
          if (r.isEdit()) {
            info.setCurrentRevision(r.name());
            break;
          }
        }
      }
    }
    return resolveRevisionToDisplay(info);
  }

  private void addExtensionPoints(ChangeInfo change, RevisionInfo rev, Entry result) {
    addExtensionPoint(GerritUiExtensionPoint.CHANGE_SCREEN_HEADER, headerExtension, change, rev);
    addExtensionPoint(
        GerritUiExtensionPoint.CHANGE_SCREEN_HEADER_RIGHT_OF_BUTTONS,
        headerExtensionMiddle,
        change,
        rev);
    addExtensionPoint(
        GerritUiExtensionPoint.CHANGE_SCREEN_HEADER_RIGHT_OF_POP_DOWNS,
        headerExtensionRight,
        change,
        rev);
    addExtensionPoint(
        GerritUiExtensionPoint.CHANGE_SCREEN_BELOW_CHANGE_INFO_BLOCK,
        changeExtension,
        change,
        rev,
        result.getExtensionPanelNames(
            GerritUiExtensionPoint.CHANGE_SCREEN_BELOW_CHANGE_INFO_BLOCK.toString()));
    addExtensionPoint(
        GerritUiExtensionPoint.CHANGE_SCREEN_BELOW_RELATED_INFO_BLOCK,
        relatedExtension,
        change,
        rev);
    addExtensionPoint(
        GerritUiExtensionPoint.CHANGE_SCREEN_BELOW_COMMIT_INFO_BLOCK, commitExtension, change, rev);
    addExtensionPoint(
        GerritUiExtensionPoint.CHANGE_SCREEN_HISTORY_RIGHT_OF_BUTTONS,
        historyExtensionRight,
        change,
        rev);
  }

  private void addExtensionPoint(
      GerritUiExtensionPoint extensionPoint,
      Panel p,
      ChangeInfo change,
      RevisionInfo rev,
      List<String> panelNames) {
    ExtensionPanel extensionPanel = new ExtensionPanel(extensionPoint, panelNames);
    extensionPanel.putObject(GerritUiExtensionPoint.Key.CHANGE_INFO, change);
    extensionPanel.putObject(GerritUiExtensionPoint.Key.REVISION_INFO, rev);
    p.add(extensionPanel);
  }

  private void addExtensionPoint(
      GerritUiExtensionPoint extensionPoint, Panel p, ChangeInfo change, RevisionInfo rev) {
    addExtensionPoint(extensionPoint, p, change, rev, Collections.emptyList());
  }

  private boolean enableSignedPush() {
    return Gerrit.info().receive().enableSignedPush();
  }

  void loadChangeInfo(boolean fg, AsyncCallback<ChangeInfo> cb) {
    RestApi call = ChangeApi.detail(Project.NameKey.asStringOrNull(project), changeId.get());
    EnumSet<ListChangesOption> opts =
        EnumSet.of(ListChangesOption.ALL_REVISIONS, ListChangesOption.CHANGE_ACTIONS);
    if (enableSignedPush()) {
      opts.add(ListChangesOption.PUSH_CERTIFICATES);
    }
    ChangeList.addOptions(call, opts);
    if (!fg) {
      call.background();
    }
    call.get(cb);
  }

  void loadRevisionInfo() {
    RestApi call = ChangeApi.actions(getProject().get(), changeId.get(), revision);
    call.background();
    call.get(
        new GerritCallback<NativeMap<ActionInfo>>() {
          @Override
          public void onSuccess(NativeMap<ActionInfo> actionMap) {
            actionMap.copyKeysIntoChildren("id");
            renderRevisionInfo(changeInfo, actionMap);
          }
        });
  }

  @Override
  protected void onUnload() {
    if (replyAction != null) {
      replyAction.hide();
    }
    if (updateCheck != null) {
      updateCheck.cancel();
      updateCheck = null;
    }
    for (HandlerRegistration h : handlers) {
      h.removeHandler();
    }
    handlers.clear();
    super.onUnload();
  }

  @Override
  protected void onInitUI() {
    super.onInitUI();
    setHeaderVisible(false);
    Resources.I.style().ensureInjected();
    star.setVisible(Gerrit.isSignedIn());
    labels.init(style);
    reviewers.init(style, ccText);
    hashtags.init(style);
  }

  private void initReplyButton(ChangeInfo info, String revision) {
    if (!info.revision(revision).isEdit()) {
      reply.setTitle(Gerrit.info().change().replyLabel());
      reply.setHTML(
          new SafeHtmlBuilder().openDiv().append(Gerrit.info().change().replyLabel()).closeDiv());
      if (hasDraftComments || lc.hasReplyComment()) {
        reply.setStyleName(style.highlight());
      }
      reply.setVisible(true);
    }
  }

  private void gotoSibling(int offset) {
    if (offset > 0
        && changeInfo.currentRevision() != null
        && changeInfo.currentRevision().equals(revision)) {
      return;
    }

    if (offset < 0 && changeInfo.revision(revision)._number() == 1) {
      return;
    }

    JsArray<RevisionInfo> revisions = changeInfo.revisions().values();
    RevisionInfo.sortRevisionInfoByNumber(revisions);
    for (int i = 0; i < revisions.length(); i++) {
      if (revision.equals(revisions.get(i).name())) {
        if (0 <= i + offset && i + offset < revisions.length()) {
          Gerrit.display(
              PageLinks.toChange(
                  project,
                  new PatchSet.Id(changeInfo.legacyId(), revisions.get(i + offset)._number())));
          return;
        }
        return;
      }
    }
  }

  private void initIncludedInAction(ChangeInfo info) {
    if (info.status() == Status.MERGED) {
      includedInAction =
          new IncludedInAction(
              info.projectNameKey(), info.legacyId(), style, headerLine, includedIn);
      includedIn.setVisible(true);
    }
  }

  private void updatePatchSetsTextStyle(boolean isPatchSetCurrent) {
    if (isPatchSetCurrent) {
      patchSetsText.removeClassName(style.notCurrentPatchSet());
    } else {
      patchSetsText.addClassName(style.notCurrentPatchSet());
    }
  }

  private void initRevisionsAction(ChangeInfo info, String revision) {
    int currentPatchSet;
    if (info.currentRevision() != null && info.revisions().containsKey(info.currentRevision())) {
      currentPatchSet = info.revision(info.currentRevision())._number();
    } else {
      JsArray<RevisionInfo> revList = info.revisions().values();
      RevisionInfo.sortRevisionInfoByNumber(revList);
      currentPatchSet = revList.get(revList.length() - 1)._number();
    }

    String currentlyViewedPatchSet;
    boolean isPatchSetCurrent = true;
    String revisionId = info.revision(revision).id();
    if (revisionId.equals("edit")) {
      currentlyViewedPatchSet =
          Resources.M.editPatchSet(RevisionInfo.findEditParent(info.revisions().values()));
      currentPatchSet = info.revisions().values().length() - 1;
    } else {
      currentlyViewedPatchSet = revisionId;
      if (!currentlyViewedPatchSet.equals(Integer.toString(currentPatchSet))) {
        isPatchSetCurrent = false;
      }
    }
    patchSetsText.setInnerText(Resources.M.patchSets(currentlyViewedPatchSet, currentPatchSet));
    updatePatchSetsTextStyle(isPatchSetCurrent);
    patchSetsAction =
        new PatchSetsAction(
            info.projectNameKey(), info.legacyId(), revision, edit, style, headerLine, patchSets);
  }

  private void initDownloadAction(ChangeInfo info, String revision) {
    downloadAction = new DownloadAction(info, revision, style, headerLine, download);
  }

  private void initProjectLinks(ChangeInfo info) {
    projectSettingsLink.setHref("#" + PageLinks.toProject(info.projectNameKey()));
    projectSettings.addDomHandler(
        new ClickHandler() {
          @Override
          public void onClick(ClickEvent event) {
            if (Hyperlink.impl.handleAsClick((Event) event.getNativeEvent())) {
              event.stopPropagation();
              event.preventDefault();
              Gerrit.display(PageLinks.toProject(info.projectNameKey()));
            }
          }
        },
        ClickEvent.getType());
    projectDashboard.setText(info.project());
    projectDashboard.setTargetHistoryToken(
        PageLinks.toProjectDefaultDashboard(info.projectNameKey()));
  }

  private void initBranchLink(ChangeInfo info) {
    branchLink.setText(info.branch());
    branchLink.setTargetHistoryToken(
        PageLinks.toChangeQuery(
            BranchLink.query(info.projectNameKey(), info.status(), info.branch(), null)));
  }

  private void initEditMode(ChangeInfo info, String revision) {
    if (Gerrit.isSignedIn()) {
      RevisionInfo rev = info.revision(revision);
      if (info.status().isOpen()) {
        if (isEditModeEnabled(info, rev)) {
          editMode.setVisible(fileTableMode == FileTable.Mode.REVIEW);
          addFile.setVisible(!editMode.isVisible());
          deleteFile.setVisible(!editMode.isVisible());
          renameFile.setVisible(!editMode.isVisible());
          reviewMode.setVisible(!editMode.isVisible());
          addFileAction =
              new AddFileAction(
                  info.projectNameKey(), changeId, info.revision(revision), style, addFile, files);
          deleteFileAction =
              new DeleteFileAction(
                  info.projectNameKey(), changeId, info.revision(revision), style, addFile);
          renameFileAction =
              new RenameFileAction(
                  info.projectNameKey(), changeId, info.revision(revision), style, addFile);
        } else {
          editMode.setVisible(false);
          addFile.setVisible(false);
          reviewMode.setVisible(false);
        }

        if (rev.isEdit()) {
          if (info.hasEditBasedOnCurrentPatchSet()) {
            publishEdit.setVisible(true);
          } else {
            rebaseEdit.setVisible(true);
          }
          deleteEdit.setVisible(true);
        }
      } else if (rev.isEdit()) {
        deleteEdit.setStyleName(style.highlight());
        deleteEdit.setVisible(true);
      }
    }
  }

  private boolean isEditModeEnabled(ChangeInfo info, RevisionInfo rev) {
    if (rev.isEdit()) {
      return true;
    }
    if (edit == null) {
      return revision.equals(info.currentRevision());
    }
    return rev._number() == RevisionInfo.findEditParent(info.revisions().values());
  }

  @UiHandler("publishEdit")
  void onPublishEdit(@SuppressWarnings("unused") ClickEvent e) {
    EditActions.publishEdit(getProject(), changeId, publishEdit, rebaseEdit, deleteEdit);
  }

  @UiHandler("rebaseEdit")
  void onRebaseEdit(@SuppressWarnings("unused") ClickEvent e) {
    EditActions.rebaseEdit(getProject(), changeId, publishEdit, rebaseEdit, deleteEdit);
  }

  @UiHandler("deleteEdit")
  void onDeleteEdit(@SuppressWarnings("unused") ClickEvent e) {
    if (Window.confirm(Resources.C.deleteChangeEdit())) {
      EditActions.deleteEdit(getProject(), changeId, publishEdit, rebaseEdit, deleteEdit);
    }
  }

  @Override
  public void registerKeys() {
    super.registerKeys();

    KeyCommandSet keysNavigation = new KeyCommandSet(Gerrit.C.sectionNavigation());
    keysNavigation.add(
        new KeyCommand(0, 'u', Util.C.upToChangeList()) {
          @Override
          public void onKeyPress(KeyPressEvent event) {
            Gerrit.displayLastChangeList();
          }
        });
    keysNavigation.add(
        new KeyCommand(0, 'R', Util.C.keyReloadChange()) {
          @Override
          public void onKeyPress(KeyPressEvent event) {
            Gerrit.display(PageLinks.toChange(project, changeId));
          }
        });
    keysNavigation.add(
        new KeyCommand(0, 'n', Util.C.keyNextPatchSet()) {
          @Override
          public void onKeyPress(KeyPressEvent event) {
            gotoSibling(1);
          }
        },
        new KeyCommand(0, 'p', Util.C.keyPreviousPatchSet()) {
          @Override
          public void onKeyPress(KeyPressEvent event) {
            gotoSibling(-1);
          }
        });
    handlers.add(GlobalKey.add(this, keysNavigation));

    KeyCommandSet keysAction = new KeyCommandSet(Gerrit.C.sectionActions());
    keysAction.add(
        new KeyCommand(0, 'a', Util.C.keyPublishComments()) {
          @Override
          public void onKeyPress(KeyPressEvent event) {
            if (Gerrit.isSignedIn()) {
              onReply(null);
            } else {
              Gerrit.doSignIn(getToken());
            }
          }
        });
    keysAction.add(
        new KeyCommand(0, 'x', Util.C.keyExpandAllMessages()) {
          @Override
          public void onKeyPress(KeyPressEvent event) {
            onExpandAll(null);
          }
        });
    keysAction.add(
        new KeyCommand(0, 'z', Util.C.keyCollapseAllMessages()) {
          @Override
          public void onKeyPress(KeyPressEvent event) {
            onCollapseAll(null);
          }
        });
    keysAction.add(
        new KeyCommand(0, 's', Util.C.changeTableStar()) {
          @Override
          public void onKeyPress(KeyPressEvent event) {
            if (Gerrit.isSignedIn()) {
              star.setValue(!star.getValue(), true);
            } else {
              Gerrit.doSignIn(getToken());
            }
          }
        });
    keysAction.add(
        new KeyCommand(0, 'c', Util.C.keyAddReviewers()) {
          @Override
          public void onKeyPress(KeyPressEvent event) {
            if (Gerrit.isSignedIn()) {
              reviewers.onOpenForm();
            } else {
              Gerrit.doSignIn(getToken());
            }
          }
        });
    keysAction.add(
        new KeyCommand(0, 't', Util.C.keyEditTopic()) {
          @Override
          public void onKeyPress(KeyPressEvent event) {
            if (Gerrit.isSignedIn()) {
              // In Firefox this event is mistakenly called when F5 is pressed so
              // differentiate F5 from 't' by checking the charCode(F5=0, t=116).
              if (event.getNativeEvent().getCharCode() == 0) {
                Window.Location.reload();
                return;
              }
              if (topic.canEdit()) {
                topic.onEdit();
              }
            } else {
              Gerrit.doSignIn(getToken());
            }
          }
        });
    handlers.add(GlobalKey.add(this, keysAction));
    files.registerKeys();
  }

  @Override
  public void onShowView() {
    super.onShowView();
    commit.onShowView();
    related.setMaxHeight(commit.getElement().getParentElement().getOffsetHeight());

    if (openReplyBox) {
      onReply();
    } else {
      String prior = Gerrit.getPriorView();
      if (prior != null && prior.startsWith("/c/")) {
        scrollToPath(prior.substring(3));
      }
    }

    ChangeGlue.fireShowChange(changeInfo, changeInfo.revision(revision));
    CodeMirror.preload();
    startPoller();
  }

  private void scrollToPath(String token) {
    ProjectChangeId cId;
    try {
      cId = ProjectChangeId.create(token);
    } catch (IllegalArgumentException e) {
      // Scrolling is best-effort.
      return;
    }
    if (!changeId.equals(cId.getChangeId())) {
      return; // Unrelated URL, do not scroll.
    }

    // Extract the start of a file path. The patch set is always contained in the URL and separated
    // by from the changeId by a forward slash. Example: /c/project/+/123/1/folder/file.txt
    int s = token.indexOf('/', cId.identifierLength() + 1);
    if (s < 0) {
      return; // URL does not name a file.
    }

    int c = token.lastIndexOf(',');
    if (0 <= c) {
      token = token.substring(s + 1, c);
    } else {
      token = token.substring(s + 1);
    }

    if (!token.isEmpty()) {
      files.scrollToPath(KeyUtil.decode(token));
    }
  }

  @UiHandler("star")
  void onToggleStar(ValueChangeEvent<Boolean> e) {
    StarredChanges.toggleStar(changeId, e.getValue());
  }

  @UiHandler("includedIn")
  void onIncludedIn(@SuppressWarnings("unused") ClickEvent e) {
    includedInAction.show();
  }

  @UiHandler("download")
  void onDownload(@SuppressWarnings("unused") ClickEvent e) {
    downloadAction.show();
  }

  @UiHandler("patchSets")
  void onPatchSets(@SuppressWarnings("unused") ClickEvent e) {
    patchSetsAction.show();
  }

  @UiHandler("reply")
  void onReply(@SuppressWarnings("unused") ClickEvent e) {
    onReply();
  }

  @UiHandler("permalink")
  void onReload(ClickEvent e) {
    e.preventDefault();
    Gerrit.display(PageLinks.toChange(project, changeId));
  }

  private void onReply() {
    if (Gerrit.isSignedIn()) {
      replyAction.onReply(null);
    } else {
      Gerrit.doSignIn(getToken());
    }
  }

  @UiHandler("openAll")
  void onOpenAll(@SuppressWarnings("unused") ClickEvent e) {
    files.openAll();
  }

  @UiHandler("editMode")
  void onEditMode(@SuppressWarnings("unused") ClickEvent e) {
    fileTableMode = FileTable.Mode.EDIT;
    refreshFileTable();
    editMode.setVisible(false);
    addFile.setVisible(true);
    deleteFile.setVisible(true);
    renameFile.setVisible(true);
    reviewMode.setVisible(true);
  }

  @UiHandler("reviewMode")
  void onReviewMode(@SuppressWarnings("unused") ClickEvent e) {
    fileTableMode = FileTable.Mode.REVIEW;
    refreshFileTable();
    editMode.setVisible(true);
    addFile.setVisible(false);
    deleteFile.setVisible(false);
    renameFile.setVisible(false);
    reviewMode.setVisible(false);
  }

  @UiHandler("addFile")
  void onAddFile(@SuppressWarnings("unused") ClickEvent e) {
    addFileAction.onEdit();
  }

  @UiHandler("deleteFile")
  void onDeleteFile(@SuppressWarnings("unused") ClickEvent e) {
    deleteFileAction.onDelete();
  }

  @UiHandler("renameFile")
  void onRenameFile(@SuppressWarnings("unused") ClickEvent e) {
    renameFileAction.onRename();
  }

  private void refreshFileTable() {
    int idx = diffBase.getSelectedIndex();
    if (0 <= idx) {
      String n = diffBase.getValue(idx);
      loadConfigInfo(changeInfo, DiffObject.parse(changeInfo.legacyId(), n));
    }
  }

  @UiHandler("showTaggedComments")
  void onShowTaggedComments(@SuppressWarnings("unused") ClickEvent e) {
    showTaggedComments.setVisible(false);
    hideTaggedComments.setVisible(true);
    int n = history.getWidgetCount();
    for (int i = 0; i < n; i++) {
      Message m = ((Message) history.getWidget(i));
      m.setVisible(true);
    }
  }

  @UiHandler("hideTaggedComments")
  void onHideTaggedComments(@SuppressWarnings("unused") ClickEvent e) {
    hideTaggedComments.setVisible(false);
    showTaggedComments.setVisible(true);
    int n = history.getWidgetCount();
    for (int i = 0; i < n; i++) {
      Message m = ((Message) history.getWidget(i));
      if (m.getMessageInfo().tag() != null) {
        m.setVisible(false);
      }
    }
  }

  @UiHandler("expandAll")
  void onExpandAll(@SuppressWarnings("unused") ClickEvent e) {
    int n = history.getWidgetCount();
    for (int i = 0; i < n; i++) {
      ((Message) history.getWidget(i)).setOpen(true);
    }
    expandAll.setVisible(false);
    collapseAll.setVisible(true);
  }

  @UiHandler("collapseAll")
  void onCollapseAll(@SuppressWarnings("unused") ClickEvent e) {
    int n = history.getWidgetCount();
    for (int i = 0; i < n; i++) {
      ((Message) history.getWidget(i)).setOpen(false);
    }
    expandAll.setVisible(true);
    collapseAll.setVisible(false);
  }

  @UiHandler("diffBase")
  void onChangeRevision(@SuppressWarnings("unused") ChangeEvent e) {
    int idx = diffBase.getSelectedIndex();
    if (0 <= idx) {
      String n = diffBase.getValue(idx);
      loadConfigInfo(changeInfo, DiffObject.parse(changeInfo.legacyId(), n));
    }
  }

  private void loadConfigInfo(ChangeInfo info, DiffObject base) {
    final RevisionInfo rev = info.revision(revision);
    if (base.isAutoMerge() && !initCurrentRevision(info).isMerge()) {
      Gerrit.display(getToken(), new NotFoundScreen());
    }

    updateToken(info, base, rev);

    RevisionInfo baseRev = resolveRevisionOrPatchSetId(info, base.asString(), null);

    CallbackGroup group = new CallbackGroup();
    Timestamp lastReply = myLastReply(info);
    if (rev.isEdit()) {
      // Comments are filtered for the current revision. Use parent
      // patch set for edits, as edits themself can never have comments.
      RevisionInfo p = RevisionInfo.findEditParentRevision(info.revisions().values());
      List<NativeMap<JsArray<CommentInfo>>> comments = loadComments(p, group);
      loadFileList(base, baseRev, rev, lastReply, group, comments, null);
    } else {
      loadDiff(base, baseRev, rev, lastReply, group);
    }
    group.addListener(
        new AsyncCallback<Void>() {
          @Override
          public void onSuccess(Void result) {
            loadConfigInfo(info, rev);
          }

          @Override
          public void onFailure(Throwable caught) {
            logger.log(
                Level.SEVERE,
                "Loading file list and inline comments failed: " + caught.getMessage());
            loadConfigInfo(info, rev);
          }
        });
    group.done();
  }

  private void loadConfigInfo(ChangeInfo info, RevisionInfo rev) {
    if (loaded) {
      return;
    }

    RevisionInfoCache.add(changeId, rev);
    ConfigInfoCache.add(info);
    ConfigInfoCache.get(
        info.projectNameKey(),
        new ScreenLoadCallback<ConfigInfoCache.Entry>(this) {
          @Override
          protected void preDisplay(Entry result) {
            loaded = true;
            commentLinkProcessor = result.getCommentLinkProcessor();
            setTheme(result.getTheme());
            renderChangeInfo(info);
            loadRevisionInfo();
          }
        });
    ConfigInfoCache.get(
        info.projectNameKey(),
        new GerritCallback<Entry>() {
          @Override
          public void onSuccess(Entry entry) {
            addExtensionPoints(info, rev, entry);
          }
        });
  }

  private void updateToken(ChangeInfo info, DiffObject base, RevisionInfo rev) {
    StringBuilder token =
        new StringBuilder("/c/")
            .append(PageLinks.toChangeId(info.projectNameKey(), info.legacyId()))
            .append("/");
    if (base.asString() != null) {
      token.append(base.asString()).append("..");
    }
    if (base.asString() != null || !rev.name().equals(info.currentRevision())) {
      token.append(rev._number());
    }
    setToken(token.toString());
  }

  static Timestamp myLastReply(ChangeInfo info) {
    if (Gerrit.isSignedIn() && info.messages() != null) {
      int self = Gerrit.getUserAccount()._accountId();
      for (int i = info.messages().length() - 1; i >= 0; i--) {
        MessageInfo m = info.messages().get(i);
        if (m.author() != null && m.author()._accountId() == self) {
          return m.date();
        }
      }
    }
    return null;
  }

  private void loadDiff(
      DiffObject base,
      RevisionInfo baseRev,
      RevisionInfo rev,
      Timestamp myLastReply,
      CallbackGroup group) {
    List<NativeMap<JsArray<CommentInfo>>> comments = loadComments(rev, group);
    List<NativeMap<JsArray<CommentInfo>>> drafts = loadDrafts(rev, group);
    loadFileList(base, baseRev, rev, myLastReply, group, comments, drafts);

    if (Gerrit.isSignedIn() && fileTableMode == FileTable.Mode.REVIEW) {
      ChangeApi.revision(getProject().get(), changeId.get(), rev.name())
          .view("files")
          .addParameterTrue("reviewed")
          .get(
              group.add(
                  new AsyncCallback<JsArrayString>() {
                    @Override
                    public void onSuccess(JsArrayString result) {
                      files.markReviewed(result);
                    }

                    @Override
                    public void onFailure(Throwable caught) {}
                  }));
    }
  }

  private void loadFileList(
      final DiffObject base,
      final RevisionInfo baseRev,
      final RevisionInfo rev,
      final Timestamp myLastReply,
      CallbackGroup group,
      final List<NativeMap<JsArray<CommentInfo>>> comments,
      final List<NativeMap<JsArray<CommentInfo>>> drafts) {
    DiffApi.list(
        getProject().get(),
        changeId.get(),
        rev.name(),
        baseRev,
        group.add(
            new AsyncCallback<NativeMap<FileInfo>>() {
              @Override
              public void onSuccess(NativeMap<FileInfo> m) {
                files.set(
                    base,
                    new PatchSet.Id(changeId, rev._number()),
                    getProject(),
                    style,
                    reply,
                    fileTableMode,
                    edit != null);
                files.setValue(
                    m,
                    myLastReply,
                    comments != null ? comments.get(0) : null,
                    drafts != null ? drafts.get(0) : null);
              }

              @Override
              public void onFailure(Throwable caught) {
                files.showError(caught);
              }
            }));
  }

  private List<NativeMap<JsArray<CommentInfo>>> loadComments(
      final RevisionInfo rev, CallbackGroup group) {
    final List<NativeMap<JsArray<CommentInfo>>> r = new ArrayList<>(1);
    // TODO(dborowitz): Could eliminate this call by adding an option to include
    // inline comments in the change detail.
    ChangeApi.comments(getProject().get(), changeId.get())
        .get(
            group.add(
                new AsyncCallback<NativeMap<JsArray<CommentInfo>>>() {
                  @Override
                  public void onSuccess(NativeMap<JsArray<CommentInfo>> result) {
                    // Return value is used for populating the file table, so only count
                    // comments for the current revision. Still include all comments in
                    // the history table.
                    r.add(filterForRevision(result, rev._number()));
                    history.addComments(result);
                  }

                  @Override
                  public void onFailure(Throwable caught) {}
                }));
    return r;
  }

  private static NativeMap<JsArray<CommentInfo>> filterForRevision(
      NativeMap<JsArray<CommentInfo>> comments, int id) {
    NativeMap<JsArray<CommentInfo>> filtered = NativeMap.create();
    for (String k : comments.keySet()) {
      JsArray<CommentInfo> allRevisions = comments.get(k);
      JsArray<CommentInfo> thisRevision = JsArray.createArray().cast();
      for (int i = 0; i < allRevisions.length(); i++) {
        CommentInfo c = allRevisions.get(i);
        if (c.patchSet() == id) {
          thisRevision.push(c);
        }
      }
      filtered.put(k, thisRevision);
    }
    return filtered;
  }

  private List<NativeMap<JsArray<CommentInfo>>> loadDrafts(RevisionInfo rev, CallbackGroup group) {
    final List<NativeMap<JsArray<CommentInfo>>> r = new ArrayList<>(1);
    if (Gerrit.isSignedIn()) {
      ChangeApi.revision(getProject().get(), changeId.get(), rev.name())
          .view("drafts")
          .get(
              group.add(
                  new AsyncCallback<NativeMap<JsArray<CommentInfo>>>() {
                    @Override
                    public void onSuccess(NativeMap<JsArray<CommentInfo>> result) {
                      r.add(result);
                    }

                    @Override
                    public void onFailure(Throwable caught) {}
                  }));
    } else {
      r.add(NativeMap.<JsArray<CommentInfo>>create());
    }
    return r;
  }

  private void loadCommit(RevisionInfo rev, CallbackGroup group) {
    if (rev.isEdit() || rev.commit() != null) {
      return;
    }

    ChangeApi.commitWithLinks(
        getProject().get(),
        changeId.get(),
        rev.name(),
        group.add(
            new AsyncCallback<CommitInfo>() {
              @Override
              public void onSuccess(CommitInfo info) {
                rev.setCommit(info);
              }

              @Override
              public void onFailure(Throwable caught) {}
            }));
  }

  private void renderSubmitType(Change.Status status, boolean canSubmit, SubmitType submitType) {
    if (status == Change.Status.NEW && !changeInfo.isWorkInProgress()) {
      if (canSubmit) {
        statusText.setInnerText(
            changeInfo.mergeable() ? Util.C.readyToSubmit() : Util.C.mergeConflict());
      }
      setVisible(notMergeable, !changeInfo.mergeable());
    }
    submitActionText.setInnerText(com.google.gerrit.client.admin.Util.toLongString(submitType));
  }

  private RevisionInfo resolveRevisionToDisplay(ChangeInfo info) {
    RevisionInfo rev = resolveRevisionOrPatchSetId(info, revision, info.currentRevision());
    if (rev != null) {
      revision = rev.name();
      return rev;
    }

    // the revision is not visible to the calling user (maybe it is a draft?)
    // or the change is corrupt, take the last revision that was returned,
    // if no revision was returned display an error
    JsArray<RevisionInfo> revisions = info.revisions().values();
    if (revisions.length() > 0) {
      RevisionInfo.sortRevisionInfoByNumber(revisions);
      rev = revisions.get(revisions.length() - 1);
      revision = rev.name();
      return rev;
    }
    new ErrorDialog(Resources.M.changeWithNoRevisions(info.legacyId().get())).center();
    throw new IllegalStateException("no revision, cannot proceed");
  }

  /**
   * Resolve a revision or patch set id string to RevisionInfo. When this view is created from the
   * changes table, revision is passed as a real revision. When this view is created from side by
   * side (by closing it with 'u') patch set id is passed.
   *
   * @param info change info
   * @param revOrId revision or patch set id
   * @param defaultValue value returned when revOrId is null
   * @return resolved revision or default value
   */
  private RevisionInfo resolveRevisionOrPatchSetId(
      ChangeInfo info, String revOrId, String defaultValue) {
    int parentNum;
    if (revOrId == null) {
      revOrId = defaultValue;
    } else if ((parentNum = toParentNum(revOrId)) > 0) {
      CommitInfo commitInfo = info.revision(revision).commit();
      JsArray<CommitInfo> parents = commitInfo.parents();
      if (parents.length() >= parentNum) {
        return RevisionInfo.forParent(-parentNum, parents.get(parentNum - 1));
      }
    } else if (!info.revisions().containsKey(revOrId)) {
      JsArray<RevisionInfo> list = info.revisions().values();
      for (int i = 0; i < list.length(); i++) {
        RevisionInfo r = list.get(i);
        if (revOrId.equals(String.valueOf(r._number()))) {
          revOrId = r.name();
          break;
        }
      }
    }
    return revOrId != null ? info.revision(revOrId) : null;
  }

  private boolean isSubmittable(ChangeInfo info) {
    boolean canSubmit = info.status().isOpen() && revision.equals(info.currentRevision());
    if (canSubmit && info.status() == Change.Status.NEW) {
      for (String name : info.labels()) {
        LabelInfo label = info.label(name);
        switch (label.status()) {
          case NEED:
            statusText.setInnerText(Util.M.needs(name));
            canSubmit = false;
            break;
          case REJECT:
          case IMPOSSIBLE:
            if (label.blocking()) {
              statusText.setInnerText(Util.M.blockedOn(name));
              canSubmit = false;
            }
            break;
          case MAY:
          case OK:
          default:
            break;
        }
      }
    }
    return canSubmit;
  }

  private void renderChangeInfo(ChangeInfo info) {
    RevisionInfo revisionInfo = info.revision(revision);
    changeInfo = info;
    lastDisplayedUpdate = info.updated();

    labels.set(info);

    renderOwner(info);
    renderUploader(info, revisionInfo);
    renderActionTextDate(info);
    renderDiffBaseListBox(info);
    initReplyButton(info, revision);
    initIncludedInAction(info);
    initDownloadAction(info, revision);
    initProjectLinks(info);
    initBranchLink(info);
    initEditMode(info, revision);
    actions.display(info, revision);

    star.setValue(info.starred());
    permalink.setHref(ChangeLink.permalink(changeId));
    permalink.setText(String.valueOf(info.legacyId()));
    topic.set(info, revision);
    commit.set(commentLinkProcessor, info, revision);
    related.set(info, revision);
    reviewers.set(info);
    assignee.set(info);
    if (Gerrit.isNoteDbEnabled()) {
      hashtags.set(info, revision);
    } else {
      setVisible(hashtagTableRow, false);
    }

    StringBuilder sb = new StringBuilder();
    sb.append(Util.M.changeScreenTitleId(info.idAbbreviated()));
    if (info.subject() != null) {
      sb.append(": ");
      sb.append(info.subject());
    }
    setWindowTitle(sb.toString());

    // Although this is related to the revision, we can process it early to
    // render it faster.
    if (!info.status().isOpen()
        || !revision.equals(info.currentRevision())
        || revisionInfo.isEdit()) {
      setVisible(strategy, false);
    }

    // Properly render revision actions initially while waiting for
    // the callback to populate them correctly.
    NativeMap<ActionInfo> emptyMap = NativeMap.<ActionInfo>create();
    initRevisionsAction(info, revision);
    quickApprove.setVisible(false);
    actions.reloadRevisionActions(emptyMap);

    boolean current = revision.equals(info.currentRevision()) && !revisionInfo.isEdit();

    if (revisionInfo.isEdit()) {
      statusText.setInnerText(Util.C.changeEdit());
    } else if (!current) {
      statusText.setInnerText(Util.C.notCurrent());
      labels.setVisible(false);
    } else {
      statusText.setInnerText(Util.toLongString(info.status()));
    }

    if (info.isPrivate()) {
      privateText.setInnerText(Util.C.isPrivate());
    }

    if (info.isWorkInProgress()) {
      wipText.setInnerText(Util.C.isWorkInProgress());
    }

    if (Gerrit.isSignedIn()) {
      replyAction =
          new ReplyAction(
              info, revision, hasDraftComments, style, commentLinkProcessor, reply, quickApprove);
    }
    history.set(commentLinkProcessor, replyAction, changeId, info);

    if (current && info.status().isOpen()) {
      quickApprove.set(info, revision, replyAction);
      renderSubmitType(info.status(), isSubmittable(info), info.submitType());
    } else {
      quickApprove.setVisible(false);
    }
  }

  private void renderRevisionInfo(ChangeInfo info, NativeMap<ActionInfo> actionMap) {
    initRevisionsAction(info, revision);
    commit.setParentNotCurrent(
        actionMap.containsKey("rebase") && actionMap.get("rebase").enabled());
    actions.reloadRevisionActions(actionMap);
  }

  private void renderOwner(ChangeInfo info) {
    // TODO info card hover
    String name = name(info.owner());
    if (info.owner().avatar(AvatarInfo.DEFAULT_SIZE) != null) {
      ownerPanel.insert(new AvatarImage(info.owner()), 0);
    }
    ownerLink.setText(name);
    ownerLink.setTitle(email(info.owner(), name));
    ownerLink.setTargetHistoryToken(
        PageLinks.toAccountQuery(
            info.owner().name() != null
                ? info.owner().name()
                : info.owner().email() != null
                    ? info.owner().email()
                    : String.valueOf(info.owner()._accountId()),
            Change.Status.NEW));
  }

  private void renderUploader(ChangeInfo changeInfo, RevisionInfo revInfo) {
    AccountInfo uploader = revInfo.uploader();
    boolean isOwner = uploader == null || uploader._accountId() == changeInfo.owner()._accountId();
    renderPushCertificate(revInfo, isOwner ? ownerPanel : uploaderPanel);
    if (isOwner) {
      uploaderRow.getStyle().setDisplay(Display.NONE);
      return;
    }
    uploaderRow.getStyle().setDisplay(Display.TABLE_ROW);

    if (uploader.avatar(AvatarInfo.DEFAULT_SIZE) != null) {
      uploaderPanel.insert(new AvatarImage(uploader), 0);
    }
    String name = name(uploader);
    uploaderName.setText(name);
    uploaderName.setTitle(email(uploader, name));
  }

  private void renderPushCertificate(RevisionInfo revInfo, FlowPanel panel) {
    if (!enableSignedPush()) {
      return;
    }
    Image status = new Image();
    panel.add(status);
    status.setStyleName(style.pushCertStatus());
    if (!revInfo.hasPushCertificate() || revInfo.pushCertificate().key() == null) {
      status.setResource(Gerrit.RESOURCES.question());
      status.setTitle(Util.C.pushCertMissing());
      return;
    }
    PushCertificateInfo certInfo = revInfo.pushCertificate();
    GpgKeyInfo.Status s = certInfo.key().status();
    switch (s) {
      case BAD:
        status.setResource(Gerrit.RESOURCES.redNot());
        status.setTitle(problems(Util.C.pushCertBad(), certInfo));
        break;
      case OK:
        status.setResource(Gerrit.RESOURCES.warning());
        status.setTitle(problems(Util.C.pushCertOk(), certInfo));
        break;
      case TRUSTED:
        status.setResource(Gerrit.RESOURCES.greenCheck());
        status.setTitle(Util.C.pushCertTrusted());
        break;
    }
  }

  private static String name(AccountInfo info) {
    return info.name() != null ? info.name() : Gerrit.info().user().anonymousCowardName();
  }

  private static String email(AccountInfo info, String name) {
    return info.email() != null ? info.email() : name;
  }

  private static String problems(String msg, PushCertificateInfo info) {
    if (info.key() == null || !info.key().hasProblems() || info.key().problems().length() == 0) {
      return msg;
    }

    StringBuilder sb = new StringBuilder();
    sb.append(msg).append(':');
    for (String problem : Natives.asList(info.key().problems())) {
      sb.append('\n').append(problem);
    }
    return sb.toString();
  }

  private void renderActionTextDate(ChangeInfo info) {
    String action;
    if (info.created().equals(info.updated())) {
      action = Util.C.changeInfoBlockUploaded();
    } else {
      action = Util.C.changeInfoBlockUpdated();
    }
    actionText.setInnerText(action);
    actionDate.setInnerText(FormatUtil.relativeFormat(info.updated()));
  }

  private void renderDiffBaseListBox(ChangeInfo info) {
    JsArray<RevisionInfo> list = info.revisions().values();
    RevisionInfo.sortRevisionInfoByNumber(list);
    int selectedIdx = list.length();
    for (int i = list.length() - 1; i >= 0; i--) {
      RevisionInfo r = list.get(i);
      diffBase.addItem(r.id() + ": " + r.name().substring(0, 6), r.id());
      if (r.name().equals(revision)) {
        SelectElement.as(diffBase.getElement())
            .getOptions()
            .getItem(diffBase.getItemCount() - 1)
            .setDisabled(true);
      }
      if (base.isPatchSet() && base.asPatchSetId().get() == r._number()) {
        selectedIdx = diffBase.getItemCount() - 1;
      }
    }

    RevisionInfo rev = info.revisions().get(revision);
    JsArray<CommitInfo> parents = rev.commit().parents();
    if (parents.length() > 1) {
      diffBase.addItem(Util.C.autoMerge(), DiffObject.AUTO_MERGE);
      for (int i = 0; i < parents.length(); i++) {
        int parentNum = i + 1;
        diffBase.addItem(Util.M.diffBaseParent(parentNum), String.valueOf(-parentNum));
      }

      if (base.isParent()) {
        selectedIdx = list.length() + base.getParentNum();
      }
    } else {
      diffBase.addItem(Util.C.baseDiffItem(), "");
    }

    diffBase.setSelectedIndex(selectedIdx);
  }

  void showUpdates(ChangeInfo newInfo) {
    if (!isAttached() || newInfo.updated().equals(lastDisplayedUpdate)) {
      return;
    }

    JsArray<MessageInfo> om = changeInfo.messages();
    JsArray<MessageInfo> nm = newInfo.messages();

    if (om == null) {
      om = JsArray.createArray().cast();
    }
    if (nm == null) {
      nm = JsArray.createArray().cast();
    }

    if (om.length() == nm.length()) {
      return;
    }

    if (updateAvailable == null) {
      updateAvailable =
          new UpdateAvailableBar() {
            @Override
            void onShow() {
              Gerrit.display(PageLinks.toChange(project, changeId));
            }

            @Override
            void onIgnore(Timestamp newTime) {
              lastDisplayedUpdate = newTime;
            }
          };
    }
    updateAvailable.set(Natives.asList(nm).subList(om.length(), nm.length()), newInfo.updated());
    if (!updateAvailable.isAttached()) {
      add(updateAvailable);
    }
  }

  private void startPoller() {
    if (Gerrit.isSignedIn() && 0 < Gerrit.info().change().updateDelay()) {
      updateCheck = new UpdateCheckTimer(this);
      updateCheck.schedule();
      handlers.add(UserActivityMonitor.addValueChangeHandler(updateCheck));
    }
  }

  private static String normalize(String r) {
    return r != null && !r.isEmpty() ? r : null;
  }

  /**
   * @param parentToken
   * @return 1-based parentNum if parentToken is a String which can be parsed as a negative integer
   *     i.e. "-1", "-2", etc. If parentToken cannot be parsed as a negative integer, return zero.
   */
  private static int toParentNum(String parentToken) {
    try {
      int n = Integer.parseInt(parentToken);
      if (n < 0) {
        return -n;
      }
      return 0;
    } catch (NumberFormatException e) {
      return 0;
    }
  }
}
