/**
 * @license
 * Copyright 2015 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import {BehaviorSubject} from 'rxjs';
import '../gr-copy-links/gr-copy-links';
import '@polymer/paper-tabs/paper-tabs';
import '../../../styles/gr-a11y-styles';
import '../../../styles/gr-paper-styles';
import '../../../styles/shared-styles';
import '../../plugins/gr-endpoint-decorator/gr-endpoint-decorator';
import '../../plugins/gr-endpoint-param/gr-endpoint-param';
import '../../shared/gr-button/gr-button';
import '../../shared/gr-change-star/gr-change-star';
import '../../shared/gr-change-status/gr-change-status';
import '../../shared/gr-editable-content/gr-editable-content';
import '../../shared/gr-formatted-text/gr-formatted-text';
import '../../shared/gr-overlay/gr-overlay';
import '../../shared/gr-tooltip-content/gr-tooltip-content';
import '../gr-change-actions/gr-change-actions';
import '../gr-change-summary/gr-change-summary';
import '../gr-change-metadata/gr-change-metadata';
import '../gr-commit-info/gr-commit-info';
import '../gr-download-dialog/gr-download-dialog';
import '../gr-file-list-header/gr-file-list-header';
import '../gr-file-list/gr-file-list';
import '../gr-included-in-dialog/gr-included-in-dialog';
import '../gr-messages-list/gr-messages-list';
import '../gr-related-changes-list/gr-related-changes-list';
import '../../diff/gr-apply-fix-dialog/gr-apply-fix-dialog';
import '../gr-reply-dialog/gr-reply-dialog';
import '../gr-thread-list/gr-thread-list';
import '../../checks/gr-checks-tab';
import {ChangeStarToggleStarDetail} from '../../shared/gr-change-star/gr-change-star';
import {flush} from '@polymer/polymer/lib/legacy/polymer.dom';
import {GrEditConstants} from '../../edit/gr-edit-constants';
import {pluralize} from '../../../utils/string-util';
import {
  querySelectorAll,
  whenVisible,
  windowLocationReload,
} from '../../../utils/dom-util';
import {navigationToken} from '../../core/gr-navigation/gr-navigation';
import {getPluginEndpoints} from '../../shared/gr-js-api-interface/gr-plugin-endpoints';
import {getPluginLoader} from '../../shared/gr-js-api-interface/gr-plugin-loader';
import {RevisionInfo as RevisionInfoClass} from '../../shared/revision-info/revision-info';
import {
  ChangeStatus,
  DefaultBase,
  Tab,
  DiffViewMode,
} from '../../../constants/constants';
import {getAppContext} from '../../../services/app-context';
import {
  computeAllPatchSets,
  computeLatestPatchNum,
  findEdit,
  findEditParentRevision,
  PatchSet,
} from '../../../utils/patch-set-util';
import {
  changeIsAbandoned,
  changeIsMerged,
  changeIsOpen,
  changeStatuses,
  isInvolved,
  roleDetails,
} from '../../../utils/change-util';
import {EventType as PluginEventType} from '../../../api/plugin';
import {customElement, property, query, state} from 'lit/decorators.js';
import {GrApplyFixDialog} from '../../diff/gr-apply-fix-dialog/gr-apply-fix-dialog';
import {GrFileListHeader} from '../gr-file-list-header/gr-file-list-header';
import {GrEditableContent} from '../../shared/gr-editable-content/gr-editable-content';
import {GrOverlay} from '../../shared/gr-overlay/gr-overlay';
import {GrRelatedChangesList} from '../gr-related-changes-list/gr-related-changes-list';
import {GrChangeStar} from '../../shared/gr-change-star/gr-change-star';
import {GrChangeActions} from '../gr-change-actions/gr-change-actions';
import {
  AccountDetailInfo,
  ActionNameToActionInfoMap,
  BasePatchSetNum,
  ChangeId,
  ChangeInfo,
  CommitId,
  CommitInfo,
  ConfigInfo,
  DetailedLabelInfo,
  EDIT,
  LabelNameToInfoMap,
  NumericChangeId,
  PARENT,
  PatchRange,
  PatchSetNum,
  PatchSetNumber,
  PreferencesInfo,
  QuickLabelInfo,
  RelatedChangeAndCommitInfo,
  RelatedChangesInfo,
  RevisionInfo,
  RevisionPatchSetNum,
  ServerInfo,
  UrlEncodedCommentId,
} from '../../../types/common';
import {FocusTarget, GrReplyDialog} from '../gr-reply-dialog/gr-reply-dialog';
import {GrIncludedInDialog} from '../gr-included-in-dialog/gr-included-in-dialog';
import {GrDownloadDialog} from '../gr-download-dialog/gr-download-dialog';
import {GrChangeMetadata} from '../gr-change-metadata/gr-change-metadata';
import {assertIsDefined, assert, queryAll} from '../../../utils/common-util';
import {GrEditControls} from '../../edit/gr-edit-controls/gr-edit-controls';
import {
  CommentThread,
  isRobot,
  isUnresolved,
  DraftInfo,
} from '../../../utils/comment-util';
import {PaperTabsElement} from '@polymer/paper-tabs/paper-tabs';
import {GrFileList} from '../gr-file-list/gr-file-list';
import {EditRevisionInfo, ParsedChangeInfo} from '../../../types/types';
import {
  CloseFixPreviewEvent,
  EditableContentSaveEvent,
  EventType,
  OpenFixPreviewEvent,
  ShowAlertEventDetail,
  SwitchTabEvent,
  TabState,
  ValueChangedEvent,
} from '../../../types/events';
import {GrButton} from '../../shared/gr-button/gr-button';
import {GrMessagesList} from '../gr-messages-list/gr-messages-list';
import {GrThreadList} from '../gr-thread-list/gr-thread-list';
import {
  fireAlert,
  fireDialogChange,
  fireEvent,
  fireReload,
  fireTitleChange,
} from '../../../utils/event-util';
import {GerritView} from '../../../services/router/router-model';
import {
  debounce,
  DelayedTask,
  throttleWrap,
  until,
} from '../../../utils/async-util';
import {Interaction, Timing, Execution} from '../../../constants/reporting';
import {ChangeStates} from '../../shared/gr-change-status/gr-change-status';
import {getRevertCreatedChangeIds} from '../../../utils/message-util';
import {
  getAddedByReason,
  getRemovedByReason,
  hasAttention,
} from '../../../utils/attention-set-util';
import {
  Shortcut,
  ShortcutSection,
  shortcutsServiceToken,
} from '../../../services/shortcuts/shortcuts-service';
import {LoadingStatus} from '../../../models/change/change-model';
import {commentsModelToken} from '../../../models/comments/comments-model';
import {resolve} from '../../../models/dependency';
import {checksModelToken} from '../../../models/checks/checks-model';
import {changeModelToken} from '../../../models/change/change-model';
import {css, html, LitElement, nothing, PropertyValues} from 'lit';
import {a11yStyles} from '../../../styles/gr-a11y-styles';
import {paperStyles} from '../../../styles/gr-paper-styles';
import {sharedStyles} from '../../../styles/shared-styles';
import {ifDefined} from 'lit/directives/if-defined.js';
import {when} from 'lit/directives/when.js';
import {ShortcutController} from '../../lit/shortcut-controller';
import {FilesExpandedState} from '../gr-file-list-constants';
import {subscribe} from '../../lit/subscription-controller';
import {configModelToken} from '../../../models/config/config-model';
import {filesModelToken} from '../../../models/change/files-model';
import {getBaseUrl, prependOrigin} from '../../../utils/url-util';
import {CopyLink, GrCopyLinks} from '../gr-copy-links/gr-copy-links';
import {
  changeViewModelToken,
  ChangeViewState,
  createChangeUrl,
} from '../../../models/views/change';
import {rootUrl} from '../../../utils/url-util';
import {createEditUrl} from '../../../models/views/edit';

const CHANGE_ID_ERROR = {
  MISMATCH: 'mismatch',
  MISSING: 'missing',
};
const CHANGE_ID_REGEX_PATTERN =
  /^(Change-Id:\s|Link:.*\/id\/)(I[0-9a-f]{8,40})/gm;

const MIN_LINES_FOR_COMMIT_COLLAPSE = 18;

const REVIEWERS_REGEX = /^(R|CC)=/gm;
const MIN_CHECK_INTERVAL_SECS = 0;

const REPLY_REFIT_DEBOUNCE_INTERVAL_MS = 500;

const ACCIDENTAL_STARRING_LIMIT_MS = 10 * 1000;

const TRAILING_WHITESPACE_REGEX = /[ \t]+$/gm;

const PREFIX = '#message-';

const ReloadToastMessage = {
  NEWER_REVISION: 'A newer patch set has been uploaded',
  RESTORED: 'This change has been restored',
  ABANDONED: 'This change has been abandoned',
  MERGED: 'This change has been merged',
  NEW_MESSAGE: 'There are new messages on this change',
};

// Making the tab names more unique in case a plugin adds one with same name
const ROBOT_COMMENTS_LIMIT = 10;

export type ChangeViewPatchRange = Partial<PatchRange>;

@customElement('gr-change-view')
export class GrChangeView extends LitElement {
  /**
   * Fired when the title of the page should change.
   *
   * @event title-change
   */

  /**
   * Fired if an error occurs when fetching the change data.
   *
   * @event page-error
   */

  /**
   * Fired if being logged in is required.
   *
   * @event show-auth-required
   */

  @query('#applyFixDialog') applyFixDialog?: GrApplyFixDialog;

  @query('#fileList') fileList?: GrFileList;

  @query('#fileListHeader') fileListHeader?: GrFileListHeader;

  @query('#commitMessageEditor') commitMessageEditor?: GrEditableContent;

  @query('#includedInOverlay') includedInOverlay?: GrOverlay;

  @query('#includedInDialog') includedInDialog?: GrIncludedInDialog;

  @query('#downloadOverlay') downloadOverlay?: GrOverlay;

  @query('#downloadDialog') downloadDialog?: GrDownloadDialog;

  @query('#replyOverlay') replyOverlay?: GrOverlay;

  @query('#replyDialog') replyDialog?: GrReplyDialog;

  @query('#mainContent') mainContent?: HTMLDivElement;

  @query('#changeStar') changeStar?: GrChangeStar;

  @query('#actions') actions?: GrChangeActions;

  @query('#commitMessage') commitMessage?: HTMLDivElement;

  @query('#commitAndRelated') commitAndRelated?: HTMLDivElement;

  @query('#metadata') metadata?: GrChangeMetadata;

  @query('#mainChangeInfo') mainChangeInfo?: HTMLDivElement;

  @query('#replyBtn') replyBtn?: GrButton;

  @query('#tabs') tabs?: PaperTabsElement;

  @query('gr-messages-list') messagesList?: GrMessagesList;

  @query('gr-thread-list') threadList?: GrThreadList;

  @query('gr-copy-links') private copyLinksDropdown?: GrCopyLinks;

  private _viewState?: ChangeViewState;

  @property({type: Object})
  get viewState() {
    return this._viewState;
  }

  set viewState(viewState: ChangeViewState | undefined) {
    if (this._viewState === viewState) return;
    const oldViewState = this._viewState;
    this._viewState = viewState;
    this.viewStateChanged();
    this.requestUpdate('viewState', oldViewState);
  }

  @property({type: String})
  backPage?: string;

  @state()
  private hasParent?: boolean;

  // Private but used in tests.
  @state()
  commentThreads?: CommentThread[];

  // Don't use, use serverConfig instead.
  private _serverConfig?: ServerInfo;

  // Private but used in tests.
  @state()
  get serverConfig() {
    return this._serverConfig;
  }

  set serverConfig(serverConfig: ServerInfo | undefined) {
    if (this._serverConfig === serverConfig) return;
    const oldServerConfig = this._serverConfig;
    this._serverConfig = serverConfig;
    this.startUpdateCheckTimer();
    this.requestUpdate('serverConfig', oldServerConfig);
  }

  @state()
  private account?: AccountDetailInfo;

  // Private but used in tests.
  @state()
  prefs?: PreferencesInfo;

  canStartReview() {
    return !!(
      this.change &&
      this.change.actions &&
      this.change.actions.ready &&
      this.change.actions.ready.enabled
    );
  }

  // Use change getter/setter instead.
  private _change?: ParsedChangeInfo;

  @state()
  get change() {
    return this._change;
  }

  set change(change: ParsedChangeInfo | undefined) {
    if (this._change === change) return;
    const oldChange = this._change;
    this._change = change;
    this.changeChanged(oldChange);
    this.requestUpdate('change', oldChange);
  }

  // Private but used in tests.
  @state()
  commitInfo?: CommitInfo;

  // Private but used in tests.
  @state()
  changeNum?: NumericChangeId;

  // Private but used in tests.
  @state()
  diffDrafts?: {[path: string]: DraftInfo[]} = {};

  @state()
  private editingCommitMessage = false;

  @state()
  private latestCommitMessage: string | null = '';

  // Use patchRange getter/setter.
  private _patchRange?: ChangeViewPatchRange;

  // Private but used in tests.
  @state()
  get patchRange() {
    return this._patchRange;
  }

  set patchRange(patchRange: ChangeViewPatchRange | undefined) {
    if (this._patchRange === patchRange) return;
    const oldPatchRange = this._patchRange;
    this._patchRange = patchRange;
    this.patchNumChanged();
    this.requestUpdate('patchRange', oldPatchRange);
  }

  // Private but used in tests.
  @state()
  selectedRevision?: RevisionInfo | EditRevisionInfo;

  @state()
  get changeIdCommitMessageError() {
    return this.computeChangeIdCommitMessageError(
      this.latestCommitMessage,
      this.change
    );
  }

  /**
   * <gr-change-actions> populates this via two-way data binding.
   * Private but used in tests.
   */
  @state()
  currentRevisionActions?: ActionNameToActionInfoMap = {};

  @state()
  private allPatchSets?: PatchSet[];

  // Private but used in tests.
  @state()
  loggedIn = false;

  // Private but used in tests.
  @state()
  loading?: boolean;

  @state()
  private projectConfig?: ConfigInfo;

  @state()
  private shownFileCount?: number;

  // Private but used in tests.
  @state()
  initialLoadComplete = false;

  // Private but used in tests.
  @state()
  replyDisabled = true;

  // Private but used in tests.
  @state()
  changeStatuses: ChangeStates[] = [];

  @state()
  private updateCheckTimerHandle?: number | null;

  // Private but used in tests.
  getEditMode() {
    if (!this.patchRange || !this.viewState) {
      return false;
    }

    if (this.viewState.edit) {
      return true;
    }

    return this.patchRange.patchNum === EDIT;
  }

  isSubmitEnabled(): boolean {
    return !!(
      this.currentRevisionActions &&
      this.currentRevisionActions.submit &&
      this.currentRevisionActions.submit.enabled
    );
  }

  // Private but used in tests.
  @state()
  mergeable: boolean | null = null;

  /**
   * Plugins can provide (multiple) tabs. For each plugin tab we render an
   * endpoint for the header. If the plugin tab is active, then we also render
   * an endpoint for the content.
   *
   * This is the list of endpoint names for the headers. The header name that
   * the user sees is an implementation detail of the plugin that we don't know.
   */
  // Private but used in tests.
  @state()
  pluginTabsHeaderEndpoints: string[] = [];

  /**
   * Plugins can provide (multiple) tabs. For each plugin tab we render an
   * endpoint for the header. If the plugin tab is active, then we also render
   * an endpoint for the content.
   *
   * This is the list of endpoint names for the content.
   */
  @state()
  private pluginTabsContentEndpoints: string[] = [];

  @state()
  private currentRobotCommentsPatchSet?: PatchSetNum;

  // TODO(milutin) - remove once new gr-dialog will do it out of the box
  // This removes rest of page from a11y tree, when reply dialog is open
  @state()
  private changeViewAriaHidden = false;

  /**
   * This can be a string only for plugin provided tabs.
   */
  // visible for testing
  @state()
  activeTab: Tab | string = Tab.FILES;

  @property({type: Boolean})
  unresolvedOnly = true;

  @state()
  private showAllRobotComments = false;

  @state()
  private showRobotCommentsButton = false;

  @state()
  private draftCount = 0;

  private throttledToggleChangeStar?: (e: KeyboardEvent) => void;

  @state()
  private showChecksTab = false;

  // visible for testing
  @state()
  showFindingsTab = false;

  @state()
  private isViewCurrent = false;

  @state()
  private tabState?: TabState;

  @state()
  private revertedChange?: ChangeInfo;

  // Private but used in tests.
  @state()
  scrollCommentId?: UrlEncodedCommentId;

  /** Just reflects the `opened` prop of the overlay. */
  @state()
  private replyOverlayOpened = false;

  // Accessed in tests.
  readonly reporting = getAppContext().reportingService;

  readonly jsAPI = getAppContext().jsApiService;

  private readonly getChecksModel = resolve(this, checksModelToken);

  readonly restApiService = getAppContext().restApiService;

  // Private but used in tests.
  readonly userModel = getAppContext().userModel;

  // Private but used in tests.
  readonly getChangeModel = resolve(this, changeModelToken);

  private readonly routerModel = getAppContext().routerModel;

  // Private but used in tests.
  readonly getCommentsModel = resolve(this, commentsModelToken);

  private readonly getConfigModel = resolve(this, configModelToken);

  private readonly getFilesModel = resolve(this, filesModelToken);

  private readonly getViewModel = resolve(this, changeViewModelToken);

  private readonly getShortcutsService = resolve(this, shortcutsServiceToken);

  private replyRefitTask?: DelayedTask;

  private scrollTask?: DelayedTask;

  private lastStarredTimestamp?: number;

  private diffViewMode?: DiffViewMode;

  /**
   * If the user comes back to the change page we want to remember the scroll
   * position when we re-render the page as is.
   */
  private scrollPosition?: number;

  private connected$ = new BehaviorSubject(false);

  /**
   * For `connectedCallback()` to distinguish between connecting to the DOM for
   * the first time or if just re-connecting.
   */
  private isFirstConnection = true;

  /** Simply reflects the router-model value. */
  // visible for testing
  routerPatchNum?: RevisionPatchSetNum;

  private readonly shortcutsController = new ShortcutController(this);

  private readonly getNavigation = resolve(this, navigationToken);

  constructor() {
    super();
    this.setupListeners();
    this.setupShortcuts();
    this.setupSubscriptions();
  }

  private setupListeners() {
    this.addEventListener(
      // When an overlay is opened in a mobile viewport, the overlay has a full
      // screen view. When it has a full screen view, we do not want the
      // background to be scrollable. This will eliminate background scroll by
      // hiding most of the contents on the screen upon opening, and showing
      // again upon closing.
      'fullscreen-overlay-opened',
      () => this.handleHideBackgroundContent()
    );
    this.addEventListener('fullscreen-overlay-closed', () =>
      this.handleShowBackgroundContent()
    );
    this.addEventListener('open-reply-dialog', () => this.openReplyDialog());
    this.addEventListener('change-message-deleted', () => fireReload(this));
    this.addEventListener('editable-content-save', e =>
      this.handleCommitMessageSave(e)
    );
    this.addEventListener('editable-content-cancel', () =>
      this.handleCommitMessageCancel()
    );
    this.addEventListener('open-fix-preview', e => this.onOpenFixPreview(e));
    this.addEventListener('close-fix-preview', e => this.onCloseFixPreview(e));

    this.addEventListener(EventType.SHOW_TAB, e => this.setActiveTab(e));
    this.addEventListener('reload', e => {
      this.loadData(
        /* isLocationChange= */ false,
        /* clearPatchset= */ e.detail && e.detail.clearPatchset
      );
    });
  }

  private setupShortcuts() {
    // TODO: Do we still need docOnly bindings?
    this.shortcutsController.addAbstract(Shortcut.EMOJI_DROPDOWN, () => {}); // docOnly
    this.shortcutsController.addAbstract(Shortcut.MENTIONS_DROPDOWN, () => {}); // docOnly
    this.shortcutsController.addAbstract(Shortcut.REFRESH_CHANGE, () =>
      fireReload(this, true)
    );
    this.shortcutsController.addAbstract(Shortcut.OPEN_REPLY_DIALOG, () =>
      this.handleOpenReplyDialog()
    );
    this.shortcutsController.addAbstract(Shortcut.OPEN_DOWNLOAD_DIALOG, () =>
      this.handleOpenDownloadDialog()
    );
    this.shortcutsController.addAbstract(Shortcut.TOGGLE_DIFF_MODE, () =>
      this.handleToggleDiffMode()
    );
    this.shortcutsController.addAbstract(Shortcut.TOGGLE_CHANGE_STAR, e => {
      if (this.throttledToggleChangeStar) {
        this.throttledToggleChangeStar(e);
      }
    });
    this.shortcutsController.addAbstract(Shortcut.UP_TO_DASHBOARD, () =>
      this.determinePageBack()
    );
    this.shortcutsController.addAbstract(Shortcut.EXPAND_ALL_MESSAGES, () =>
      this.handleExpandAllMessages()
    );
    this.shortcutsController.addAbstract(Shortcut.COLLAPSE_ALL_MESSAGES, () =>
      this.handleCollapseAllMessages()
    );
    this.shortcutsController.addAbstract(Shortcut.OPEN_DIFF_PREFS, () =>
      this.handleOpenDiffPrefsShortcut()
    );
    this.shortcutsController.addAbstract(Shortcut.EDIT_TOPIC, () => {
      assertIsDefined(this.metadata);
      this.metadata.editTopic();
    });
    this.shortcutsController.addAbstract(Shortcut.DIFF_AGAINST_BASE, () =>
      this.handleDiffAgainstBase()
    );
    this.shortcutsController.addAbstract(Shortcut.DIFF_AGAINST_LATEST, () =>
      this.handleDiffAgainstLatest()
    );
    this.shortcutsController.addAbstract(Shortcut.DIFF_BASE_AGAINST_LEFT, () =>
      this.handleDiffBaseAgainstLeft()
    );
    this.shortcutsController.addAbstract(
      Shortcut.DIFF_RIGHT_AGAINST_LATEST,
      () => this.handleDiffRightAgainstLatest()
    );
    this.shortcutsController.addAbstract(
      Shortcut.DIFF_BASE_AGAINST_LATEST,
      () => this.handleDiffBaseAgainstLatest()
    );
    this.shortcutsController.addAbstract(Shortcut.OPEN_SUBMIT_DIALOG, () =>
      this.handleOpenSubmitDialog()
    );
    this.shortcutsController.addAbstract(Shortcut.TOGGLE_ATTENTION_SET, () =>
      this.handleToggleAttentionSet()
    );
    this.shortcutsController.addAbstract(
      Shortcut.OPEN_COPY_LINKS_DROPDOWN,
      () => this.copyLinksDropdown?.openDropdown()
    );
  }

  private setupSubscriptions() {
    subscribe(
      this,
      () => this.getViewModel().state$,
      s => (this.viewState = s)
    );
    subscribe(
      this,
      () => this.getViewModel().tab$,
      t => (this.activeTab = t ?? Tab.FILES)
    );
    subscribe(
      this,
      () => this.getChecksModel().aPluginHasRegistered$,
      b => {
        this.showChecksTab = b;
      }
    );
    subscribe(
      this,
      () => this.getCommentsModel().robotCommentCount$,
      count => {
        this.showFindingsTab = count > 0;
      }
    );
    subscribe(
      this,
      () => this.routerModel.routerView$,
      view => {
        this.isViewCurrent = view === GerritView.CHANGE;
      }
    );
    subscribe(
      this,
      () => this.routerModel.routerPatchNum$,
      patchNum => {
        this.routerPatchNum = patchNum;
      }
    );
    subscribe(
      this,
      () => this.getCommentsModel().drafts$,
      drafts => {
        this.diffDrafts = {...drafts};
      }
    );
    subscribe(
      this,
      () => this.userModel.preferenceDiffViewMode$,
      diffViewMode => {
        this.diffViewMode = diffViewMode;
      }
    );
    subscribe(
      this,
      () => this.getCommentsModel().draftsCount$,
      draftCount => {
        this.draftCount = draftCount;
      }
    );
    subscribe(
      this,
      () => this.getCommentsModel().threads$,
      threads => {
        this.commentThreads = threads;
      }
    );
    subscribe(
      this,
      () => this.getChangeModel().change$,
      change => {
        // The change view is tied to a specific change number, so don't update
        // change to undefined.
        if (change) this.change = change;
      }
    );
    subscribe(
      this,
      () => this.userModel.account$,
      account => {
        this.account = account;
      }
    );
    subscribe(
      this,
      () => this.userModel.loggedIn$,
      loggedIn => {
        this.loggedIn = loggedIn;
      }
    );
    subscribe(
      this,
      () => this.getConfigModel().serverConfig$,
      config => {
        this.serverConfig = config;
        this.replyDisabled = false;
      }
    );
    subscribe(
      this,
      () => this.getConfigModel().repoConfig$,
      config => {
        this.projectConfig = config;
      }
    );
  }

  override connectedCallback() {
    super.connectedCallback();
    this.firstConnectedCallback();
    this.connected$.next(true);

    // Make sure to reverse everything below this line in disconnectedCallback().
    // Or consider using either firstConnectedCallback() or constructor().
    document.addEventListener('visibilitychange', this.handleVisibilityChange);
    document.addEventListener('scroll', this.handleScroll);
  }

  override firstUpdated() {
    // _onTabSizingChanged is called when iron-items-changed event is fired
    // from iron-selectable but that is called before the element is present
    // in view which whereas the method requires paper tabs already be visible
    // as it relies on dom rect calculation.
    // _onTabSizingChanged ensures the primary tab(Files/Comments/Checks) is
    // underlined.
    assertIsDefined(this.tabs, 'tabs');
    whenVisible(this.tabs, () => this.tabs!._onTabSizingChanged());
  }

  /**
   * For initialization that should only happen once, not again when
   * re-connecting to the DOM later.
   */
  private firstConnectedCallback() {
    if (!this.isFirstConnection) return;
    this.isFirstConnection = false;

    getPluginLoader()
      .awaitPluginsLoaded()
      .then(() => {
        this.pluginTabsHeaderEndpoints =
          getPluginEndpoints().getDynamicEndpoints('change-view-tab-header');
        this.pluginTabsContentEndpoints =
          getPluginEndpoints().getDynamicEndpoints('change-view-tab-content');
        if (
          this.pluginTabsContentEndpoints.length !==
          this.pluginTabsHeaderEndpoints.length
        ) {
          this.reporting.error(
            'Plugin change-view-tab',
            new Error('Mismatch of headers and content.')
          );
        }
      })
      .then(() => this.initActiveTab());

    this.throttledToggleChangeStar = throttleWrap<KeyboardEvent>(_ =>
      this.handleToggleChangeStar()
    );
  }

  override disconnectedCallback() {
    document.removeEventListener(
      'visibilitychange',
      this.handleVisibilityChange
    );
    document.removeEventListener('scroll', this.handleScroll);
    this.replyRefitTask?.cancel();
    this.scrollTask?.cancel();

    if (this.updateCheckTimerHandle) {
      this.cancelUpdateCheckTimer();
    }
    this.connected$.next(false);
    super.disconnectedCallback();
  }

  protected override willUpdate(changedProperties: PropertyValues): void {
    if (
      changedProperties.has('change') ||
      changedProperties.has('mergeable') ||
      changedProperties.has('currentRevisionActions')
    ) {
      this.changeStatuses = this.computeChangeStatusChips();
    }
  }

  static override get styles() {
    return [
      a11yStyles,
      paperStyles,
      sharedStyles,
      css`
        .container:not(.loading) {
          background-color: var(--background-color-tertiary);
        }
        .container.loading {
          color: var(--deemphasized-text-color);
          padding: var(--spacing-l);
        }
        .header {
          align-items: center;
          background-color: var(--background-color-primary);
          border-bottom: 1px solid var(--border-color);
          display: flex;
          padding: var(--spacing-s) var(--spacing-l);
          z-index: 99; /* Less than gr-overlay's backdrop */
        }
        .header.editMode {
          background-color: var(--edit-mode-background-color);
        }
        .header .download {
          margin-right: var(--spacing-l);
        }
        gr-change-status {
          margin-left: var(--spacing-s);
        }
        gr-change-status:first-child {
          margin-left: 0;
        }
        .headerTitle {
          align-items: center;
          display: flex;
          flex: 1;
        }
        .headerSubject {
          font-family: var(--header-font-family);
          font-size: var(--font-size-h3);
          font-weight: var(--font-weight-h3);
          line-height: var(--line-height-h3);
          margin-left: var(--spacing-l);
        }
        .changeNumberColon {
          color: transparent;
        }
        .changeCopyClipboard {
          margin-left: var(--spacing-s);
        }
        .showCopyLinkDialogButton {
          --gr-button-padding: 0 0 0 var(--spacing-s);
          --background-color: transparent;
          margin-left: var(--spacing-s);
        }
        #replyBtn {
          margin-bottom: var(--spacing-m);
        }
        gr-change-star {
          margin-left: var(--spacing-s);
        }
        .showCopyLinkDialogButton gr-change-star {
          margin-left: 0;
        }
        a.changeNumber {
          margin-left: var(--spacing-xs);
        }
        gr-reply-dialog {
          width: 60em;
        }
        .changeStatus {
          text-transform: capitalize;
        }
        /* Strong specificity here is needed due to
            https://github.com/Polymer/polymer/issues/2531 */
        .container .changeInfo {
          display: flex;
          background-color: var(--background-color-secondary);
          padding-right: var(--spacing-m);
        }
        .changeId {
          color: var(--deemphasized-text-color);
          font-family: var(--font-family);
          margin-top: var(--spacing-l);
        }
        section {
          background-color: var(--view-background-color);
          box-shadow: var(--elevation-level-1);
        }
        .changeMetadata {
          /* Limit meta section to half of the screen at max */
          max-width: 50%;
        }
        .commitMessage {
          font-family: var(--monospace-font-family);
          font-size: var(--font-size-mono);
          line-height: var(--line-height-mono);
          margin-right: var(--spacing-l);
          margin-bottom: var(--spacing-l);
          /* Account for border and padding and rounding errors. */
          max-width: calc(72ch + 2px + 2 * var(--spacing-m) + 0.4px);
        }
        .commitMessage gr-formatted-text {
          word-break: break-word;
        }
        #commitMessageEditor {
          /* Account for border and padding and rounding errors. */
          min-width: calc(72ch + 2px + 2 * var(--spacing-m) + 0.4px);
          --collapsed-max-height: 300px;
        }
        .changeStatuses,
        .commitActions {
          align-items: center;
          display: flex;
        }
        .changeStatuses {
          flex-wrap: wrap;
        }
        .mainChangeInfo {
          display: flex;
          flex: 1;
          flex-direction: column;
          min-width: 0;
        }
        #commitAndRelated {
          align-content: flex-start;
          display: flex;
          flex: 1;
          overflow-x: hidden;
        }
        .relatedChanges {
          flex: 0 1 auto;
          overflow: hidden;
          padding: var(--spacing-l) 0;
        }
        .mobile {
          display: none;
        }
        hr {
          border: 0;
          border-top: 1px solid var(--border-color);
          height: 0;
          margin-bottom: var(--spacing-l);
        }
        .emptySpace {
          flex-grow: 1;
        }
        .commitContainer {
          display: flex;
          flex-direction: column;
          flex-shrink: 0;
          margin: var(--spacing-l) 0;
          padding: 0 var(--spacing-l);
        }
        .showOnEdit {
          display: none;
        }
        .scrollable {
          overflow: auto;
        }
        .text {
          white-space: pre;
        }
        gr-commit-info {
          display: inline-block;
        }
        paper-tabs {
          background-color: var(--background-color-tertiary);
          margin-top: var(--spacing-m);
          height: calc(var(--line-height-h3) + var(--spacing-m));
          --paper-tabs-selection-bar-color: var(--link-color);
        }
        paper-tab {
          box-sizing: border-box;
          max-width: 12em;
          --paper-tab-ink: var(--link-color);
          --paper-font-common-base_-_font-family: var(--header-font-family);
          --paper-font-common-base_-_-webkit-font-smoothing: initial;
          --paper-tab-content_-_margin-bottom: var(--spacing-s);
          /* paper-tabs uses 700 here, which can look awkward */
          --paper-tab-content-focused_-_font-weight: var(--font-weight-h3);
          --paper-tab-content-focused_-_background: var(
            --gray-background-focus
          );
          --paper-tab-content-unselected_-_opacity: 1;
          --paper-tab-content-unselected_-_color: var(
            --deemphasized-text-color
          );
        }
        gr-thread-list,
        gr-messages-list {
          display: block;
        }
        gr-thread-list {
          min-height: 250px;
        }
        #includedInOverlay {
          width: 65em;
        }
        #uploadHelpOverlay {
          width: 50em;
        }
        #metadata {
          --metadata-horizontal-padding: var(--spacing-l);
          padding-top: var(--spacing-l);
          width: 100%;
        }
        gr-change-summary {
          margin-left: var(--spacing-m);
        }
        @media screen and (max-width: 75em) {
          .relatedChanges {
            padding: 0;
          }
          #relatedChanges {
            padding-top: var(--spacing-l);
          }
          #commitAndRelated {
            flex-direction: column;
            flex-wrap: nowrap;
          }
          #commitMessageEditor {
            min-width: 0;
          }
          .commitMessage {
            margin-right: 0;
          }
          .mainChangeInfo {
            padding-right: 0;
          }
        }
        @media screen and (max-width: 50em) {
          .mobile {
            display: block;
          }
          .header {
            align-items: flex-start;
            flex-direction: column;
            flex: 1;
            padding: var(--spacing-s) var(--spacing-l);
          }
          .headerTitle {
            flex-wrap: wrap;
            font-family: var(--header-font-family);
            font-size: var(--font-size-h3);
            font-weight: var(--font-weight-h3);
            line-height: var(--line-height-h3);
          }
          .desktop {
            display: none;
          }
          .reply {
            display: block;
            margin-right: 0;
            /* px because don't have the same font size */
            margin-bottom: 6px;
          }
          .changeInfo-column:not(:last-of-type) {
            margin-right: 0;
            padding-right: 0;
          }
          .changeInfo,
          #commitAndRelated {
            flex-direction: column;
            flex-wrap: nowrap;
          }
          .commitContainer {
            margin: 0;
            padding: var(--spacing-l);
          }
          .changeMetadata {
            margin-top: var(--spacing-xs);
            max-width: none;
          }
          #metadata,
          .mainChangeInfo {
            padding: 0;
          }
          .commitActions {
            display: block;
            margin-top: var(--spacing-l);
            width: 100%;
          }
          .commitMessage {
            flex: initial;
            margin: 0;
          }
          /* Change actions are the only thing thant need to remain visible due
            to the fact that they may have the currently visible overlay open. */
          #mainContent.overlayOpen .hideOnMobileOverlay {
            display: none;
          }
          gr-reply-dialog {
            height: 100vh;
            min-width: initial;
            width: 100vw;
          }
          #replyOverlay {
            z-index: var(--reply-overlay-z-index);
          }
        }
        .patch-set-dropdown {
          margin: var(--spacing-m) 0 0 var(--spacing-m);
        }
        .show-robot-comments {
          margin: var(--spacing-m);
        }
        .tabContent gr-thread-list::part(threads) {
          padding: var(--spacing-l);
        }
      `,
    ];
  }

  override render() {
    return html`${this.renderLoading()}${this.renderMainContent()}`;
  }

  private renderLoading() {
    if (!this.loading) return nothing;
    return html`
      <div class="container loading" ?hidden=${!this.loading}>Loading...</div>
    `;
  }

  private renderMainContent() {
    return html`
      <div
        id="mainContent"
        class="container"
        ?hidden=${this.loading}
        aria-hidden=${this.changeViewAriaHidden ? 'true' : 'false'}
      >
        ${this.renderChangeInfoSection()}
        <h2 class="assistive-tech-only">Files and Comments tabs</h2>
        ${this.renderTabHeaders()} ${this.renderTabContent()}
        ${this.renderChangeLog()}
      </div>
      <gr-apply-fix-dialog
        id="applyFixDialog"
        .change=${this.change}
        .changeNum=${this.changeNum}
      ></gr-apply-fix-dialog>
      <gr-overlay id="downloadOverlay" with-backdrop="">
        <gr-download-dialog
          id="downloadDialog"
          .change=${this.change}
          .config=${this.serverConfig?.download}
          @close=${this.handleDownloadDialogClose}
        ></gr-download-dialog>
      </gr-overlay>
      <gr-overlay id="includedInOverlay" with-backdrop="">
        <gr-included-in-dialog
          id="includedInDialog"
          .changeNum=${this.changeNum}
          @close=${this.handleIncludedInDialogClose}
        ></gr-included-in-dialog>
      </gr-overlay>
      <gr-overlay
        id="replyOverlay"
        class="scrollable"
        no-cancel-on-outside-click=""
        no-cancel-on-esc-key=""
        scroll-action="lock"
        with-backdrop=""
        @iron-overlay-canceled=${this.onReplyOverlayCanceled}
        @opened-changed=${this.onReplyOverlayOpenedChanged}
      >
        ${when(
          this.replyOverlayOpened && this.loggedIn,
          () => html`
            <gr-reply-dialog
              id="replyDialog"
              .patchNum=${computeLatestPatchNum(this.allPatchSets)}
              .permittedLabels=${this.change?.permitted_labels}
              .projectConfig=${this.projectConfig}
              .canBeStarted=${this.canStartReview()}
              @send=${this.handleReplySent}
              @cancel=${this.handleReplyCancel}
              @autogrow=${this.handleReplyAutogrow}
              @send-disabled-changed=${this.resetReplyOverlayFocusStops}
            >
            </gr-reply-dialog>
          `
        )}
      </gr-overlay>
    `;
  }

  private renderChangeInfoSection() {
    return html`<section class="changeInfoSection">
      <div class=${this.computeHeaderClass()}>
        <h1 class="assistive-tech-only">
          Change ${this.change?._number}: ${this.change?.subject}
        </h1>
        ${this.renderHeaderTitle()} ${this.renderCommitActions()}
      </div>
      <h2 class="assistive-tech-only">Change metadata</h2>
      ${this.renderChangeInfo()}
    </section>`;
  }

  private renderHeaderTitle() {
    const resolveWeblinks = this.commitInfo?.resolve_conflicts_web_links ?? [];
    return html` <div class="headerTitle">
      <div class="changeStatuses">
        ${this.changeStatuses.map(
          status => html` <gr-change-status
            .change=${this.change}
            .revertedChange=${this.revertedChange}
            .status=${status}
            .resolveWeblinks=${resolveWeblinks}
          ></gr-change-status>`
        )}
      </div>
      ${this.renderCopyLinksDropdown()}
      <gr-button
        flatten
        down-arrow
        class="showCopyLinkDialogButton"
        @click=${() => this.copyLinksDropdown?.toggleDropdown()}
        ><gr-change-star
          id="changeStar"
          .change=${this.change}
          @toggle-star=${(e: CustomEvent<ChangeStarToggleStarDetail>) =>
            this.handleToggleStar(e)}
          ?hidden=${!this.loggedIn}
        ></gr-change-star>
        <a
          class="changeNumber"
          aria-label=${`Change ${this.change?._number}`}
          href=${ifDefined(this.computeChangeUrl(true))}
          @click=${(e: MouseEvent) => e.stopPropagation()}
          >${this.change?._number}</a
        >
      </gr-button>
      <span class="headerSubject">${this.change?.subject}</span>
      <gr-copy-clipboard
        class="changeCopyClipboard"
        hideInput=""
        text=${this.computeCopyTextForTitle()}
      >
      </gr-copy-clipboard>
    </div>`;
  }

  private renderCopyLinksDropdown() {
    const url = this.computeChangeUrl();
    if (!url) return;
    const changeURL = prependOrigin(getBaseUrl() + url);
    const links: CopyLink[] = [
      {
        label: 'Change Number',
        shortcut: 'n',
        value: `${this.change?._number}`,
      },
      {
        label: 'Change URL',
        shortcut: 'u',
        value: changeURL,
      },
      {
        label: 'Title and URL',
        shortcut: 't',
        value: `${this.change?._number}: ${this.change?.subject} | ${changeURL}`,
      },
      {
        label: 'URL and title',
        shortcut: 'r',
        value: `${changeURL}: ${this.change?.subject}`,
      },
      {
        label: 'Markdown',
        shortcut: 'm',
        value: `[${this.change?.subject}](${changeURL})`,
      },
      {
        label: 'Change-Id',
        shortcut: 'd',
        value: `${this.change?.id.split('~').pop()}`,
      },
    ];
    if (
      this.change?.status === ChangeStatus.MERGED &&
      this.change?.current_revision
    ) {
      links.push({
        label: 'SHA',
        shortcut: 's',
        value: this.change.current_revision,
      });
    }
    return html`<gr-copy-links .copyLinks=${links}> </gr-copy-links>`;
  }

  private renderCommitActions() {
    return html` <div class="commitActions">
      <!-- always show gr-change-actions regardless if logged in or not -->
      <gr-change-actions
        id="actions"
        .change=${this.change}
        .disableEdit=${false}
        .hasParent=${this.hasParent}
        .account=${this.account}
        .changeNum=${this.changeNum}
        .changeStatus=${this.change?.status}
        .commitNum=${this.commitInfo?.commit}
        .commitMessage=${this.latestCommitMessage}
        .editMode=${this.getEditMode()}
        .privateByDefault=${this.projectConfig?.private_by_default}
        .loggedIn=${this.loggedIn}
        @edit-tap=${() => this.handleEditTap()}
        @stop-edit-tap=${() => this.handleStopEditTap()}
        @download-tap=${() => this.handleOpenDownloadDialog()}
        @included-tap=${() => this.handleOpenIncludedInDialog()}
        @revision-actions-changed=${this.handleRevisionActionsChanged}
      ></gr-change-actions>
    </div>`;
  }

  private renderChangeInfo() {
    const hideEditCommitMessage = this.computeHideEditCommitMessage(
      this.loggedIn,
      this.editingCommitMessage,
      this.change,
      this.getEditMode()
    );
    return html` <div class="changeInfo">
      <div class="changeInfo-column changeMetadata hideOnMobileOverlay">
        <gr-change-metadata
          id="metadata"
          .change=${this.change}
          .revertedChange=${this.revertedChange}
          .account=${this.account}
          .revision=${this.selectedRevision}
          .commitInfo=${this.commitInfo}
          .serverConfig=${this.serverConfig}
          .parentIsCurrent=${this.isParentCurrent()}
          .repoConfig=${this.projectConfig}
          @show-reply-dialog=${this.handleShowReplyDialog}
        >
        </gr-change-metadata>
      </div>
      <div id="mainChangeInfo" class="changeInfo-column mainChangeInfo">
        <div id="commitAndRelated" class="hideOnMobileOverlay">
          <div class="commitContainer">
            <h3 class="assistive-tech-only">Commit Message</h3>
            <div>
              <gr-button
                id="replyBtn"
                class="reply"
                title=${this.createTitle(
                  Shortcut.OPEN_REPLY_DIALOG,
                  ShortcutSection.ACTIONS
                )}
                ?hidden=${!this.loggedIn}
                primary=""
                .disabled=${this.replyDisabled}
                @click=${this.handleReplyTap}
                >${this.computeReplyButtonLabel()}</gr-button
              >
            </div>
            <div id="commitMessage" class="commitMessage">
              <gr-editable-content
                id="commitMessageEditor"
                .editing=${this.editingCommitMessage}
                .content=${this.latestCommitMessage}
                @editing-changed=${this.handleEditingChanged}
                @content-changed=${this.handleContentChanged}
                .storageKey=${`c${this.change?._number}_rev${this.change?.current_revision}`}
                .hideEditCommitMessage=${hideEditCommitMessage}
                .commitCollapsible=${this.computeCommitCollapsible()}
                remove-zero-width-space=""
              >
                <gr-formatted-text
                  .content=${this.latestCommitMessage ?? ''}
                  .markdown=${false}
                ></gr-formatted-text>
              </gr-editable-content>
              <div class="changeId" ?hidden=${!this.changeIdCommitMessageError}>
                <hr />
                Change-Id:
                <span
                  class=${this.computeChangeIdClass(
                    this.changeIdCommitMessageError
                  )}
                  title=${this.computeTitleAttributeWarning(
                    this.changeIdCommitMessageError
                  )}
                  >${this.change?.change_id}</span
                >
              </div>
            </div>
            <h3 class="assistive-tech-only">Comments and Checks Summary</h3>
            <gr-change-summary></gr-change-summary>
            <gr-endpoint-decorator name="commit-container">
              <gr-endpoint-param name="change" .value=${this.change}>
              </gr-endpoint-param>
              <gr-endpoint-param
                name="revision"
                .value=${this.selectedRevision}
              >
              </gr-endpoint-param>
            </gr-endpoint-decorator>
          </div>
          <div class="relatedChanges">
            <gr-related-changes-list
              id="relatedChanges"
              .change=${this.change}
              .mergeable=${this.mergeable}
            ></gr-related-changes-list>
          </div>
          <div class="emptySpace"></div>
        </div>
      </div>
    </div>`;
  }

  private renderTabHeaders() {
    return html`
      <paper-tabs
        id="tabs"
        @selected-changed=${this.onPaperTabSelectionChanged}
      >
        <paper-tab @click=${this.onPaperTabClick} data-name=${Tab.FILES}
          ><span>Files</span></paper-tab
        >
        <paper-tab
          @click=${this.onPaperTabClick}
          data-name=${Tab.COMMENT_THREADS}
          class="commentThreads"
        >
          <gr-tooltip-content
            has-tooltip
            title=${ifDefined(this.computeTotalCommentCounts())}
          >
            <span>Comments</span></gr-tooltip-content
          >
        </paper-tab>
        ${when(
          this.showChecksTab,
          () => html`
            <paper-tab data-name=${Tab.CHECKS} @click=${this.onPaperTabClick}
              ><span>Checks</span></paper-tab
            >
          `
        )}
        ${this.pluginTabsHeaderEndpoints.map(
          tabHeader => html`
            <paper-tab data-name=${tabHeader}>
              <gr-endpoint-decorator name=${tabHeader}>
                <gr-endpoint-param name="change" .value=${this.change}>
                </gr-endpoint-param>
                <gr-endpoint-param
                  name="revision"
                  .value=${this.selectedRevision}
                >
                </gr-endpoint-param>
              </gr-endpoint-decorator>
            </paper-tab>
          `
        )}
        ${when(
          this.showFindingsTab,
          () => html`
            <paper-tab data-name=${Tab.FINDINGS} @click=${this.onPaperTabClick}>
              <span>Findings</span>
            </paper-tab>
          `
        )}
      </paper-tabs>
    `;
  }

  private renderTabContent() {
    return html`
      <section class="tabContent">
        ${this.renderFilesTab()} ${this.renderCommentsTab()}
        ${this.renderChecksTab()} ${this.renderFindingsTab()}
        ${this.renderPluginTab()}
      </section>
    `;
  }

  private renderFilesTab() {
    return html`
      <div ?hidden=${this.activeTab !== Tab.FILES}>
        <gr-file-list-header
          id="fileListHeader"
          .account=${this.account}
          .change=${this.change}
          .changeNum=${this.changeNum}
          .commitInfo=${this.commitInfo}
          .changeUrl=${this.computeChangeUrl()}
          .editMode=${this.getEditMode()}
          .loggedIn=${this.loggedIn}
          .shownFileCount=${this.shownFileCount}
          .filesExpanded=${this.fileList?.filesExpanded}
          @open-diff-prefs=${this.handleOpenDiffPrefs}
          @open-download-dialog=${this.handleOpenDownloadDialog}
          @expand-diffs=${this.expandAllDiffs}
          @collapse-diffs=${this.collapseAllDiffs}
        >
        </gr-file-list-header>
        <gr-file-list
          id="fileList"
          class="hideOnMobileOverlay"
          .change=${this.change}
          .changeNum=${this.changeNum}
          .editMode=${this.getEditMode()}
          @files-shown-changed=${(e: CustomEvent<{length: number}>) => {
            this.shownFileCount = e.detail.length;
          }}
          @files-expanded-changed=${(
            _e: ValueChangedEvent<FilesExpandedState>
          ) => {
            this.requestUpdate();
          }}
          @file-action-tap=${this.handleFileActionTap}
        >
        </gr-file-list>
      </div>
    `;
  }

  private renderCommentsTab() {
    if (this.activeTab !== Tab.COMMENT_THREADS) return nothing;
    return html`
      <h3 class="assistive-tech-only">Comments</h3>
      <gr-thread-list
        .threads=${this.commentThreads}
        .commentTabState=${this.tabState}
        only-show-robot-comments-with-human-reply
        .unresolvedOnly=${this.unresolvedOnly}
        .scrollCommentId=${this.scrollCommentId}
        show-comment-context
      ></gr-thread-list>
    `;
  }

  private renderChecksTab() {
    if (this.activeTab !== Tab.CHECKS) return nothing;
    return html`
      <h3 class="assistive-tech-only">Checks</h3>
      <gr-checks-tab id="checksTab" .tabState=${this.tabState}></gr-checks-tab>
    `;
  }

  private renderFindingsTab() {
    if (this.activeTab !== Tab.FINDINGS) return nothing;
    if (!this.showFindingsTab) return nothing;
    const robotCommentThreads = this.computeRobotCommentThreads();
    const robotCommentsPatchSetDropdownItems =
      this.computeRobotCommentsPatchSetDropdownItems();
    return html`
      <gr-dropdown-list
        class="patch-set-dropdown"
        .items=${robotCommentsPatchSetDropdownItems}
        .value=${this.currentRobotCommentsPatchSet}
        @value-change=${this.handleRobotCommentPatchSetChanged}
      >
      </gr-dropdown-list>
      <gr-thread-list .threads=${robotCommentThreads} hide-dropdown>
      </gr-thread-list>
      ${when(
        this.showRobotCommentsButton,
        () => html`
          <gr-button
            class="show-robot-comments"
            @click=${this.toggleShowRobotComments}
          >
            ${this.showAllRobotComments ? 'Show Less' : 'Show more'}
          </gr-button>
        `
      )}
    `;
  }

  private renderPluginTab() {
    const i = this.pluginTabsHeaderEndpoints.findIndex(
      t => this.activeTab === t
    );
    if (i === -1) return nothing;
    const pluginTabContentEndpoint = this.pluginTabsContentEndpoints[i];
    return html`
      <gr-endpoint-decorator .name=${pluginTabContentEndpoint}>
        <gr-endpoint-param name="change" .value=${this.change}>
        </gr-endpoint-param>
        <gr-endpoint-param name="revision" .value=${this.selectedRevision}></gr-endpoint-param>
        </gr-endpoint-param>
      </gr-endpoint-decorator>
    `;
  }

  private renderChangeLog() {
    return html`
      <gr-endpoint-decorator name="change-view-integration">
        <gr-endpoint-param name="change" .value=${this.change}>
        </gr-endpoint-param>
        <gr-endpoint-param name="revision" .value=${this.selectedRevision}>
        </gr-endpoint-param>
      </gr-endpoint-decorator>

      <paper-tabs>
        <paper-tab data-name="_changeLog" class="changeLog">
          Change Log
        </paper-tab>
      </paper-tabs>
      <section class="changeLog">
        <h2 class="assistive-tech-only">Change Log</h2>
        <gr-messages-list
          class="hideOnMobileOverlay"
          .labels=${this.change?.labels}
          .messages=${this.change?.messages}
          .reviewerUpdates=${this.change?.reviewer_updates}
          @message-anchor-tap=${this.handleMessageAnchorTap}
          @reply=${this.handleMessageReply}
        ></gr-messages-list>
      </section>
    `;
  }

  private readonly handleScroll = () => {
    if (!this.isViewCurrent) return;
    this.scrollTask = debounce(
      this.scrollTask,
      () => (this.scrollPosition = document.documentElement.scrollTop),
      150
    );
  };

  private onOpenFixPreview(e: OpenFixPreviewEvent) {
    assertIsDefined(this.applyFixDialog);
    this.applyFixDialog.open(e);
  }

  private onCloseFixPreview(e: CloseFixPreviewEvent) {
    if (e.detail.fixApplied) fireReload(this);
  }

  // Private but used in tests.
  handleToggleDiffMode() {
    if (this.diffViewMode === DiffViewMode.SIDE_BY_SIDE) {
      this.userModel.updatePreferences({diff_view: DiffViewMode.UNIFIED});
    } else {
      this.userModel.updatePreferences({
        diff_view: DiffViewMode.SIDE_BY_SIDE,
      });
    }
  }

  onPaperTabSelectionChanged(e: ValueChangedEvent) {
    if (!this.tabs) return;
    const tabs = [...queryAll<HTMLElement>(this.tabs, 'paper-tab')];
    if (!tabs) return;

    const tabIndex = Number(e.detail.value);
    assert(
      Number.isInteger(tabIndex) && 0 <= tabIndex && tabIndex < tabs.length,
      `${tabIndex} must be integer`
    );
    const tab = tabs[tabIndex].dataset['name'];

    this.getViewModel().updateState({tab});
  }

  setActiveTab(e: SwitchTabEvent) {
    if (!this.tabs) return;
    const tabs = [...queryAll<HTMLElement>(this.tabs, 'paper-tab')];
    if (!tabs) return;

    const tab = e.detail.tab;
    const tabIndex = tabs.findIndex(t => t.dataset['name'] === tab);
    assert(tabIndex !== -1, `tab ${tab} not found`);

    if (this.tabs.selected !== tabIndex) {
      this.tabs.selected = tabIndex;
    }

    this.getViewModel().updateState({tab});

    if (e.detail.tabState) this.tabState = e.detail.tabState;
    if (e.detail.scrollIntoView) this.tabs.scrollIntoView({block: 'center'});
  }

  /**
   * Currently there is a bug in this code where this.unresolvedOnly is only
   * assigned the correct value when onPaperTabClick is triggered which is
   * only triggered when user explicitly clicks on the tab however the comments
   * tab can also be opened via the url in which case the correct value to
   * unresolvedOnly is never assigned.
   */
  private onPaperTabClick(e: MouseEvent) {
    let target = e.target as HTMLElement | null;
    let tabName: string | undefined;
    // target can be slot child of papertab, so we search for tabName in parents
    do {
      tabName = target?.dataset?.['name'];
      if (tabName) break;
      target = target?.parentElement as HTMLElement | null;
    } while (target);

    if (tabName === Tab.COMMENT_THREADS) {
      // Show unresolved threads by default
      // Show resolved threads only if no unresolved threads exist
      const hasUnresolvedThreads =
        (this.commentThreads ?? []).filter(thread => isUnresolved(thread))
          .length > 0;
      if (!hasUnresolvedThreads) this.unresolvedOnly = false;
    }

    this.reporting.reportInteraction(Interaction.SHOW_TAB, {
      tabName,
      src: 'paper-tab-click',
    });
  }

  private handleEditingChanged(e: ValueChangedEvent<boolean>) {
    this.editingCommitMessage = e.detail.value;
  }

  private handleContentChanged(e: ValueChangedEvent) {
    this.latestCommitMessage = e.detail.value;
  }

  // Private but used in tests.
  handleCommitMessageSave(e: EditableContentSaveEvent) {
    assertIsDefined(this.change, 'change');
    assertIsDefined(this.changeNum, 'changeNum');
    // to prevent 2 requests at the same time
    if (!this.commitMessageEditor || this.commitMessageEditor.disabled) return;
    // Trim trailing whitespace from each line.
    const message = e.detail.content.replace(TRAILING_WHITESPACE_REGEX, '');

    this.jsAPI.handleCommitMessage(this.change, message);

    this.commitMessageEditor.disabled = true;
    this.restApiService
      .putChangeCommitMessage(this.changeNum, message)
      .then(resp => {
        assertIsDefined(this.commitMessageEditor);
        this.commitMessageEditor.disabled = false;
        if (!resp.ok) {
          return;
        }

        this.latestCommitMessage = this.prepareCommitMsgForLinkify(message);
        this.editingCommitMessage = false;
        this.reloadWindow();
      })
      .catch(() => {
        assertIsDefined(this.commitMessageEditor);
        this.commitMessageEditor.disabled = false;
      });
  }

  private reloadWindow() {
    windowLocationReload();
  }

  private handleCommitMessageCancel() {
    this.editingCommitMessage = false;
  }

  private computeChangeStatusChips() {
    if (!this.change) {
      return [];
    }

    // Show no chips until mergeability is loaded.
    if (this.mergeable === null) {
      return [];
    }

    const options = {
      includeDerived: true,
      mergeable: !!this.mergeable,
      submitEnabled: !!this.isSubmitEnabled(),
    };
    return changeStatuses(this.change as ChangeInfo, options);
  }

  // Private but used in tests.
  computeHideEditCommitMessage(
    loggedIn: boolean,
    editing: boolean,
    change?: ParsedChangeInfo,
    editMode?: boolean
  ) {
    if (
      !loggedIn ||
      editing ||
      (change && change.status === ChangeStatus.MERGED) ||
      editMode
    ) {
      return true;
    }

    return false;
  }

  // Private but used in tests.
  robotCommentCountPerPatchSet(threads: CommentThread[]) {
    return threads.reduce((robotCommentCountMap, thread) => {
      const comments = thread.comments;
      const robotCommentsCount = comments.reduce(
        (acc, comment) => (isRobot(comment) ? acc + 1 : acc),
        0
      );
      if (comments[0].patch_set)
        robotCommentCountMap[`${comments[0].patch_set}`] =
          (robotCommentCountMap[`${comments[0].patch_set}`] || 0) +
          robotCommentsCount;
      return robotCommentCountMap;
    }, {} as {[patchset: string]: number});
  }

  // Private but used in tests.
  computeText(
    patch: RevisionInfo | EditRevisionInfo,
    commentThreads: CommentThread[]
  ) {
    const commentCount = this.robotCommentCountPerPatchSet(commentThreads);
    const commentCnt = commentCount[patch._number] || 0;
    if (commentCnt === 0) return `Patchset ${patch._number}`;
    return `Patchset ${patch._number} (${pluralize(commentCnt, 'finding')})`;
  }

  private computeRobotCommentsPatchSetDropdownItems() {
    if (!this.change || !this.commentThreads || !this.change.revisions)
      return [];

    return Object.values(this.change.revisions)
      .filter(patch => patch._number !== EDIT)
      .map(patch => {
        return {
          text: this.computeText(patch, this.commentThreads!),
          value: patch._number,
        };
      })
      .sort((a, b) => (b.value as number) - (a.value as number));
  }

  private handleRobotCommentPatchSetChanged(e: CustomEvent<{value: string}>) {
    const patchSet = Number(e.detail.value) as PatchSetNum;
    if (patchSet === this.currentRobotCommentsPatchSet) return;
    this.currentRobotCommentsPatchSet = patchSet;
  }

  private toggleShowRobotComments() {
    this.showAllRobotComments = !this.showAllRobotComments;
  }

  // Private but used in tests.
  computeRobotCommentThreads() {
    if (!this.commentThreads || !this.currentRobotCommentsPatchSet) return [];
    const threads = this.commentThreads.filter(thread => {
      const comments = thread.comments || [];
      return (
        comments.length &&
        isRobot(comments[0]) &&
        comments[0].patch_set === this.currentRobotCommentsPatchSet
      );
    });
    this.showRobotCommentsButton = threads.length > ROBOT_COMMENTS_LIMIT;
    return threads.slice(
      0,
      this.showAllRobotComments ? undefined : ROBOT_COMMENTS_LIMIT
    );
  }

  private computeTotalCommentCounts() {
    const unresolvedCount = this.change?.unresolved_comment_count ?? 0;
    const draftCount = this.draftCount;
    const unresolvedString =
      unresolvedCount === 0 ? '' : `${unresolvedCount} unresolved`;
    const draftString = pluralize(draftCount, 'draft');

    return (
      unresolvedString +
      // Add a comma and space if both unresolved and draft comments exist.
      (unresolvedString && draftString ? ', ' : '') +
      draftString
    );
  }

  private handleReplyTap(e: MouseEvent) {
    e.preventDefault();
    this.openReplyDialog(FocusTarget.ANY);
  }

  private onReplyOverlayCanceled() {
    fireDialogChange(this, {canceled: true});
    this.changeViewAriaHidden = false;
  }

  private onReplyOverlayOpenedChanged(e: ValueChangedEvent<boolean>) {
    this.replyOverlayOpened = e.detail.value;
  }

  private handleOpenDiffPrefs() {
    assertIsDefined(this.fileList);
    this.fileList.openDiffPrefs();
  }

  private handleOpenIncludedInDialog() {
    assertIsDefined(this.includedInDialog);
    assertIsDefined(this.includedInOverlay);
    this.includedInDialog.loadData().then(() => {
      assertIsDefined(this.includedInOverlay);
      flush();
      this.includedInOverlay.refit();
    });
    this.includedInOverlay.open();
  }

  private handleIncludedInDialogClose() {
    assertIsDefined(this.includedInOverlay);
    this.includedInOverlay.close();
  }

  // Private but used in tests
  handleOpenDownloadDialog() {
    assertIsDefined(this.downloadOverlay);
    this.downloadOverlay.open().then(() => {
      assertIsDefined(this.downloadOverlay);
      assertIsDefined(this.downloadDialog);
      this.downloadOverlay.setFocusStops(this.downloadDialog.getFocusStops());
      this.downloadDialog.focus();
    });
  }

  private handleDownloadDialogClose() {
    assertIsDefined(this.downloadOverlay);
    this.downloadOverlay.close();
  }

  // Private but used in tests.
  handleMessageReply(e: CustomEvent<{message: {message: string}}>) {
    const msg: string = e.detail.message.message;
    const quoteStr =
      msg
        .split('\n')
        .map(line => '> ' + line)
        .join('\n') + '\n\n';
    this.openReplyDialog(FocusTarget.BODY, quoteStr);
  }

  // Private but used in tests.
  handleHideBackgroundContent() {
    assertIsDefined(this.mainContent);
    this.mainContent.classList.add('overlayOpen');
  }

  // Private but used in tests.
  handleShowBackgroundContent() {
    assertIsDefined(this.mainContent);
    this.mainContent.classList.remove('overlayOpen');
  }

  // Private but used in tests.
  handleReplySent() {
    this.addEventListener(
      'change-details-loaded',
      () => {
        this.reporting.timeEnd(Timing.SEND_REPLY);
      },
      {once: true}
    );
    assertIsDefined(this.replyOverlay);
    this.replyOverlay.cancel();
    fireReload(this);
  }

  private handleReplyCancel() {
    assertIsDefined(this.replyOverlay);
    this.replyOverlay.cancel();
  }

  private handleReplyAutogrow() {
    // If the textarea resizes, we need to re-fit the overlay.
    this.replyRefitTask = debounce(
      this.replyRefitTask,
      () => {
        assertIsDefined(this.replyOverlay);
        this.replyOverlay.refit();
      },
      REPLY_REFIT_DEBOUNCE_INTERVAL_MS
    );
  }

  // Private but used in tests.
  handleShowReplyDialog(e: CustomEvent<{value: {ccsOnly: boolean}}>) {
    let target = FocusTarget.REVIEWERS;
    if (e.detail.value && e.detail.value.ccsOnly) {
      target = FocusTarget.CCS;
    }
    this.openReplyDialog(target);
  }

  private expandAllDiffs() {
    assertIsDefined(this.fileList);
    this.fileList.expandAllDiffs();
  }

  private collapseAllDiffs() {
    assertIsDefined(this.fileList);
    this.fileList.collapseAllDiffs();
  }

  /**
   * ChangeView is never re-used for different changes. It is safer and simpler
   * to just re-create another change view when the user switches to a new
   * change page. Thus we need a reliable way to detect that the change view
   * does not match the current change number anymore.
   *
   * If this method returns true, then the change view should not do anything
   * anymore. The app element makes sure that an obsolete change view is not
   * shown anymore, so if the change view is still and doing some update to
   * itself, then that is not dangerous. But for example it should not call
   * the navigation service's set/replaceUrl() methods anymore. That would very
   * likely cause erroneous behavior.
   */
  private isChangeObsolete() {
    // While this.changeNum is undefined the change view is fresh and has just
    // not updated it to viewState.changeNum yet. Not obsolete in that case.
    if (this.changeNum === undefined) return false;
    // this.viewState reflects the current state of the URL. If this.changeNum
    // does not match it anymore, then this view must be considered obsolete.
    return this.changeNum !== this.viewState?.changeNum;
  }

  // Private but used in tests.
  hasPatchRangeChanged(viewState: ChangeViewState) {
    if (!this.patchRange) return false;
    if (this.patchRange.basePatchNum !== viewState.basePatchNum) return true;
    return this.hasPatchNumChanged(viewState);
  }

  // Private but used in tests.
  hasPatchNumChanged(viewState: ChangeViewState) {
    if (!this.patchRange) return false;
    if (viewState.patchNum !== undefined) {
      return this.patchRange.patchNum !== viewState.patchNum;
    } else {
      // value.patchNum === undefined specifies the latest patchset
      return (
        this.patchRange.patchNum !== computeLatestPatchNum(this.allPatchSets)
      );
    }
  }

  // Private but used in tests.
  viewStateChanged() {
    if (this.viewState === undefined) {
      this.initialLoadComplete = false;
      querySelectorAll(this, 'gr-overlay').forEach(overlay =>
        (overlay as GrOverlay).close()
      );
      return;
    }

    if (this.isChangeObsolete()) {
      // Tell the app element that we are not going to handle the new change
      // number and that they have to create a new change view.
      fireEvent(this, EventType.RECREATE_CHANGE_VIEW);
      return;
    }

    if (this.viewState.changeNum && this.viewState.project) {
      this.restApiService.setInProjectLookup(
        this.viewState.changeNum,
        this.viewState.project
      );
    }

    if (this.viewState.basePatchNum === undefined)
      this.viewState.basePatchNum = PARENT;

    const patchChanged = this.hasPatchRangeChanged(this.viewState);
    let patchNumChanged = this.hasPatchNumChanged(this.viewState);

    this.patchRange = {
      patchNum: this.viewState.patchNum,
      basePatchNum: this.viewState.basePatchNum,
    };
    this.scrollCommentId = this.viewState.commentId;

    const patchKnown =
      !this.patchRange.patchNum ||
      (this.allPatchSets ?? []).some(
        ps => ps.num === this.patchRange!.patchNum
      );
    // _allPatchsets does not know value.patchNum so force a reload.
    const forceReload = this.viewState.forceReload || !patchKnown;

    // If changeNum is defined that means the change has already been
    // rendered once before so a full reload is not required.
    if (this.changeNum !== undefined && !forceReload) {
      if (!this.patchRange.patchNum) {
        this.patchRange = {
          ...this.patchRange,
          patchNum: computeLatestPatchNum(this.allPatchSets),
        };
        patchNumChanged = true;
      }
      if (patchChanged) {
        // We need to collapse all diffs when viewState changes so that a non
        // existing diff is not requested. See Issue 125270 for more details.
        this.fileList?.resetFileState();
        this.fileList?.collapseAllDiffs();
        this.reloadPatchNumDependentResources(patchNumChanged);
      }

      // If there is no change in patchset or changeNum, such as when user goes
      // to the diff view and then comes back to change page then there is no
      // need to reload anything and we render the change view component as is.
      document.documentElement.scrollTop = this.scrollPosition ?? 0;
      this.reporting.reportInteraction('change-view-re-rendered');
      this.updateTitle(this.change);
      // We still need to check if post load tasks need to be done such as when
      // user wants to open the reply dialog when in the diff page, the change
      // page should open the reply dialog
      this.performPostLoadTasks();
      return;
    }

    // We need to collapse all diffs when viewState changes so that a non
    // existing diff is not requested. See Issue 125270 for more details.
    this.updateComplete.then(() => {
      assertIsDefined(this.fileList);
      this.fileList?.collapseAllDiffs();
      this.fileList?.resetFileState();
    });

    // If the change was loaded before, then we are firing a 'reload' event
    // instead of calling `loadData()` directly for two reasons:
    // 1. We want to avoid code such as `this.initialLoadComplete = false` that
    //    is only relevant for the initial load of a change.
    // 2. We have to somehow trigger the change-model reloading. Otherwise
    //    this.change is not updated.
    if (this.changeNum) {
      if (!this._patchRange?.patchNum) {
        this._patchRange = {
          basePatchNum: PARENT,
          patchNum: computeLatestPatchNum(this.allPatchSets),
        };
      }
      fireReload(this);
      return;
    }

    this.initialLoadComplete = false;
    this.changeNum = this.viewState.changeNum;
    this.loadData(true).then(() => {
      this.performPostLoadTasks();
    });

    getPluginLoader()
      .awaitPluginsLoaded()
      .then(() => {
        this.initActiveTab();
      });
  }

  private initActiveTab() {
    let tab = Tab.FILES;
    if (this.viewState?.tab) {
      tab = this.viewState?.tab as Tab;
    } else if (this.viewState?.commentId) {
      tab = Tab.COMMENT_THREADS;
    }
    this.setActiveTab(new CustomEvent(EventType.SHOW_TAB, {detail: {tab}}));
  }

  // Private but used in tests.
  sendShowChangeEvent() {
    assertIsDefined(this.patchRange, 'patchRange');
    this.jsAPI.handleEvent(PluginEventType.SHOW_CHANGE, {
      change: this.change,
      patchNum: this.patchRange.patchNum,
      info: {mergeable: this.mergeable},
    });
  }

  private performPostLoadTasks() {
    this.maybeShowReplyDialog();
    this.maybeShowRevertDialog();

    this.sendShowChangeEvent();

    this.updateComplete.then(() => {
      this.maybeScrollToMessage(window.location.hash);
      this.initialLoadComplete = true;
    });
  }

  // Private but used in tests.
  handleMessageAnchorTap(e: CustomEvent<{id: string}>) {
    assertIsDefined(this.change, 'change');
    assertIsDefined(this.patchRange, 'patchRange');
    const hash = PREFIX + e.detail.id;
    const url = createChangeUrl({
      change: this.change,
      patchNum: this.patchRange.patchNum,
      basePatchNum: this.patchRange.basePatchNum,
      edit: this.getEditMode(),
      messageHash: hash,
    });
    history.replaceState(null, '', url);
  }

  // Private but used in tests.
  maybeScrollToMessage(hash: string) {
    if (hash.startsWith(PREFIX) && this.messagesList) {
      this.messagesList.scrollToMessage(hash.substr(PREFIX.length));
    }
  }

  // Private but used in tests.
  getLocationSearch() {
    // Not inlining to make it easier to test.
    return window.location.search;
  }

  _getUrlParameter(param: string) {
    const pageURL = this.getLocationSearch().substring(1);
    const vars = pageURL.split('&');
    for (let i = 0; i < vars.length; i++) {
      const name = vars[i].split('=');
      if (name[0] === param) {
        return name[0];
      }
    }
    return null;
  }

  // Private but used in tests.
  maybeShowRevertDialog() {
    getPluginLoader()
      .awaitPluginsLoaded()
      .then(() => {
        if (
          !this.loggedIn ||
          !this.change ||
          this.change.status !== ChangeStatus.MERGED
        ) {
          // Do not display dialog if not logged-in or the change is not
          // merged.
          return;
        }
        if (this._getUrlParameter('revert')) {
          assertIsDefined(this.actions);
          this.actions.showRevertDialog();
        }
      });
  }

  private maybeShowReplyDialog() {
    if (!this.loggedIn) return;
    if (this.viewState?.openReplyDialog) {
      this.openReplyDialog(FocusTarget.ANY);
    }
  }

  private updateTitle(change?: ChangeInfo | ParsedChangeInfo) {
    if (!change) return;
    const title = change.subject + ' (' + change.change_id.substr(0, 9) + ')';
    fireTitleChange(this, title);
  }

  // Private but used in tests.
  changeChanged(oldChange: ParsedChangeInfo | undefined) {
    this.allPatchSets = computeAllPatchSets(this.change);
    if (!this.change) return;
    this.labelsChanged(oldChange?.labels, this.change.labels);
    if (
      this.change.current_revision &&
      this.change.revisions &&
      this.change.revisions[this.change.current_revision]
    ) {
      this.currentRobotCommentsPatchSet =
        this.change.revisions[this.change.current_revision]._number;
    }
    if (!this.change || !this.patchRange || !this.allPatchSets) {
      return;
    }

    // We get the parent first so we keep the original value for basePatchNum
    // and not the updated value.
    const parent = this.getBasePatchNum();

    this.patchRange = {
      ...this.patchRange,
      basePatchNum: parent,
      patchNum:
        this.patchRange.patchNum || computeLatestPatchNum(this.allPatchSets),
    };
    this.updateTitle(this.change);
  }

  /**
   * Gets base patch number, if it is a parent try and decide from
   * preference whether to default to `auto merge`, `Parent 1` or `PARENT`.
   * Private but used in tests.
   */
  getBasePatchNum() {
    if (
      this.patchRange &&
      this.patchRange.basePatchNum &&
      this.patchRange.basePatchNum !== PARENT
    ) {
      return this.patchRange.basePatchNum;
    }

    const revisionInfo = this.getRevisionInfo();
    if (!revisionInfo) return PARENT;

    // TODO: It is a bit unclear why `1` is used here instead of
    // `patchRange.patchNum`. Maybe that is a bug? Maybe if one patchset
    // is a merge commit, then all patchsets are merge commits??
    const isMerge = revisionInfo.isMergeCommit(1 as PatchSetNumber);
    const preferFirst =
      this.prefs &&
      this.prefs.default_base_for_merges === DefaultBase.FIRST_PARENT;

    // TODO: I think checking `!patchRange.patchNum` here is a bug and means
    // that the feature is actually broken at the moment. Looking at the
    // `changeChanged` method, `patchRange.patchNum` is set before
    // `getBasePatchNum` is called, so it is unlikely that this method will
    // ever return -1.
    if (isMerge && preferFirst && !this.patchRange?.patchNum) {
      this.reporting.reportExecution(Execution.PREFER_MERGE_FIRST_PARENT);
      return -1 as BasePatchSetNum;
    }
    return PARENT;
  }

  private computeChangeUrl(forceReload?: boolean) {
    if (!this.change) return undefined;
    return createChangeUrl({
      change: this.change,
      forceReload: !!forceReload,
    });
  }

  // private but used in test
  computeChangeIdClass(displayChangeId?: string | null) {
    if (displayChangeId) {
      return displayChangeId === CHANGE_ID_ERROR.MISMATCH ? 'warning' : '';
    }
    return '';
  }

  computeTitleAttributeWarning(displayChangeId?: string | null) {
    if (!displayChangeId) {
      return undefined;
    }
    if (displayChangeId === CHANGE_ID_ERROR.MISMATCH) {
      return 'Change-Id mismatch';
    } else if (displayChangeId === CHANGE_ID_ERROR.MISSING) {
      return 'No Change-Id in commit message';
    }
    return undefined;
  }

  computeChangeIdCommitMessageError(
    commitMessage: string | null,
    change?: ParsedChangeInfo
  ) {
    if (change === undefined) {
      return undefined;
    }

    if (!commitMessage) {
      return CHANGE_ID_ERROR.MISSING;
    }

    // Find the last match in the commit message:
    let changeId;
    let changeIdArr;

    while ((changeIdArr = CHANGE_ID_REGEX_PATTERN.exec(commitMessage))) {
      changeId = changeIdArr[2];
    }

    if (changeId) {
      // A change-id is detected in the commit message.

      if (changeId === change.change_id) {
        // The change-id found matches the real change-id.
        return null;
      }
      // The change-id found does not match the change-id.
      return CHANGE_ID_ERROR.MISMATCH;
    }
    // There is no change-id in the commit message.
    return CHANGE_ID_ERROR.MISSING;
  }

  // Private but used in tests.
  computeReplyButtonLabel() {
    if (this.diffDrafts === undefined) {
      return 'Reply';
    }

    const draftCount = Object.keys(this.diffDrafts).reduce(
      (count, file) => count + this.diffDrafts![file].length,
      0
    );

    let label = this.canStartReview() ? 'Start Review' : 'Reply';
    if (draftCount > 0) {
      label += ` (${draftCount})`;
    }
    return label;
  }

  private handleOpenReplyDialog() {
    if (!this.loggedIn) {
      fireEvent(this, 'show-auth-required');
      return;
    }
    this.openReplyDialog(FocusTarget.ANY);
  }

  private handleOpenSubmitDialog() {
    if (!this.isSubmitEnabled()) return;
    assertIsDefined(this.actions);
    this.actions.showSubmitDialog();
  }

  // Private but used in tests.
  handleToggleAttentionSet() {
    if (!this.change || !this.account?._account_id) return;
    if (!this.loggedIn || !isInvolved(this.change, this.account)) return;
    const newChange = {...this.change};
    if (!newChange.attention_set) newChange.attention_set = {};
    if (hasAttention(this.account, this.change)) {
      const reason = getRemovedByReason(this.account, this.serverConfig);
      if (newChange.attention_set)
        delete newChange.attention_set[this.account._account_id];
      fireAlert(this, 'Removing you from the attention set ...');
      this.restApiService
        .removeFromAttentionSet(
          this.change._number,
          this.account._account_id,
          reason
        )
        .then(() => {
          fireEvent(this, 'hide-alert');
        });
    } else {
      const reason = getAddedByReason(this.account, this.serverConfig);
      fireAlert(this, 'Adding you to the attention set ...');
      newChange.attention_set[this.account._account_id] = {
        account: this.account,
        reason,
        reason_account: this.account,
      };
      this.restApiService
        .addToAttentionSet(
          this.change._number,
          this.account._account_id,
          reason
        )
        .then(() => {
          fireEvent(this, 'hide-alert');
        });
    }
    this.change = newChange;
  }

  // Private but used in tests.
  handleDiffAgainstBase() {
    assertIsDefined(this.change, 'change');
    assertIsDefined(this.patchRange, 'patchRange');
    if (this.patchRange.basePatchNum === PARENT) {
      fireAlert(this, 'Base is already selected.');
      return;
    }
    this.getNavigation().setUrl(
      createChangeUrl({change: this.change, patchNum: this.patchRange.patchNum})
    );
  }

  // Private but used in tests.
  handleDiffBaseAgainstLeft() {
    assertIsDefined(this.change, 'change');
    assertIsDefined(this.patchRange, 'patchRange');

    if (this.patchRange.basePatchNum === PARENT) {
      fireAlert(this, 'Left is already base.');
      return;
    }
    this.getNavigation().setUrl(
      createChangeUrl({
        change: this.change,
        patchNum: this.patchRange.basePatchNum as RevisionPatchSetNum,
      })
    );
  }

  // Private but used in tests.
  handleDiffAgainstLatest() {
    assertIsDefined(this.change, 'change');
    assertIsDefined(this.patchRange, 'patchRange');
    const latestPatchNum = computeLatestPatchNum(this.allPatchSets);
    if (this.patchRange.patchNum === latestPatchNum) {
      fireAlert(this, 'Latest is already selected.');
      return;
    }
    this.getNavigation().setUrl(
      createChangeUrl({
        change: this.change,
        patchNum: latestPatchNum,
        basePatchNum: this.patchRange.basePatchNum,
      })
    );
  }

  // Private but used in tests.
  handleDiffRightAgainstLatest() {
    assertIsDefined(this.change, 'change');
    assertIsDefined(this.patchRange, 'patchRange');
    const latestPatchNum = computeLatestPatchNum(this.allPatchSets);
    if (this.patchRange.patchNum === latestPatchNum) {
      fireAlert(this, 'Right is already latest.');
      return;
    }
    this.getNavigation().setUrl(
      createChangeUrl({
        change: this.change,
        patchNum: latestPatchNum,
        basePatchNum: this.patchRange.patchNum as BasePatchSetNum,
      })
    );
  }

  // Private but used in tests.
  handleDiffBaseAgainstLatest() {
    assertIsDefined(this.change, 'change');
    assertIsDefined(this.patchRange, 'patchRange');
    const latestPatchNum = computeLatestPatchNum(this.allPatchSets);
    if (
      this.patchRange.patchNum === latestPatchNum &&
      this.patchRange.basePatchNum === PARENT
    ) {
      fireAlert(this, 'Already diffing base against latest.');
      return;
    }
    this.getNavigation().setUrl(
      createChangeUrl({change: this.change, patchNum: latestPatchNum})
    );
  }

  private handleToggleChangeStar() {
    assertIsDefined(this.changeStar);
    this.changeStar.toggleStar();
  }

  private handleExpandAllMessages() {
    if (this.messagesList) {
      this.messagesList.handleExpandCollapse(true);
    }
  }

  private handleCollapseAllMessages() {
    if (this.messagesList) {
      this.messagesList.handleExpandCollapse(false);
    }
  }

  private handleOpenDiffPrefsShortcut() {
    if (!this.loggedIn) return;
    assertIsDefined(this.fileList);
    this.fileList.openDiffPrefs();
  }

  private determinePageBack() {
    // Default backPage to root if user came to change view page
    // via an email link, etc.
    this.getNavigation().setUrl(this.backPage || rootUrl());
  }

  private handleLabelRemoved(
    oldLabels: LabelNameToInfoMap,
    newLabels: LabelNameToInfoMap
  ) {
    for (const key in oldLabels) {
      if (!Object.prototype.hasOwnProperty.call(oldLabels, key)) continue;
      const oldLabelInfo: QuickLabelInfo & DetailedLabelInfo = oldLabels[key];
      const newLabelInfo: (QuickLabelInfo & DetailedLabelInfo) | undefined =
        newLabels[key];
      if (!newLabelInfo) continue;
      if (!oldLabelInfo.all || !newLabelInfo.all) continue;
      const oldAccounts = oldLabelInfo.all.map(x => x._account_id);
      const newAccounts = newLabelInfo.all.map(x => x._account_id);
      for (const account of oldAccounts) {
        if (
          !newAccounts.includes(account) &&
          newLabelInfo.approved?._account_id === account
        ) {
          fireReload(this);
          return;
        }
      }
    }
  }

  private labelsChanged(
    oldLabels: LabelNameToInfoMap | undefined,
    newLabels: LabelNameToInfoMap | undefined
  ) {
    if (!oldLabels || !newLabels) {
      return;
    }
    this.handleLabelRemoved(oldLabels, newLabels);
    this.jsAPI.handleEvent(PluginEventType.LABEL_CHANGE, {
      change: this.change,
    });
  }

  openReplyDialog(focusTarget?: FocusTarget, quote?: string) {
    if (!this.change) return;
    assertIsDefined(this.replyOverlay);
    const overlay = this.replyOverlay;
    overlay.open().finally(() => {
      // the following code should be executed no matter open succeed or not
      const dialog = this.replyDialog;
      assertIsDefined(dialog, 'reply dialog');
      this.resetReplyOverlayFocusStops();
      dialog.open(focusTarget, quote);
      const observer = new ResizeObserver(() => overlay.center());
      observer.observe(dialog);
    });
    fireDialogChange(this, {opened: true});
    this.changeViewAriaHidden = true;
  }

  // Private but used in tests.
  prepareCommitMsgForLinkify(msg: string) {
    // TODO(wyatta) switch linkify sequence, see issue 5526.
    // This is a zero-with space. It is added to prevent the linkify library
    // from including R= or CC= as part of the email address.
    return msg.replace(REVIEWERS_REGEX, '$1=\u200B');
  }

  /**
   * Utility function to make the necessary modifications to a change in the
   * case an edit exists.
   * Private but used in tests.
   */
  processEdit(change: ParsedChangeInfo) {
    const revisions = Object.values(change.revisions || {});
    const editRev = findEdit(revisions);
    const editParentRev = findEditParentRevision(revisions);
    if (
      !editRev &&
      this.patchRange?.patchNum === EDIT &&
      changeIsOpen(change)
    ) {
      fireAlert(this, 'Change edit not found. Please create a change edit.');
      fireReload(this, true);
      return;
    }

    if (
      !editRev &&
      (changeIsMerged(change) || changeIsAbandoned(change)) &&
      this.getEditMode()
    ) {
      fireAlert(
        this,
        'Change edits cannot be created if change is merged or abandoned. Redirecting to non edit mode.'
      );
      fireReload(this, true);
      return;
    }

    if (!editRev) return;
    assertIsDefined(this.patchRange, 'patchRange');
    assertIsDefined(editRev.commit.commit, 'editRev.commit.commit');
    assertIsDefined(editParentRev, 'editParentRev');

    const latestPsNum = computeLatestPatchNum(computeAllPatchSets(change));
    // If the change was loaded without a specific patchset, then this normally
    // means that the *latest* patchset should be loaded. But if there is an
    // active edit, then automatically switch to that edit as the current
    // patchset.
    // TODO: This goes together with `change.current_revision` being set, which
    // is under change-model control. `patchRange.patchNum` should eventually
    // also be model managed, so we can reconcile these two code snippets into
    // one location.
    if (!this.routerPatchNum && latestPsNum === editParentRev._number) {
      this.patchRange = {...this.patchRange, patchNum: EDIT};
      // The file list is not reactive (yet) with regards to patch range
      // changes, so we have to actively trigger it.
      this.reloadPatchNumDependentResources();
    }
  }

  computeRevertSubmitted(change?: ChangeInfo | ParsedChangeInfo) {
    if (!change?.messages) return;
    Promise.all(
      getRevertCreatedChangeIds(change.messages).map(changeId =>
        this.restApiService.getChange(changeId)
      )
    ).then(changes => {
      // if a change is deleted then getChanges returns null for that changeId
      changes = changes.filter(
        change => change && change.status !== ChangeStatus.ABANDONED
      );
      if (!changes.length) return;
      const submittedRevert = changes.find(
        change => change?.status === ChangeStatus.MERGED
      );
      if (!this.changeStatuses) return;
      if (submittedRevert) {
        this.revertedChange = submittedRevert;
        this.changeStatuses = this.changeStatuses.concat([
          ChangeStates.REVERT_SUBMITTED,
        ]);
      } else {
        if (changes[0]) this.revertedChange = changes[0];
        this.changeStatuses = this.changeStatuses.concat([
          ChangeStates.REVERT_CREATED,
        ]);
      }
    });
  }

  private async untilModelLoaded() {
    // NOTE: Wait until this page is connected before determining whether the
    // model is loaded.  This can happen when viewState changes when setting up
    // this view. It's unclear whether this issue is related to Polymer
    // specifically.
    if (!this.isConnected) {
      await until(this.connected$, connected => connected);
    }
    await until(
      this.getChangeModel().changeLoadingStatus$,
      status => status === LoadingStatus.LOADED
    );
  }

  /**
   * Process edits
   * Check if a revert of this change has been submitted
   * Calculate selected revision
   */
  // private but used in tests
  async performPostChangeLoadTasks() {
    assertIsDefined(this.changeNum, 'changeNum');

    const prefCompletes = this.restApiService.getPreferences();
    await this.untilModelLoaded();

    this.prefs = await prefCompletes;

    if (!this.change) return false;

    this.processEdit(this.change);
    // Issue 4190: Coalesce missing topics to null.
    // TODO(TS): code needs second thought,
    // it might be that nulls were assigned to trigger some bindings
    if (!this.change.topic) {
      this.change.topic = null as unknown as undefined;
    }
    if (!this.change.reviewer_updates) {
      this.change.reviewer_updates = null as unknown as undefined;
    }
    const latestRevisionSha = this.getLatestRevisionSHA(this.change);
    if (!latestRevisionSha)
      throw new Error('Could not find latest Revision Sha');
    const currentRevision = this.change.revisions[latestRevisionSha];
    if (currentRevision.commit && currentRevision.commit.message) {
      this.latestCommitMessage = this.prepareCommitMsgForLinkify(
        currentRevision.commit.message
      );
    } else {
      this.latestCommitMessage = null;
    }

    this.computeRevertSubmitted(this.change);
    if (
      !this.patchRange ||
      !this.patchRange.patchNum ||
      this.patchRange.patchNum === currentRevision._number
    ) {
      // CommitInfo.commit is optional, and may need patching.
      if (currentRevision.commit && !currentRevision.commit.commit) {
        currentRevision.commit.commit = latestRevisionSha as CommitId;
      }
      this.commitInfo = currentRevision.commit;
      this.selectedRevision = currentRevision;
      // TODO: Fetch and process files.
    } else {
      if (!this.change?.revisions || !this.patchRange) return false;
      this.selectedRevision = Object.values(this.change.revisions).find(
        revision => {
          // edit patchset is a special one
          const thePatchNum = this.patchRange!.patchNum;
          if (thePatchNum === EDIT) {
            return revision._number === thePatchNum;
          }
          return revision._number === Number(`${thePatchNum}`);
        }
      );
    }
    return true;
  }

  private isParentCurrent() {
    const revisionActions = this.currentRevisionActions;
    if (revisionActions && revisionActions.rebase) {
      return !revisionActions.rebase.enabled;
    } else {
      return true;
    }
  }

  // Private but used in tests.
  getLatestCommitMessage() {
    assertIsDefined(this.changeNum, 'changeNum');
    const lastpatchNum = computeLatestPatchNum(this.allPatchSets);
    if (lastpatchNum === undefined)
      throw new Error('missing lastPatchNum property');
    return this.restApiService
      .getChangeCommitInfo(this.changeNum, lastpatchNum)
      .then(commitInfo => {
        if (!commitInfo) return;
        this.latestCommitMessage = this.prepareCommitMsgForLinkify(
          commitInfo.message
        );
      });
  }

  // Private but used in tests.
  getLatestRevisionSHA(change: ChangeInfo | ParsedChangeInfo) {
    if (change.current_revision) return change.current_revision;
    // current_revision may not be present in the case where the latest rev is
    // a draft and the user doesn’t have permission to view that rev.
    let latestRev = null;
    let latestPatchNum = -1 as PatchSetNum;
    for (const [rev, revInfo] of Object.entries(change.revisions ?? {})) {
      if (revInfo._number > latestPatchNum) {
        latestRev = rev;
        latestPatchNum = revInfo._number;
      }
    }
    return latestRev;
  }

  // visible for testing
  loadAndSetCommitInfo() {
    assertIsDefined(this.changeNum, 'changeNum');
    assertIsDefined(this.patchRange?.patchNum, 'patchRange.patchNum');
    return this.restApiService
      .getChangeCommitInfo(this.changeNum, this.patchRange.patchNum)
      .then(commitInfo => {
        this.commitInfo = commitInfo;
      });
  }

  /**
   * Reload the change.
   *
   * @param isLocationChange Reloads the related changes
   * when true and ends reporting events that started on location change.
   * @param clearPatchset Reloads the change ignoring any patchset
   * choice made.
   * @return A promise that resolves when the core data has loaded.
   * Some non-core data loading may still be in-flight when the core data
   * promise resolves.
   */
  loadData(isLocationChange?: boolean, clearPatchset?: boolean) {
    if (this.isChangeObsolete()) return Promise.resolve();
    if (clearPatchset && this.change) {
      this.getNavigation().setUrl(
        createChangeUrl({change: this.change, forceReload: true})
      );
      return Promise.resolve();
    }
    this.loading = true;
    this.reporting.time(Timing.CHANGE_RELOAD);
    this.reporting.time(Timing.CHANGE_DATA);

    // Array to house all promises related to data requests.
    const allDataPromises: Promise<unknown>[] = [];

    // Resolves when the change detail and the edit patch set (if available)
    // are loaded.
    const detailCompletes = this.untilModelLoaded();
    allDataPromises.push(detailCompletes);

    // Resolves when the loading flag is set to false, meaning that some
    // change content may start appearing.
    const loadingFlagSet = detailCompletes.then(() => {
      this.loading = false;
      this.performPostChangeLoadTasks();
    });

    let coreDataPromise;

    // If the patch number is specified
    if (this.patchRange && this.patchRange.patchNum) {
      // Because a specific patchset is specified, reload the resources that
      // are keyed by patch number or patch range.
      const patchResourcesLoaded = this.reloadPatchNumDependentResources();
      allDataPromises.push(patchResourcesLoaded);

      // Promise resolves when the change detail and patch dependent resources
      // have loaded.
      coreDataPromise = Promise.all([patchResourcesLoaded, loadingFlagSet]);
    } else {
      const latestCommitMessageLoaded = loadingFlagSet.then(() => {
        // If the latest commit message is known, there is nothing to do.
        if (this.latestCommitMessage) {
          return Promise.resolve();
        }
        return this.getLatestCommitMessage();
      });
      allDataPromises.push(latestCommitMessageLoaded);

      coreDataPromise = loadingFlagSet;
    }
    const mergeabilityLoaded = coreDataPromise.then(() =>
      this.getMergeability()
    );
    allDataPromises.push(mergeabilityLoaded);

    coreDataPromise.then(() => {
      fireEvent(this, 'change-details-loaded');
      this.reporting.timeEnd(Timing.CHANGE_RELOAD);
      if (isLocationChange) {
        this.reporting.changeDisplayed(roleDetails(this.change, this.account));
      }
    });

    if (isLocationChange) {
      this.editingCommitMessage = false;
    }
    const relatedChangesLoaded = coreDataPromise.then(() => {
      let relatedChangesPromise:
        | Promise<RelatedChangesInfo | undefined>
        | undefined;
      const patchNum = computeLatestPatchNum(this.allPatchSets);
      if (this.change && patchNum) {
        relatedChangesPromise = this.restApiService
          .getRelatedChanges(this.change._number, patchNum)
          .then(response => {
            if (this.change && response) {
              this.hasParent = this.calculateHasParent(
                this.change.change_id,
                response.changes
              );
            }
            return response;
          });
      }
      return this.getRelatedChangesList()?.reload(relatedChangesPromise);
    });
    allDataPromises.push(relatedChangesLoaded);
    allDataPromises.push(this.filesLoaded());

    Promise.all(allDataPromises).then(() => {
      // Loading of commments data is no longer part of this reporting
      this.reporting.timeEnd(Timing.CHANGE_DATA);
      if (isLocationChange) {
        this.reporting.changeFullyLoaded();
      }
    });

    return coreDataPromise;
  }

  private async filesLoaded() {
    if (!this.isConnected) await until(this.connected$, connected => connected);
    await until(this.getFilesModel().files$, f => f.length > 0);
  }

  /**
   * Determines whether or not the given change has a parent change. If there
   * is a relation chain, and the change id is not the last item of the
   * relation chain, there is a parent.
   *
   * Private but used in tests.
   */
  calculateHasParent(
    currentChangeId: ChangeId,
    relatedChanges: RelatedChangeAndCommitInfo[]
  ) {
    return (
      relatedChanges.length > 0 &&
      relatedChanges[relatedChanges.length - 1].change_id !== currentChangeId
    );
  }

  /**
   * Kicks off requests for resources that rely on the patch range
   * (`this.patchRange`) being defined.
   */
  reloadPatchNumDependentResources(patchNumChanged?: boolean) {
    assertIsDefined(this.changeNum, 'changeNum');
    if (!this.patchRange?.patchNum) throw new Error('missing patchNum');
    const promises = [this.loadAndSetCommitInfo()];
    if (patchNumChanged) {
      promises.push(
        this.getCommentsModel().reloadPortedComments(
          this.changeNum,
          this.patchRange?.patchNum
        )
      );
      promises.push(
        this.getCommentsModel().reloadPortedDrafts(
          this.changeNum,
          this.patchRange?.patchNum
        )
      );
    }
    return Promise.all(promises);
  }

  // Private but used in tests
  getMergeability(): Promise<void> {
    if (!this.change) {
      this.mergeable = null;
      return Promise.resolve();
    }
    // If the change is closed, it is not mergeable. Note: already merged
    // changes are obviously not mergeable, but the mergeability API will not
    // answer for abandoned changes.
    if (
      this.change.status === ChangeStatus.MERGED ||
      this.change.status === ChangeStatus.ABANDONED
    ) {
      this.mergeable = false;
      return Promise.resolve();
    }

    if (!this.changeNum) {
      return Promise.reject(new Error('missing required changeNum property'));
    }

    // If mergeable bit was already returned in detail REST endpoint, use it.
    if (this.change.mergeable !== undefined) {
      this.mergeable = this.change.mergeable;
      return Promise.resolve();
    }

    this.mergeable = null;
    return this.restApiService
      .getMergeable(this.changeNum)
      .then(mergableInfo => {
        if (mergableInfo) {
          this.mergeable = mergableInfo.mergeable;
        }
      });
  }

  /**
   * Returns the text to be copied when
   * click the copy icon next to change subject
   * Private but used in tests.
   */
  computeCopyTextForTitle(): string {
    return (
      `${this.change?._number}: ${this.change?.subject} | ` +
      `${location.protocol}//${location.host}` +
      `${this.computeChangeUrl()}`
    );
  }

  private computeCommitCollapsible() {
    if (!this.latestCommitMessage) {
      return false;
    }
    return (
      this.latestCommitMessage.split('\n').length >=
      MIN_LINES_FOR_COMMIT_COLLAPSE
    );
  }

  private startUpdateCheckTimer() {
    if (
      !this.serverConfig ||
      !this.serverConfig.change ||
      this.serverConfig.change.update_delay === undefined ||
      this.serverConfig.change.update_delay <= MIN_CHECK_INTERVAL_SECS
    ) {
      return;
    }

    this.updateCheckTimerHandle = window.setTimeout(() => {
      if (!this.isViewCurrent || !this.change) {
        this.startUpdateCheckTimer();
        return;
      }
      const change = this.change;
      this.getChangeModel()
        .fetchChangeUpdates(change)
        .then(result => {
          let toastMessage = null;
          if (!result.isLatest) {
            toastMessage = ReloadToastMessage.NEWER_REVISION;
          } else if (result.newStatus === ChangeStatus.MERGED) {
            toastMessage = ReloadToastMessage.MERGED;
          } else if (result.newStatus === ChangeStatus.ABANDONED) {
            toastMessage = ReloadToastMessage.ABANDONED;
          } else if (result.newStatus === ChangeStatus.NEW) {
            toastMessage = ReloadToastMessage.RESTORED;
          } else if (result.newMessages) {
            toastMessage = ReloadToastMessage.NEW_MESSAGE;
            if (result.newMessages.author?.name) {
              toastMessage += ` from ${result.newMessages.author.name}`;
            }
          }

          // We have to make sure that the update is still relevant for the user.
          // Since starting to fetch the change update the user may have sent a
          // reply, or the change might have been reloaded, or it could be in the
          // process of being reloaded.
          const changeWasReloaded = change !== this.change;
          if (
            !toastMessage ||
            this.loading ||
            changeWasReloaded ||
            !this.isViewCurrent
          ) {
            this.startUpdateCheckTimer();
            return;
          }

          this.cancelUpdateCheckTimer();
          this.dispatchEvent(
            new CustomEvent<ShowAlertEventDetail>(EventType.SHOW_ALERT, {
              detail: {
                message: toastMessage,
                // Persist this alert.
                dismissOnNavigation: true,
                showDismiss: true,
                action: 'Reload',
                callback: () => fireReload(this, true),
              },
              composed: true,
              bubbles: true,
            })
          );
        });
    }, this.serverConfig.change.update_delay * 1000);
  }

  private cancelUpdateCheckTimer() {
    if (this.updateCheckTimerHandle) {
      window.clearTimeout(this.updateCheckTimerHandle);
    }
    this.updateCheckTimerHandle = null;
  }

  private readonly handleVisibilityChange = () => {
    if (document.hidden && this.updateCheckTimerHandle) {
      this.cancelUpdateCheckTimer();
    } else if (!this.updateCheckTimerHandle) {
      this.startUpdateCheckTimer();
    }
  };

  // Private but used in tests.
  computeHeaderClass() {
    const classes = ['header'];
    if (this.getEditMode()) {
      classes.push('editMode');
    }
    return classes.join(' ');
  }

  private handleFileActionTap(e: CustomEvent<{path: string; action: string}>) {
    e.preventDefault();
    assertIsDefined(this.fileListHeader);
    const controls =
      this.fileListHeader.shadowRoot!.querySelector<GrEditControls>(
        '#editControls'
      );
    if (!controls) throw new Error('Missing edit controls');
    assertIsDefined(this.change, 'change');
    assertIsDefined(this.patchRange, 'patchRange');

    const path = e.detail.path;
    switch (e.detail.action) {
      case GrEditConstants.Actions.DELETE.id:
        controls.openDeleteDialog(path);
        break;
      case GrEditConstants.Actions.OPEN.id:
        assertIsDefined(this.patchRange.patchNum, 'patchset number');
        this.getNavigation().setUrl(
          createEditUrl({
            changeNum: this.change._number,
            project: this.change.project,
            path,
            patchNum: this.patchRange.patchNum,
          })
        );
        break;
      case GrEditConstants.Actions.RENAME.id:
        controls.openRenameDialog(path);
        break;
      case GrEditConstants.Actions.RESTORE.id:
        controls.openRestoreDialog(path);
        break;
    }
  }

  private patchNumChanged() {
    if (!this.selectedRevision || !this.patchRange?.patchNum) {
      return;
    }
    assertIsDefined(this.change, 'change');

    if (this.patchRange.patchNum === this.selectedRevision._number) {
      return;
    }
    if (!this.change.revisions) return;
    this.selectedRevision = Object.values(this.change.revisions).find(
      revision => revision._number === this.patchRange!.patchNum
    );
  }

  /**
   * If an edit exists already, load it. Otherwise, toggle edit mode via the
   * navigation API.
   */
  private handleEditTap() {
    if (!this.change || !this.change.revisions)
      throw new Error('missing required change property');
    const editInfo = Object.values(this.change.revisions).find(
      info => info._number === EDIT
    );

    if (editInfo) {
      const url = createChangeUrl({change: this.change, patchNum: EDIT});
      this.getNavigation().setUrl(url);
      return;
    }

    this.getNavigation().setUrl(
      createChangeUrl({
        change: this.change,
        patchNum: this.routerPatchNum,
        edit: true,
        forceReload: true,
      })
    );
  }

  private handleStopEditTap() {
    assertIsDefined(this.change, 'change');
    assertIsDefined(this.patchRange, 'patchRange');
    this.getNavigation().setUrl(
      createChangeUrl({
        change: this.change,
        patchNum: this.patchRange.patchNum,
        forceReload: true,
      })
    );
  }

  private resetReplyOverlayFocusStops() {
    const dialog = this.replyDialog;
    const focusStops = dialog?.getFocusStops();
    if (!focusStops) return;
    assertIsDefined(this.replyOverlay);
    this.replyOverlay.setFocusStops(focusStops);
  }

  // Private but used in tests.
  async handleToggleStar(e: CustomEvent<ChangeStarToggleStarDetail>) {
    if (e.detail.starred) {
      this.reporting.reportInteraction('change-starred-from-change-view');
      this.lastStarredTimestamp = Date.now();
    } else {
      if (
        this.lastStarredTimestamp &&
        Date.now() - this.lastStarredTimestamp < ACCIDENTAL_STARRING_LIMIT_MS
      ) {
        this.reporting.reportInteraction('change-accidentally-starred');
      }
    }
    const msg = e.detail.starred
      ? 'Starring change...'
      : 'Unstarring change...';
    fireAlert(this, msg);
    await this.restApiService.saveChangeStarred(
      e.detail.change._number,
      e.detail.starred
    );
    fireEvent(this, 'hide-alert');
  }

  private getRevisionInfo(): RevisionInfoClass | undefined {
    if (this.change === undefined) return undefined;
    return new RevisionInfoClass(this.change);
  }

  getRelatedChangesList() {
    return this.shadowRoot!.querySelector<GrRelatedChangesList>(
      '#relatedChanges'
    );
  }

  createTitle(shortcutName: Shortcut, section: ShortcutSection) {
    return this.getShortcutsService().createTitle(shortcutName, section);
  }

  private handleRevisionActionsChanged(
    e: CustomEvent<{value: ActionNameToActionInfoMap}>
  ) {
    this.currentRevisionActions = e.detail.value;
  }
}

declare global {
  interface HTMLElementEventMap {
    'toggle-star': CustomEvent<ChangeStarToggleStarDetail>;
  }
  interface HTMLElementTagNameMap {
    'gr-change-view': GrChangeView;
  }
}
