// 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.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.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;
  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 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 publish;
  @UiField Button deleteRevision;
  @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(
      Change.Id changeId,
      DiffObject base,
      String revision,
      boolean openReplyBox,
      FileTable.Mode mode) {
    this.changeId = changeId;
    this.base = base;
    this.revision = normalize(revision);
    this.openReplyBox = openReplyBox;
    this.fileTableMode = mode;
    this.lc = new LocalComments(changeId);
    add(uiBinder.createAndBindUi(this));
  }

  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(
          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(final ChangeInfo info) {
                info.init();
                addExtensionPoints(info, 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) {
    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);
    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) {
    ExtensionPanel extensionPanel = new ExtensionPanel(extensionPoint);
    extensionPanel.putObject(GerritUiExtensionPoint.Key.CHANGE_INFO, change);
    extensionPanel.putObject(GerritUiExtensionPoint.Key.REVISION_INFO, rev);
    p.add(extensionPanel);
  }

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

  void loadChangeInfo(boolean fg, AsyncCallback<ChangeInfo> cb) {
    RestApi call = ChangeApi.detail(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(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(
                  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.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, NativeMap<ActionInfo> actions) {
    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.legacyId(), revision, edit, style, headerLine, patchSets);

    RevisionInfo revInfo = info.revision(revision);
    if (revInfo.draft()) {
      if (actions.containsKey("publish")) {
        publish.setVisible(true);
        publish.setTitle(actions.get("publish").title());
      }
      if (actions.containsKey("/")) {
        deleteRevision.setVisible(true);
        deleteRevision.setTitle(actions.get("/").title());
      }
    }
  }

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

  private void initProjectLinks(final 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(changeId, info.revision(revision), style, addFile, files);
          deleteFileAction =
              new DeleteFileAction(changeId, info.revision(revision), style, addFile);
          renameFileAction =
              new RenameFileAction(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(changeId, publishEdit, rebaseEdit, deleteEdit);
  }

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

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

  @UiHandler("publish")
  void onPublish(@SuppressWarnings("unused") ClickEvent e) {
    ChangeActions.publish(changeId, revision, publish, deleteRevision);
  }

  @UiHandler("deleteRevision")
  void onDeleteRevision(@SuppressWarnings("unused") ClickEvent e) {
    if (Window.confirm(Resources.C.deleteDraftRevision())) {
      ChangeActions.delete(changeId, revision, publish, deleteRevision);
    }
  }

  @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(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) {
    int s = token.indexOf('/');
    try {
      String c = token.substring(0, s);
      int editIndex = c.indexOf(",edit");
      if (editIndex > 0) {
        c = c.substring(0, editIndex);
      }
      if (s < 0 || !changeId.equals(Change.Id.parse(c))) {
        return; // Unrelated URL, do not scroll.
      }
    } catch (IllegalArgumentException e) {
      return;
    }

    s = token.indexOf('/', s + 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(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(final 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(final 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();
          }
        });
  }

  private void updateToken(ChangeInfo info, DiffObject base, RevisionInfo rev) {
    StringBuilder token = new StringBuilder("/c/").append(info._number()).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(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(
        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()),
                    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(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(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(final RevisionInfo rev, CallbackGroup group) {
    if (rev.isEdit() || rev.commit() != null) {
      return;
    }

    ChangeApi.commitWithLinks(
        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 (canSubmit && status == Change.Status.NEW) {
      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())
            && !info.revision(revision).draft();
    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, emptyMap);
    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 {
      Status s = info.revision(revision).draft() ? Status.DRAFT : info.status();
      statusText.setInnerText(Util.toLongString(s));
    }

    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, actionMap);
    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(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;
    }
  }
}
