/**
 * @license
 * Copyright 2015 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import '../../plugins/gr-endpoint-decorator/gr-endpoint-decorator';
import '../../plugins/gr-endpoint-param/gr-endpoint-param';
import '../../../styles/gr-a11y-styles';
import '../../../styles/shared-styles';
import '../../shared/gr-button/gr-button';
import '../../shared/gr-dropdown/gr-dropdown';
import '../../shared/gr-dropdown-list/gr-dropdown-list';
import '../../shared/gr-icon/gr-icon';
import '../../shared/gr-weblink/gr-weblink';
import '../../shared/revision-info/revision-info';
import '../gr-apply-fix-dialog/gr-apply-fix-dialog';
import '../gr-diff-host/gr-diff-host';
import '../gr-diff-mode-selector/gr-diff-mode-selector';
import '../gr-diff-preferences-dialog/gr-diff-preferences-dialog';
import '../gr-patch-range-select/gr-patch-range-select';
import '../../change/gr-download-dialog/gr-download-dialog';
import {getAppContext} from '../../../services/app-context';
import {getParentIndex, isMergeParent} from '../../../utils/patch-set-util';
import {
  computeDisplayPath,
  computeTruncatedPath,
  isMagicPath,
} from '../../../utils/path-list-util';
import {changeBaseURL, changeIsOpen} from '../../../utils/change-util';
import {GrDiffHost} from '../../diff/gr-diff-host/gr-diff-host';
import {
  DropdownItem,
  GrDropdownList,
} from '../../shared/gr-dropdown-list/gr-dropdown-list';
import {CommentAnchorTapEventDetail} from '../../shared/gr-comment/gr-comment';
import {ChangeComments} from '../../diff/gr-comment-api/gr-comment-api';
import {
  BasePatchSetNum,
  Comment,
  CommentMap,
  DropdownLink,
  EDIT,
  NumericChangeId,
  PARENT,
  PatchRange,
  PatchSetNumber,
  PreferencesInfo,
  RepoName,
  RevisionPatchSetNum,
} from '../../../types/common';
import {DiffInfo, DiffPreferencesInfo, WebLinkInfo} from '../../../types/diff';
import {ParsedChangeInfo} from '../../../types/types';
import {
  FilesWebLinks,
  PatchRangeChangeEvent,
} from '../gr-patch-range-select/gr-patch-range-select';
import {GrDiffCursor} from '../../../embed/diff/gr-diff-cursor/gr-diff-cursor';
import {CommentSide, DiffViewMode, Side} from '../../../constants/constants';
import {GrApplyFixDialog} from '../gr-apply-fix-dialog/gr-apply-fix-dialog';
import {OpenFixPreviewEvent, ValueChangedEvent} from '../../../types/events';
import {fire, fireAlert} from '../../../utils/event-util';
import {assertIsDefined} from '../../../utils/common-util';
import {whenVisible} from '../../../utils/dom-util';
import {CursorMoveResult} from '../../../api/core';
import {throttleWrap} from '../../../utils/async-util';
import {filter, map, switchMap, take} from 'rxjs/operators';
import {combineLatest} from 'rxjs';
import {
  Shortcut,
  ShortcutSection,
  shortcutsServiceToken,
} from '../../../services/shortcuts/shortcuts-service';
import {
  DisplayLine,
  FileRange,
  LineSelectedEventDetail,
} from '../../../api/diff';
import {GrDownloadDialog} from '../../change/gr-download-dialog/gr-download-dialog';
import {commentsModelToken} from '../../../models/comments/comments-model';
import {changeModelToken} from '../../../models/change/change-model';
import {resolve} from '../../../models/dependency';
import {css, html, LitElement, nothing, PropertyValues} from 'lit';
import {ShortcutController} from '../../lit/shortcut-controller';
import {subscribe} from '../../lit/subscription-controller';
import {customElement, property, query, state} from 'lit/decorators.js';
import {a11yStyles} from '../../../styles/gr-a11y-styles';
import {sharedStyles} from '../../../styles/shared-styles';
import {ifDefined} from 'lit/directives/if-defined.js';
import {classMap} from 'lit/directives/class-map.js';
import {when} from 'lit/directives/when.js';
import {styleMap} from 'lit/directives/style-map.js';
import {
  ChangeChildView,
  changeViewModelToken,
} from '../../../models/views/change';
import {userModelToken} from '../../../models/user/user-model';
import {modalStyles} from '../../../styles/gr-modal-styles';
import {GrDiffPreferencesDialog} from '../gr-diff-preferences-dialog/gr-diff-preferences-dialog';
import {
  FileNameToNormalizedFileInfoMap,
  filesModelToken,
} from '../../../models/change/files-model';
import {isImageDiff} from '../../../utils/diff-util';
import {formStyles} from '../../../styles/form-styles';
import {NormalizedFileInfo} from '../../change/gr-file-list/gr-file-list';
import {configModelToken} from '../../../models/config/config-model';
import {trimWithEllipsis} from '../../../utils/string-util';
import '@material/web/checkbox/checkbox';
import {MdCheckbox} from '@material/web/checkbox/checkbox';
import {materialStyles} from '../../../styles/gr-material-styles';

const LOADING_BLAME = 'Loading blame information. This may take a while ...';
const LOADED_BLAME = 'Blame loaded';

// Time in which pressing n key again after the toast navigates to next file
const NAVIGATE_TO_NEXT_FILE_TIMEOUT_MS = 5000;

// Files larger than this cannot be downloaded.
const FILE_DOWNLOAD_LIMIT_BYTES = 50 * 1000 * 1000;

// visible for testing
export interface Files {
  /** All file paths sorted by `specialFilePathCompare`. */
  sortedPaths: string[];
  changeFilesByPath: FileNameToNormalizedFileInfoMap;
}

@customElement('gr-diff-view')
export class GrDiffView extends LitElement {
  /**
   * Fired when user tries to navigate away while comments are pending save.
   *
   * @event show-alert
   */
  @query('#diffHost')
  diffHost?: GrDiffHost;

  @state()
  reviewed = false;

  @query('#downloadModal')
  downloadModal?: HTMLDialogElement;

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

  @query('#dropdown')
  dropdown?: GrDropdownList;

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

  @query('#diffPreferencesDialog')
  diffPreferencesDialog?: GrDiffPreferencesDialog;

  @query('.sidebarAnchor')
  sidebarAnchor?: HTMLDivElement;

  @state() private sidebarHeight = 0;

  // Private but used in tests.
  @state()
  get patchRange(): PatchRange | undefined {
    if (!this.patchNum) return undefined;
    return {
      patchNum: this.patchNum,
      basePatchNum: this.basePatchNum,
    };
  }

  // Private but used in tests.
  @state()
  patchNum?: RevisionPatchSetNum;

  // Private but used in tests.
  @state()
  basePatchNum: BasePatchSetNum = PARENT;

  // Private but used in tests.
  @state()
  change?: ParsedChangeInfo;

  @state()
  latestPatchNum?: PatchSetNumber;

  // Private but used in tests.
  @state()
  changeComments?: ChangeComments;

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

  // Private but used in tests.
  @state()
  diff?: DiffInfo;

  // Private but used in tests.
  @state()
  files: Files = {sortedPaths: [], changeFilesByPath: {}};

  @state() path?: string;

  @state() file?: NormalizedFileInfo;

  @state() private shownSidebar?: string;

  /** Allows us to react when the user switches to the DIFF view. */
  // Private but used in tests.
  @state() isActiveChildView = false;

  // Whether to allow the "Show Blame button"
  @state()
  allowBlame = false;

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

  @property({type: Object})
  prefs?: DiffPreferencesInfo;

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

  @state()
  private editWeblinks?: WebLinkInfo[];

  @state()
  private filesWeblinks?: FilesWebLinks;

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

  @state()
  private isBlameLoading = false;

  /** Directly reflects the view model property `diffView.lineNum`. */
  // Private but used in tests.
  @state()
  focusLineNum?: number;

  /** Directly reflects the view model property `diffView.leftSide`. */
  @state()
  leftSide = false;

  @state()
  commentsForPath: Comment[] = [];

  @state()
  isShowingEntireFile = false;

  // visible for testing
  reviewedFiles = new Set<string>();

  private readonly reporting = getAppContext().reportingService;

  private readonly getUserModel = resolve(this, userModelToken);

  private readonly getChangeModel = resolve(this, changeModelToken);

  private readonly getCommentsModel = resolve(this, commentsModelToken);

  private readonly getFilesModel = resolve(this, filesModelToken);

  private readonly getShortcutsService = resolve(this, shortcutsServiceToken);

  private readonly getViewModel = resolve(this, changeViewModelToken);

  private readonly getConfigModel = resolve(this, configModelToken);

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

  // Show the popup for navigating to next file keyboard shortcut only once
  private hasShownNavigateToFileToast = new Map<string, boolean>();

  @state()
  cursor?: GrDiffCursor;

  private readonly shortcutsController = new ShortcutController(this);

  constructor() {
    super();
    this.setupKeyboardShortcuts();
    this.setupSubscriptions();
    subscribe(
      this,
      () => this.getFilesModel().filesIncludingUnmodified$,
      files => {
        const filesByPath: FileNameToNormalizedFileInfoMap = {};
        for (const f of files) filesByPath[f.__path] = f;
        this.files = {
          sortedPaths: files.map(f => f.__path),
          changeFilesByPath: filesByPath,
        };
      }
    );
  }

  private setupKeyboardShortcuts() {
    const listen = (shortcut: Shortcut, fn: (e: KeyboardEvent) => void) => {
      this.shortcutsController.addAbstract(shortcut, fn);
    };
    listen(Shortcut.LEFT_PANE, _ => this.cursor?.moveLeft());
    listen(Shortcut.RIGHT_PANE, _ => this.cursor?.moveRight());
    listen(Shortcut.NEXT_LINE, _ => this.handleNextLine());
    listen(Shortcut.PREV_LINE, _ => this.handlePrevLine());
    listen(Shortcut.VISIBLE_LINE, _ => this.cursor?.moveToVisibleArea());
    listen(Shortcut.NEXT_FILE_WITH_COMMENTS, _ =>
      this.moveToFileWithComment(1)
    );
    listen(Shortcut.PREV_FILE_WITH_COMMENTS, _ =>
      this.moveToFileWithComment(-1)
    );
    listen(Shortcut.NEW_COMMENT, _ => this.handleNewComment());
    listen(Shortcut.SAVE_COMMENT, _ => {});
    listen(Shortcut.NEXT_FILE, _ => this.handleNextFile());
    listen(Shortcut.PREV_FILE, _ => this.handlePrevFile());
    listen(Shortcut.NEXT_CHUNK, _ => this.handleNextChunk());
    listen(Shortcut.PREV_CHUNK, _ => this.handlePrevChunk());
    listen(Shortcut.NEXT_COMMENT_THREAD, _ => this.handleNextCommentThread());
    listen(Shortcut.PREV_COMMENT_THREAD, _ => this.handlePrevCommentThread());
    listen(Shortcut.OPEN_REPLY_DIALOG, _ => this.handleOpenReplyDialog());
    listen(Shortcut.TOGGLE_LEFT_PANE, _ => this.handleToggleLeftPane());
    listen(Shortcut.OPEN_DOWNLOAD_DIALOG, _ => this.handleOpenDownloadDialog());
    listen(Shortcut.UP_TO_CHANGE, _ =>
      this.getChangeModel().navigateToChange()
    );
    listen(Shortcut.OPEN_DIFF_PREFS, _ => this.handleCommaKey());
    listen(Shortcut.TOGGLE_DIFF_MODE, _ => this.handleToggleDiffMode());
    listen(Shortcut.TOGGLE_FILE_REVIEWED, e => {
      if (this.throttledToggleFileReviewed) {
        this.throttledToggleFileReviewed(e);
      }
    });
    listen(Shortcut.TOGGLE_ALL_DIFF_CONTEXT, _ =>
      this.handleToggleAllDiffContext()
    );
    listen(Shortcut.TOGGLE_HIDE_CHECK_CODE_POINTERS, _ =>
      this.handleToggleHideCheckCodePointers()
    );
    listen(Shortcut.NEXT_UNREVIEWED_FILE, _ => this.handleNextUnreviewedFile());
    listen(Shortcut.TOGGLE_BLAME, _ => this.toggleBlame());
    listen(Shortcut.TOGGLE_HIDE_ALL_COMMENT_THREADS_AND_CODE_POINTERS, _ =>
      this.handleToggleHideAllCommentsAndCodePointers()
    );
    listen(Shortcut.OPEN_FILE_LIST, _ => this.handleOpenFileList());
    listen(Shortcut.DIFF_AGAINST_BASE, _ => this.handleDiffAgainstBase());
    listen(Shortcut.DIFF_AGAINST_LATEST, _ => this.handleDiffAgainstLatest());
    listen(Shortcut.DIFF_BASE_AGAINST_LEFT, _ =>
      this.handleDiffBaseAgainstLeft()
    );
    listen(Shortcut.DIFF_RIGHT_AGAINST_LATEST, _ =>
      this.handleDiffRightAgainstLatest()
    );
    listen(Shortcut.DIFF_BASE_AGAINST_LATEST, _ =>
      this.handleDiffBaseAgainstLatest()
    );
    listen(Shortcut.EXPAND_ALL_COMMENT_THREADS, _ => {}); // docOnly
    listen(Shortcut.COLLAPSE_ALL_COMMENT_THREADS, _ => {}); // docOnly
  }

  private setupSubscriptions() {
    subscribe(
      this,
      () => this.getUserModel().loggedIn$,
      loggedIn => {
        this.loggedIn = loggedIn;
      }
    );
    subscribe(
      this,
      () => this.getCommentsModel().changeComments$,
      changeComments => {
        this.changeComments = changeComments;
      }
    );
    subscribe(
      this,
      () => this.getUserModel().preferences$,
      preferences => {
        this.userPrefs = preferences;
      }
    );
    subscribe(
      this,
      () => this.getUserModel().diffPreferences$,
      diffPreferences => {
        this.prefs = diffPreferences;
      }
    );
    subscribe(
      this,
      () => this.getChangeModel().change$,
      change => {
        // The diff view is tied to a specific change number, so don't update
        // change to undefined.
        if (change) this.change = change;
      }
    );
    subscribe(
      this,
      () => this.getChangeModel().latestPatchNum$,
      latestPatchNum => (this.latestPatchNum = latestPatchNum)
    );
    subscribe(
      this,
      () => this.getChangeModel().reviewedFiles$,
      reviewedFiles => {
        this.reviewedFiles = new Set(reviewedFiles) ?? new Set();
      }
    );
    subscribe(
      this,
      () => this.getViewModel().changeNum$,
      changeNum => {
        if (!changeNum || this.changeNum === changeNum) return;

        // We are only setting the changeNum of the diff view once.
        // Everything in the diff view is tied to the change. It seems better to
        // force the re-creation of the diff view when the change number changes.
        // The parent element will make sure that a new change view is created
        // when the change number changes (using the `keyed` directive).
        if (!this.changeNum) this.changeNum = changeNum;
      }
    );
    subscribe(
      this,
      () => this.getViewModel().childView$,
      childView => (this.isActiveChildView = childView === ChangeChildView.DIFF)
    );
    subscribe(
      this,
      () => this.getViewModel().diffPath$,
      path => (this.path = path)
    );
    subscribe(
      this,
      () => this.getFilesModel().file$(this.getViewModel().diffPath$),
      file => (this.file = file)
    );
    subscribe(
      this,
      () => this.getViewModel().diffLine$,
      line => (this.focusLineNum = line)
    );
    subscribe(
      this,
      () => this.getViewModel().diffLeftSide$,
      leftSide => (this.leftSide = leftSide)
    );
    subscribe(
      this,
      () => this.getViewModel().patchNum$,
      patchNum => (this.patchNum = patchNum)
    );
    subscribe(
      this,
      () => this.getViewModel().basePatchNum$,
      basePatchNum => (this.basePatchNum = basePatchNum ?? PARENT)
    );
    subscribe(
      this,
      () =>
        combineLatest([
          this.getViewModel().diffPath$,
          this.getChangeModel().reviewedFiles$,
        ]),
      ([path, files]) => {
        this.reviewed = !!path && !!files && files.includes(path);
      }
    );

    subscribe(
      this,
      () => this.getConfigModel().serverConfig$,
      serverConfig =>
        (this.allowBlame = serverConfig?.change.allow_blame ?? false)
    );

    // When user initially loads the diff view, we want to automatically mark
    // the file as reviewed if they have it enabled. We can't observe these
    // properties since the method will be called anytime a property updates
    // but we only want to call this on the initial load.
    subscribe(
      this,
      () =>
        this.getViewModel().diffPath$.pipe(
          filter(diffPath => !!diffPath),
          switchMap(() =>
            combineLatest([
              this.getChangeModel().patchNum$,
              this.getViewModel().childView$,
              this.getUserModel().diffPreferences$,
              this.getChangeModel().reviewedFiles$,
            ]).pipe(
              filter(
                ([patchNum, childView, diffPrefs, reviewedFiles]) =>
                  !!patchNum &&
                  childView === ChangeChildView.DIFF &&
                  !!diffPrefs &&
                  !!reviewedFiles
              ),
              take(1)
            )
          )
        ),
      ([patchNum, _routerView, diffPrefs]) => {
        // `patchNum` must be defined, because of the `!!patchNum` filter above.
        assertIsDefined(patchNum, 'patchNum');
        this.setReviewedStatus(patchNum, diffPrefs);
      }
    );
  }

  static override get styles() {
    return [
      formStyles,
      a11yStyles,
      sharedStyles,
      modalStyles,
      materialStyles,
      css`
        :host {
          display: block;
          background-color: var(--view-background-color);
          --sidebar-width: 300px;
        }
        .hidden {
          display: none;
        }
        .headerLeft {
          display: flex;
          align-items: center;
        }
        gr-patch-range-select {
          display: block;
        }
        gr-diff {
          border: none;
        }
        .stickyHeader {
          background-color: var(--view-background-color);
          position: sticky;
          top: var(--main-header-height);
          /* sidebar should outrank <footer> in GrAppElement */
          z-index: 110;
          box-shadow: var(--elevation-level-1);
          /* This is just for giving the box-shadow some space. */
          margin-bottom: 2px;
        }
        header,
        .subHeader {
          align-items: center;
          display: flex;
          justify-content: space-between;
        }
        header {
          padding: var(--spacing-s) var(--spacing-xl);
          border-bottom: 1px solid var(--border-color);
        }
        .changeNumberColon {
          color: transparent;
        }
        .headerSubject {
          margin-left: var(--spacing-s);
          margin-right: var(--spacing-m);
          font-weight: var(--font-weight-medium);
          white-space: nowrap;
          overflow: auto;
        }
        .patchRangeLeft {
          align-items: center;
          display: flex;
        }
        .navLink:not([href]) {
          color: var(--deemphasized-text-color);
        }
        .navLinks {
          align-items: center;
          display: flex;
          white-space: nowrap;
        }
        .navLink {
          padding: 0 var(--spacing-xs);
        }
        .reviewed {
          margin: 0 var(--spacing-xs);
          flex-shrink: 0;
        }
        .jumpToFileContainer {
          display: inline-block;
          word-break: break-all;
        }
        .mobile {
          display: none;
        }
        gr-button {
          padding: var(--spacing-s) 0;
          text-decoration: none;
        }
        .loading {
          color: var(--deemphasized-text-color);
          font-family: var(--header-font-family);
          font-size: var(--font-size-h1);
          font-weight: var(--font-weight-h1);
          line-height: var(--line-height-h1);
          height: 100%;
          padding: var(--spacing-l);
          text-align: center;
        }
        .subHeader {
          background-color: var(--background-color-secondary);
          flex-wrap: wrap;
          padding: 0 var(--spacing-l);
        }
        .prefsButton {
          text-align: right;
        }
        .editMode .hideOnEdit {
          display: none;
        }
        .fileNum {
          display: none;
        }
        .blameLoader,
        .fileNum.show,
        .download,
        .preferences,
        .rightControls {
          align-items: center;
          display: flex;
        }
        .diffModeSelector,
        .editButton {
          align-items: center;
          display: flex;
        }
        .diffModeSelector span,
        .editButton span {
          margin-right: var(--spacing-xs);
        }
        .diffModeSelector.hide,
        .separator.hide {
          display: none;
        }
        .editButtona a {
          text-decoration: none;
        }
        .checkboxDiv {
          display: flex;
        }
        gr-dropdown-list {
          --gr-dropdown-copy-clipboard-margin-left: var(--spacing-s);
        }
        @media screen and (max-width: 50em) {
          header {
            padding: var(--spacing-s) var(--spacing-l);
          }
          .dash {
            display: none;
          }
          .desktop {
            display: none;
          }
          .fileNav {
            align-items: flex-start;
            display: flex;
            margin: 0 var(--spacing-xs);
          }
          .fullFileName {
            display: block;
            font-style: italic;
            min-width: 50%;
            padding: 0 var(--spacing-xxs);
            text-align: center;
            width: 100%;
            word-wrap: break-word;
          }
          .mobileNavLink {
            color: var(--primary-text-color);
            font-family: var(--header-font-family);
            font-size: var(--font-size-h2);
            font-weight: var(--font-weight-h2);
            line-height: var(--line-height-h2);
            text-decoration: none;
          }
          .mobileNavLink:not([href]) {
            color: var(--deemphasized-text-color);
          }
          /* prettier formatter removes semi-colons after css mixins. */
          /* prettier-ignore */
          gr-dropdown-list {
            width: 100%;
          }
        }
        :host(.hideComments) {
          --gr-comment-thread-display: none;
        }
        :host(.hideCheckCodePointers) {
          --gr-check-code-pointers-display: none;
        }
        .diffContainer.sidebarOpen {
          margin-left: var(--sidebar-width);
        }
        .sidebarTriggerContainer {
          display: inline-block;
          margin-right: var(--spacing-m);
        }
        .sidebarAnchor {
          height: 0;
          width: 0;
          overflow: visible;
        }
        .sidebarContents {
          background: var(--background-color-secondary);
          width: var(--sidebar-width);
          border: var(--spacing-xxs) solid var(--border-color);
          border-left: 0;
          overflow: auto;
        }
        md-checkbox {
          --md-checkbox-container-size: 15px;
          --md-checkbox-icon-size: 15px;
        }
        .expensiveDiff {
          color: var(--warning-foreground);
          font-weight: var(--font-weight-bold);
          padding: var(--spacing-m) var(--spacing-xl);
          display: flex;
          align-items: center;
          justify-content: center;
          gap: var(--spacing-s);
        }
        gr-endpoint-decorator:has([replace-content]) gr-diff-host {
          display: none;
        }
      `,
    ];
  }

  override connectedCallback() {
    super.connectedCallback();
    this.throttledToggleFileReviewed = throttleWrap(_ =>
      this.handleToggleFileReviewed()
    );
    this.addEventListener('open-fix-preview', e => this.onOpenFixPreview(e));
    this.cursor = new GrDiffCursor();
    if (this.diffHost) this.reInitCursor();
    window.addEventListener('scroll', this.updateSidebarHeight);
    window.addEventListener('resize', this.updateSidebarHeight);
    this.getUserModel()
      .preferences$.pipe(
        map(p => p.diff_page_sidebar),
        take(1)
      )
      .toPromise()
      .then(initialSidebar => {
        if (initialSidebar === 'NONE' || initialSidebar === undefined) {
          this.shownSidebar = undefined;
        } else {
          this.shownSidebar = initialSidebar.substring('plugin-'.length);
        }
      });
  }

  override disconnectedCallback() {
    this.cursor?.dispose();
    window.removeEventListener('scroll', this.updateSidebarHeight);
    window.removeEventListener('resize', this.updateSidebarHeight);
    super.disconnectedCallback();
  }

  private reInitCursor() {
    if (!this.diffHost) return;
    this.cursor?.replaceDiffs([this.diffHost]);
    this.cursor?.reInitCursor();
  }

  private readonly updateSidebarHeight = () => {
    if (this.sidebarAnchor) {
      this.sidebarHeight =
        window.innerHeight - this.sidebarAnchor.getBoundingClientRect().bottom;
    }
  };

  protected override updated(changedProperties: PropertyValues): void {
    super.updated(changedProperties);
    if (
      changedProperties.has('change') ||
      changedProperties.has('path') ||
      changedProperties.has('patchNum') ||
      changedProperties.has('basePatchNum')
    ) {
      this.reloadDiff();
    } else if (
      changedProperties.has('isActiveChildView') &&
      this.isActiveChildView
    ) {
      this.initializePositions();
    }
    if (
      changedProperties.has('focusLineNum') ||
      changedProperties.has('leftSide')
    ) {
      this.initCursor();
    }
    if (
      changedProperties.has('change') ||
      changedProperties.has('changeComments') ||
      changedProperties.has('path') ||
      changedProperties.has('patchNum') ||
      changedProperties.has('basePatchNum') ||
      changedProperties.has('files')
    ) {
      if (this.change && this.changeComments && this.path && this.patchRange) {
        assertIsDefined(this.diffHost, 'diffHost');
        const file = this.files?.changeFilesByPath?.[this.path];
        this.diffHost.updateComplete.then(() => {
          assertIsDefined(this.path);
          assertIsDefined(this.patchRange);
          assertIsDefined(this.diffHost);
          assertIsDefined(this.changeComments);
          this.diffHost.threads = this.changeComments.getThreadsBySideForFile(
            {path: this.path, basePath: file?.old_path},
            this.patchRange
          );
        });
      }
    }
    if (
      (changedProperties.has('change') ||
        changedProperties.has('changeComments') ||
        changedProperties.has('path') ||
        changedProperties.has('patchRange')) &&
      this.changeComments !== undefined &&
      this.path !== undefined &&
      this.patchRange !== undefined
    ) {
      this.commentsForPath = this.changeComments.getCommentsForPath(
        this.path,
        this.patchRange
      );
    }
    this.updateSidebarHeight();
  }

  override render() {
    if (!this.isActiveChildView) return nothing;
    if (!this.patchNum || !this.changeNum || !this.change || !this.path) {
      return html`<div class="loading">Loading...</div>`;
    }
    const file = this.getFileRange();
    return html`
      ${this.renderStickyHeader()}
      <h2 class="assistive-tech-only">Diff view</h2>
      ${when(
        this.file?.diffs_too_expensive_to_compute,
        () => html`
          <div class="expensiveDiff">
            <gr-icon icon="warning"></gr-icon>
            Diff too expensive to compute.
            <gr-button link @click=${this.handleOpenDownloadDialog}>
              Please download locally to review
            </gr-button>
          </div>
        `
      )}
      <div
        class=${classMap({
          diffContainer: true,
          sidebarOpen: !!this.shownSidebar,
          hidden: !!this.file?.diffs_too_expensive_to_compute,
        })}
      >
        <gr-endpoint-decorator name="diff-content">
          <gr-diff-host
            id="diffHost"
            .changeNum=${this.changeNum}
            .change=${this.change}
            .patchRange=${this.patchRange}
            .file=${file}
            .lineOfInterest=${this.getLineOfInterest()}
            .path=${this.path}
            .projectName=${this.change?.project}
            @is-blame-loaded-changed=${this.onIsBlameLoadedChanged}
            @comment-anchor-tap=${this.onCommentAnchorTap}
            @line-selected=${this.onLineSelected}
            @diff-changed=${this.onDiffChanged}
            @edit-weblinks-changed=${this.onEditWeblinksChanged}
            @files-weblinks-changed=${this.onFilesWeblinksChanged}
            @render=${this.reInitCursor}
          >
          </gr-diff-host>
        </gr-endpoint-decorator>
      </div>
      ${this.renderDialogs()}
    `;
  }

  private renderStickyHeader() {
    return html` <div
      class="stickyHeader ${this.patchNum === EDIT ? 'editMode' : ''}"
    >
      <h1 class="assistive-tech-only">
        Diff of ${this.path ? computeTruncatedPath(this.path) : ''}
      </h1>
      <header>${this.renderHeader()}</header>
      <div class="subHeader">
        ${this.renderPatchRangeLeft()} ${this.renderRightControls()}
      </div>
      <div class="fileNav mobile">
        <a class="mobileNavLink" href=${ifDefined(this.computeNavLinkURL(-1))}
          >&lt;</a
        >
        <div class="fullFileName mobile">${computeDisplayPath(this.path)}</div>
        <a class="mobileNavLink" href=${ifDefined(this.computeNavLinkURL(1))}
          >&gt;</a
        >
      </div>
      ${this.renderSidebarContent()}
    </div>`;
  }

  private renderHeader() {
    const formattedFiles = this.formatFilesForDropdown();
    const fileNum = this.computeFileNum(formattedFiles);
    const fileNumClass = this.computeFileNumClass(fileNum, formattedFiles);
    return html` <div class="headerLeft">
        <div>
          <a href=${ifDefined(this.getChangeModel().changeUrl())}
            >${this.changeNum}</a
          ><span class="changeNumberColon">:</span>
        </div>
        <div>
          <span class="headerSubject"
            >${trimWithEllipsis(this.change?.subject, 80)}</span
          >
        </div>
        <div class="checkboxDiv">
          <md-checkbox
            id="reviewed"
            class="reviewed hideOnEdit"
            ?hidden=${!this.loggedIn}
            title="Toggle reviewed status of file"
            aria-label="file reviewed"
            ?checked=${this.reviewed}
            @change=${this.handleReviewedChange}
          ></md-checkbox>
        </div>
        <div class="jumpToFileContainer">
          <gr-dropdown-list
            id="dropdown"
            .value=${this.path ?? ''}
            .items=${formattedFiles}
            show-copy-for-trigger-text
            @value-change=${this.handleFileChange}
          ></gr-dropdown-list>
        </div>
      </div>
      <div class="navLinks desktop">
        <span class="fileNum ${ifDefined(fileNumClass)}">
          File ${fileNum} of ${formattedFiles.length}
          <span class="separator"></span>
        </span>
        <a
          class="navLink"
          title=${this.createTitle(
            Shortcut.PREV_FILE,
            ShortcutSection.NAVIGATION
          )}
          href=${ifDefined(this.computeNavLinkURL(-1))}
          >Prev</a
        >
        <span class="separator"></span>
        <a
          class="navLink"
          title=${this.createTitle(
            Shortcut.UP_TO_CHANGE,
            ShortcutSection.NAVIGATION
          )}
          href=${ifDefined(this.getChangeModel().changeUrl())}
          >Up</a
        >
        <span class="separator"></span>
        <a
          class="navLink"
          title=${this.createTitle(
            Shortcut.NEXT_FILE,
            ShortcutSection.NAVIGATION
          )}
          href=${ifDefined(this.computeNavLinkURL(1))}
          >Next</a
        >
      </div>`;
  }

  private renderSidebarTriggers() {
    return html`
      <div class="sidebarTriggerContainer">
        <gr-endpoint-decorator name="sidebarTrigger">
          <gr-endpoint-param
            name="onTrigger"
            .value=${(pluginName: string) => {
              const closeSidebar = this.shownSidebar === pluginName;
              this.shownSidebar = closeSidebar ? undefined : pluginName;
              this.getUserModel().updatePreferences({
                diff_page_sidebar: closeSidebar
                  ? 'NONE'
                  : `plugin-${pluginName}`,
              });
            }}
          ></gr-endpoint-param>
          <!-- params cannot start falsy, so the value must be wrapped -->
          <gr-endpoint-param
            name="openSidebar"
            .value=${{name: this.shownSidebar}}
          ></gr-endpoint-param>
        </gr-endpoint-decorator>
      </div>
    `;
  }

  private renderSidebarContent() {
    // Always renders the 0x0px .sidebarAnchor div for scroll measurements.
    return html`
      <div class="sidebarAnchor">
        ${when(
          this.shownSidebar !== undefined,
          () => html`
            <div
              class="sidebarContents"
              style=${styleMap({height: `${this.sidebarHeight}px`})}
            >
              <gr-endpoint-decorator
                name=${`sidebarContent-${this.shownSidebar}`}
              >
                <gr-endpoint-param
                  name="change"
                  .value=${this.change}
                ></gr-endpoint-param>
                <gr-endpoint-param
                  name="path"
                  .value=${this.path}
                ></gr-endpoint-param>
                <!-- current diff path and, in case of rename, previous path -->
                <gr-endpoint-param
                  name="fileRange"
                  .value=${this.getFileRange()}
                ></gr-endpoint-param>
                <gr-endpoint-param
                  name="basePatchNum"
                  .value=${this.basePatchNum}
                ></gr-endpoint-param>
                <gr-endpoint-param
                  name="patchNum"
                  .value=${this.patchNum}
                ></gr-endpoint-param>
                <gr-endpoint-param
                  name="content"
                  .value=${this.diff}
                ></gr-endpoint-param>
                <gr-endpoint-param
                  name="cursor"
                  .value=${this.cursor}
                ></gr-endpoint-param>
                <gr-endpoint-param
                  name="diff"
                  .value=${this.diffHost?.diffElement}
                ></gr-endpoint-param>
                <gr-endpoint-param
                  name="comments"
                  .value=${this.commentsForPath}
                ></gr-endpoint-param>
                <gr-endpoint-param
                  name="onClose"
                  .value=${(pluginName: string) => {
                    // Only close the sidebar if that particular sidebar is
                    // still open. An async onClose callback should not close a
                    // different sidebar.
                    if (this.shownSidebar !== pluginName) return;
                    this.shownSidebar = undefined;
                    this.getUserModel().updatePreferences({
                      diff_page_sidebar: 'NONE',
                    });
                  }}
                >
                </gr-endpoint-param>
              </gr-endpoint-decorator>
            </div>
          `
        )}
      </div>
    `;
  }

  private renderPatchRangeLeft() {
    return html` <div class="patchRangeLeft">
      <gr-patch-range-select
        id="rangeSelect"
        .filesWeblinks=${this.filesWeblinks}
        .path=${this.path}
        @patch-range-change=${this.handlePatchChange}
      >
      </gr-patch-range-select>
      <span class="download desktop">
        <span class="separator"></span>
        <gr-dropdown
          link=""
          down-arrow=""
          .items=${this.computeDownloadDropdownLinks()}
          .disabledIds=${this.isTooLargeForDownload()
            ? ['left-content', 'right-content']
            : []}
          horizontal-align="left"
        >
          <span class="downloadTitle"> Download </span>
        </gr-dropdown>
      </span>
    </div>`;
  }

  private renderRightControls() {
    const diffModeSelectorClass = !this.diff || this.diff.binary ? 'hide' : '';
    return html` <div class="rightControls">
      <gr-endpoint-decorator
        name="diff-header-controls"
      ></gr-endpoint-decorator>
      ${this.renderSidebarTriggers()} ${this.renderShowEntireFileButton()}
      ${this.renderBlameButton()}
      ${when(
        this.computeCanEdit(),
        () => html`
          <span class="separator"></span>
          <span class="editButton">
            <gr-button
              link=""
              title="Edit current file"
              @click=${this.goToEditFile}
              >Edit</gr-button
            >
          </span>
        `
      )}
      ${when(
        this.computeShowEditLinks(),
        () => html`
          <span class="separator"></span>
          ${this.editWeblinks!.map(
            weblink => html`<gr-weblink .info=${weblink}></gr-weblink>`
          )}
        `
      )}
      ${when(
        this.loggedIn && this.prefs,
        () => html`
          <span class="separator"></span>
          <div class="diffModeSelector ${diffModeSelectorClass}">
            <span>Diff view:</span>
            <gr-diff-mode-selector
              id="modeSelect"
              .saveOnChange=${this.loggedIn}
              show-tooltip-below
            ></gr-diff-mode-selector>
          </div>
          <span id="diffPrefsContainer">
            <span class="preferences desktop">
              <gr-tooltip-content
                has-tooltip=""
                position-below=""
                title="Diff preferences"
              >
                <gr-button
                  link=""
                  class="prefsButton"
                  @click=${(e: Event) => this.handlePrefsTap(e)}
                  ><gr-icon icon="settings" filled></gr-icon
                ></gr-button>
              </gr-tooltip-content>
            </span>
          </span>
        `
      )}
      <gr-endpoint-decorator name="annotation-toggler">
        <span hidden="" id="annotation-span">
          <label id="annotation-label" for="annotation-checkbox"></label>
          <md-checkbox
            id="annotation-checkbox"
            touch-target="none"
            disabled
            aria-labelledby="annotation-label"
          ></md-checkbox>
        </span>
      </gr-endpoint-decorator>
    </div>`;
  }

  private renderShowEntireFileButton() {
    if (isImageDiff(this.diff) || isMagicPath(this.path)) return;
    return html`<gr-button
      link=""
      id="toggleEntireFile"
      title=${this.createTitle(
        Shortcut.TOGGLE_ALL_DIFF_CONTEXT,
        ShortcutSection.DIFFS
      )}
      @click=${this.handleToggleAllDiffContext}
      >${this.isShowingEntireFile
        ? 'Hide Unchanged Lines'
        : 'Show Entire File'}</gr-button
    >`;
  }

  private renderBlameButton() {
    if (!this.allowBlame) return;
    const showBlameLoader = !isMagicPath(this.path) && !isImageDiff(this.diff);
    if (!showBlameLoader) return;
    let blameToggleLabel = 'Loading blame ...';
    if (!this.isBlameLoading) {
      blameToggleLabel = this.isBlameLoaded ? 'Hide Blame' : 'Show Blame';
    }
    return html`<span class="separator"></span
      ><span class="blameLoader">
        <gr-button
          link=""
          id="toggleBlame"
          title=${this.createTitle(
            Shortcut.TOGGLE_BLAME,
            ShortcutSection.DIFFS
          )}
          ?disabled=${this.isBlameLoading}
          @click=${this.toggleBlame}
          >${blameToggleLabel}</gr-button
        >
      </span>`;
  }

  private renderDialogs() {
    return html`
      <gr-apply-fix-dialog id="applyFixDialog"></gr-apply-fix-dialog>
      <gr-diff-preferences-dialog id="diffPreferencesDialog">
      </gr-diff-preferences-dialog>
      <dialog id="downloadModal" tabindex="-1">
        <gr-download-dialog
          id="downloadDialog"
          @close=${this.handleDownloadDialogClose}
        ></gr-download-dialog>
      </dialog>
    `;
  }

  /**
   * Set initial review status of the file.
   * automatically mark the file as reviewed if manual review is not set.
   */
  setReviewedStatus(
    patchNum: RevisionPatchSetNum,
    diffPrefs: DiffPreferencesInfo
  ) {
    if (!this.loggedIn) return;
    if (!diffPrefs.manual_review) {
      this.setReviewed(true, patchNum);
    }
  }

  /**
   * Returns the current file path and, if it was renamed in this change, the
   * previous file path.
   */
  private getFileRange() {
    if (!this.files || !this.path) return;
    const fileInfo = this.files.changeFilesByPath[this.path];
    const fileRange: FileRange = {path: this.path};
    if (fileInfo?.old_path) {
      fileRange.basePath = fileInfo.old_path;
    }
    return fileRange;
  }

  private handleReviewedChange(e: Event) {
    const input = e.target as MdCheckbox;
    this.setReviewed(input.checked ?? false);
  }

  // Private but used in tests.
  setReviewed(
    reviewed: boolean,
    patchNum: RevisionPatchSetNum | undefined = this.patchNum
  ) {
    if (this.patchNum === EDIT) return;
    if (!patchNum || !this.path || !this.changeNum) return;
    // if file is already reviewed then do not make a saveReview request
    if (this.reviewedFiles.has(this.path) && reviewed) return;
    // optimistic update
    this.reviewed = reviewed;
    this.getChangeModel().setReviewedFilesStatus(
      this.changeNum,
      patchNum,
      this.path,
      reviewed
    );
  }

  // Private but used in tests.
  handleToggleFileReviewed() {
    this.setReviewed(!this.reviewed);
  }

  private handlePrevLine() {
    assertIsDefined(this.diffHost, 'diffHost');
    this.cursor?.moveUp();
  }

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

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

  private onDiffChanged(e: ValueChangedEvent<DiffInfo>) {
    this.diff = e.detail.value;
  }

  private onEditWeblinksChanged(
    e: ValueChangedEvent<WebLinkInfo[] | undefined>
  ) {
    this.editWeblinks = e.detail.value;
  }

  private onFilesWeblinksChanged(
    e: ValueChangedEvent<FilesWebLinks | undefined>
  ) {
    this.filesWeblinks = e.detail.value;
  }

  private handleNextLine() {
    assertIsDefined(this.diffHost, 'diffHost');
    this.cursor?.moveDown();
  }

  // Private but used in tests.
  moveToFileWithComment(direction: -1 | 1) {
    const path = this.findFileWithComment(direction);
    if (!path) {
      this.getChangeModel().navigateToChange();
    } else {
      this.getChangeModel().navigateToDiff({path});
    }
  }

  private handleNewComment() {
    this.classList.remove('hideComments');
    this.classList.remove('hideCheckCodePointers');
    this.cursor?.createCommentInPlace();
  }

  private handlePrevFile() {
    if (!this.path) return;
    if (!this.files?.sortedPaths) return;
    this.navToFile(this.files.sortedPaths, -1);
  }

  private handleNextFile() {
    if (!this.path) return;
    if (!this.files?.sortedPaths) return;
    this.navToFile(this.files.sortedPaths, 1);
  }

  private handleNextChunk() {
    const result = this.cursor?.moveToNextChunk();
    if (result === CursorMoveResult.CLIPPED && this.cursor?.isAtEnd()) {
      this.showToastAndNavigateFile('next', 'n');
    }
  }

  private handleNextCommentThread() {
    const result = this.cursor?.moveToNextCommentThread();
    if (result === CursorMoveResult.CLIPPED) {
      this.navigateToNextFileWithCommentThread();
    }
  }

  private lastDisplayedNavigateToFileToast: Map<string, number> = new Map();

  private showToastAndNavigateFile(direction: string, shortcut: string) {
    /*
     * If user presses p/n on the first/last diff chunk, show a toast informing
     * user that pressing it again will navigate them to previous/next
     * unreviewedfile if click happens within the time limit
     */
    if (
      this.lastDisplayedNavigateToFileToast.get(direction) &&
      Date.now() - this.lastDisplayedNavigateToFileToast.get(direction)! <=
        NAVIGATE_TO_NEXT_FILE_TIMEOUT_MS
    ) {
      // reset for next file
      this.lastDisplayedNavigateToFileToast.delete(direction);
      this.navigateToUnreviewedFile(direction);
    } else {
      this.lastDisplayedNavigateToFileToast.set(direction, Date.now());
      if (this.hasShownNavigateToFileToast.get(direction)) {
        // Popup for "direction" has already been shown once
        return;
      }
      fireAlert(
        this,
        `Press ${shortcut} again to navigate to ${direction} unreviewed file`
      );
      this.hasShownNavigateToFileToast.set(direction, true);
    }
  }

  private navigateToUnreviewedFile(direction: string) {
    if (!this.path) return;
    if (!this.files?.sortedPaths) return;
    if (!this.reviewedFiles) return;
    // Ensure that the currently viewed file always appears in unreviewedFiles
    // so we resolve the right "next" file.
    const unreviewedFiles = this.files.sortedPaths.filter(
      file => file === this.path || !this.reviewedFiles.has(file)
    );

    this.navToFile(unreviewedFiles, direction === 'next' ? 1 : -1);
  }

  private handlePrevChunk() {
    this.cursor?.moveToPreviousChunk();
    if (this.cursor?.isAtStart()) {
      this.showToastAndNavigateFile('previous', 'p');
    }
  }

  private handlePrevCommentThread() {
    this.cursor?.moveToPreviousCommentThread();
  }

  // Similar to gr-change-view.handleOpenReplyDialog
  private handleOpenReplyDialog() {
    if (!this.loggedIn) {
      fire(this, 'show-auth-required', {});
      return;
    }
    this.getChangeModel().navigateToChange(true);
  }

  private handleToggleLeftPane() {
    assertIsDefined(this.diffHost, 'diffHost');
    this.diffHost.toggleLeftDiff();
  }

  // private but used in tests
  handleOpenDownloadDialog() {
    assertIsDefined(this.downloadModal, 'downloadModal');
    this.downloadModal.showModal();
    whenVisible(this.downloadModal, () => {
      assertIsDefined(this.downloadModal, 'downloadModal');
      assertIsDefined(this.downloadDialog, 'downloadDialog');
      this.downloadDialog.focus();
    });
  }

  private handleDownloadDialogClose() {
    assertIsDefined(this.downloadModal, 'downloadModal');
    this.downloadModal.close();
  }

  private handleCommaKey() {
    if (!this.loggedIn) return;
    assertIsDefined(this.diffPreferencesDialog, 'diffPreferencesDialog');
    this.diffPreferencesDialog.open();
  }

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

  // Private but used in tests.
  navToFile(
    fileList: string[],
    direction: -1 | 1,
    navigateToFirstComment?: boolean
  ) {
    const newPath = this.getNavLinkPath(fileList, direction);
    if (!newPath) return;
    if (!this.patchRange) return;

    if (newPath.up) {
      this.getChangeModel().navigateToChange();
      return;
    }

    if (!newPath.path) return;
    let lineNum;
    if (navigateToFirstComment)
      lineNum = this.changeComments?.getCommentsForPath(
        newPath.path,
        this.patchRange
      )?.[0].line;
    this.getChangeModel().navigateToDiff({path: newPath.path, lineNum});
  }

  /**
   * @param direction Either 1 (next file) or -1 (prev file).
   * @return The next URL when proceeding in the specified
   * direction.
   */
  private computeNavLinkURL(direction?: -1 | 1) {
    if (!this.change) return;
    if (!this.path) return;
    if (!this.files?.sortedPaths) return;
    if (!direction) return;

    const newPath = this.getNavLinkPath(this.files.sortedPaths, direction);
    if (!newPath) return;
    if (newPath.up) return this.getChangeModel().changeUrl();
    if (!newPath.path) return;
    if (!this.patchNum) return;
    return this.getViewModel().diffUrl({
      diffView: {path: newPath.path},
      patchNum: this.patchNum,
    });
  }

  private goToEditFile() {
    assertIsDefined(this.path, 'path');

    const lineNumber = this.cursor?.getTargetLineNumber();
    const lineNum = typeof lineNumber === 'number' ? lineNumber : undefined;
    this.getChangeModel().navigateToEdit({path: this.path, lineNum});
  }

  /**
   * Gives an object representing the target of navigating either left or
   * right through the change. The resulting object will have one of the
   * following forms:
   * * {path: "<target file path>"} - When another file path should be the
   * result of the navigation.
   * * {up: true} - When the result of navigating should go back to the
   * change view.
   * * null - When no navigation is possible for the given direction.
   *
   * @param path The path of the current file being shown.
   * @param fileList The list of files in this change and
   * patch range.
   * @param direction Either 1 (next file) or -1 (prev file).
   */
  private getNavLinkPath(fileList: string[], direction: -1 | 1) {
    if (!this.path || !fileList || fileList.length === 0) {
      return null;
    }
    let idx = fileList.indexOf(this.path);
    if (idx === -1) {
      const file = direction > 0 ? fileList[0] : fileList[fileList.length - 1];
      return {path: file};
    }

    idx += direction;
    // Redirect to the change view if noUp isn't truthy and idx falls
    // outside the bounds of [0, fileList.length).
    if (idx < 0 || idx > fileList.length - 1) {
      return {up: true};
    }

    return {path: fileList[idx]};
  }

  private updateUrlToDiffUrl(lineNum?: number, leftSide?: boolean) {
    if (!this.path || !this.patchNum) return;
    const url = this.getViewModel().diffUrl({
      diffView: {
        path: this.path,
        lineNum,
        leftSide,
      },
      patchNum: this.patchNum,
    });
    history.replaceState(null, '', url);
  }

  async reloadDiff() {
    if (!this.diffHost) return;
    await this.diffHost.reload(true);
    this.reporting.diffViewDisplayed();
    if (this.isBlameLoaded) this.loadBlame();
    this.isShowingEntireFile = this.diffHost?.isShowFullContext() ?? false;
  }

  /**
   * (Re-initialize) the diff view without actually reloading the diff. The
   * typical user journey is that the user comes back from the change page.
   */
  initializePositions() {
    // The diff view is kept in the background once created. If the user
    // scrolls in the change page, the scrolling is reflected in the diff view
    // as well, which means the diff is scrolled to a random position based
    // on how much the change view was scrolled.
    // Hence, reset the scroll position here.
    document.documentElement.scrollTop = 0;
    this.initCursor();
    this.reInitCursor();
    this.diffHost?.initLayers();
    this.classList.remove('hideComments');
    this.classList.remove('hideCheckCodePointers');
  }

  /**
   * If the params specify a diff address then configure the diff cursor.
   * Private but used in tests.
   */
  initCursor() {
    if (!this.focusLineNum) return;
    if (!this.cursor) return;
    this.cursor.side = this.leftSide ? Side.LEFT : Side.RIGHT;
    this.cursor.initialLineNumber = this.focusLineNum;
  }

  // Private but used in tests.
  getLineOfInterest(): DisplayLine | undefined {
    // If there is a line number specified, pass it along to the diff so that
    // it will not get collapsed.
    if (!this.focusLineNum) return undefined;

    return {
      lineNum: this.focusLineNum,
      side: this.leftSide ? Side.LEFT : Side.RIGHT,
    };
  }

  // Private but used in tests
  formatFilesForDropdown(): DropdownItem[] {
    if (!this.files) return [];
    if (!this.patchRange) return [];
    if (!this.changeComments) return [];

    const dropdownContent: DropdownItem[] = [];
    for (const path of this.files.sortedPaths) {
      const file = this.files.changeFilesByPath[path];
      dropdownContent.push({
        text: computeDisplayPath(path),
        mobileText: computeTruncatedPath(path),
        value: path,
        bottomText: this.changeComments.computeCommentsString(
          this.patchRange,
          path,
          file,
          /* includeUnmodified= */ true
        ),
        file,
      });
    }
    return dropdownContent;
  }

  // Private but used in tests.
  handleFileChange(e: ValueChangedEvent<string>) {
    const path: string = e.detail.value;
    if (path === this.path) return;
    this.getChangeModel().navigateToDiff({path});
  }

  // Private but used in tests.
  handlePatchChange(e: PatchRangeChangeEvent) {
    if (!this.path) return;
    if (!this.patchNum) return;

    const {basePatchNum, patchNum} = e.detail;
    if (basePatchNum === this.basePatchNum && patchNum === this.patchNum) {
      return;
    }
    this.getChangeModel().navigateToDiff(
      {path: this.path},
      patchNum,
      basePatchNum
    );
  }

  // Private but used in tests.
  handlePrefsTap(e: Event) {
    e.preventDefault();
    assertIsDefined(this.diffPreferencesDialog, 'diffPreferencesDialog');
    this.diffPreferencesDialog.open();
  }

  // Private but used in tests.
  onCommentAnchorTap(e: CustomEvent<CommentAnchorTapEventDetail>) {
    const lineNumber = e.detail.number;
    if (!Number.isInteger(lineNumber)) return;
    this.updateUrlToDiffUrl(
      lineNumber as number,
      e.detail.side === CommentSide.PARENT
    );
  }

  // Private but used in tests.
  onLineSelected(e: CustomEvent<LineSelectedEventDetail>) {
    const lineNumber = e.detail.number;
    if (!Number.isInteger(lineNumber)) return;
    this.updateUrlToDiffUrl(lineNumber as number, e.detail.side === Side.LEFT);
  }

  private isTooLargeForDownload() {
    return (this.file?.size ?? 0) > FILE_DOWNLOAD_LIMIT_BYTES;
  }

  // Private but used in tests.
  computeDownloadDropdownLinks(): DropdownLink[] {
    if (!this.change?.project) return [];
    if (!this.changeNum) return [];
    if (!this.patchRange) return [];
    if (!this.path) return [];

    const links: DropdownLink[] = [
      {
        url: this.computeDownloadPatchLink(
          this.change.project,
          this.changeNum,
          this.patchRange,
          this.path
        ),
        name: 'Patch',
      },
    ];

    if (this.isTooLargeForDownload()) {
      links.push({
        id: 'left-content',
        name: 'Left Content (Too Large)',
      });
      links.push({
        id: 'right-content',
        name: 'Right Content (Too Large)',
      });
    } else {
      if (this.diff && this.diff.meta_a) {
        let leftPath = this.path;
        if (this.diff.change_type === 'RENAMED') {
          leftPath = this.diff.meta_a.name;
        }
        links.push({
          url: this.computeDownloadFileLink(
            this.change.project,
            this.changeNum,
            this.patchRange,
            leftPath,
            true
          ),
          name: 'Left Content',
        });
      }

      if (this.diff && this.diff.meta_b) {
        links.push({
          url: this.computeDownloadFileLink(
            this.change.project,
            this.changeNum,
            this.patchRange,
            this.path,
            false
          ),
          name: 'Right Content',
        });
      }
    }

    return links;
  }

  // TODO: Move to view-model or router.
  // Private but used in tests.
  computeDownloadFileLink(
    repo: RepoName,
    changeNum: NumericChangeId,
    patchRange: PatchRange,
    path: string,
    isBase?: boolean
  ) {
    let patchNum = patchRange.patchNum;
    let parent: number | undefined = undefined;

    if (isBase) {
      if (isMergeParent(patchRange.basePatchNum)) {
        parent = getParentIndex(patchRange.basePatchNum);
      } else if (patchRange.basePatchNum === PARENT) {
        parent = 1;
      } else {
        patchNum = patchRange.basePatchNum as PatchSetNumber;
      }
    }
    let url =
      changeBaseURL(repo, changeNum, patchNum) +
      `/files/${encodeURIComponent(path)}/download`;
    if (parent) url += `?parent=${parent}`;

    return url;
  }

  // TODO: Move to view-model or router.
  // Private but used in tests.
  computeDownloadPatchLink(
    repo: RepoName,
    changeNum: NumericChangeId,
    patchRange: PatchRange,
    path: string
  ) {
    let url = changeBaseURL(repo, changeNum, patchRange.patchNum);
    url += '/patch?zip&path=' + encodeURIComponent(path);
    return url;
  }

  // Private but used in tests.
  findFileWithComment(direction: -1 | 1): string | undefined {
    const fileList = this.files?.sortedPaths;
    const commentMap: CommentMap =
      this.changeComments?.getPaths(this.patchRange) ?? {};
    if (!fileList || fileList.length === 0) return undefined;
    if (!this.path) return undefined;

    const pathIndex = fileList.indexOf(this.path);
    const stopIndex = direction === 1 ? fileList.length : -1;
    for (let i = pathIndex + direction; i !== stopIndex; i += direction) {
      if (commentMap[fileList[i]]) return fileList[i];
    }
    return undefined;
  }

  // Private but used in tests.
  loadBlame() {
    this.isBlameLoading = true;
    fireAlert(this, LOADING_BLAME);
    assertIsDefined(this.diffHost, 'diffHost');
    this.diffHost
      .loadBlame()
      .then(() => {
        this.isBlameLoading = false;
        fireAlert(this, LOADED_BLAME);
      })
      .catch(() => {
        this.isBlameLoading = false;
      });
  }

  /**
   * Load and display blame information if it has not already been loaded.
   * Otherwise hide it.
   */
  private toggleBlame() {
    if (!this.allowBlame) return;
    assertIsDefined(this.diffHost, 'diffHost');
    if (this.isBlameLoaded) {
      this.diffHost.clearBlame();
    } else {
      this.loadBlame();
    }
  }

  // Private but used in tests.
  handleToggleHideAllCommentsAndCodePointers() {
    const hideComments = this.classList.toggle('hideComments');
    /* Hide the check results along with the comments
       when the user presses the keyboard shortcut 'h'. */
    if (hideComments) {
      this.classList.add('hideCheckCodePointers');
    } else {
      this.classList.remove('hideCheckCodePointers');
    }
  }

  // Private but used in tests.
  handleToggleHideCheckCodePointers() {
    this.classList.toggle('hideCheckCodePointers');
  }

  private handleOpenFileList() {
    assertIsDefined(this.dropdown, 'dropdown');
    this.dropdown.open();
  }

  // Private but used in tests.
  handleDiffAgainstBase() {
    if (!this.isActiveChildView) return;
    assertIsDefined(this.path, 'path');
    assertIsDefined(this.patchNum, 'patchNum');

    if (this.basePatchNum === PARENT) {
      fireAlert(this, 'Base is already selected.');
      return;
    }
    this.getChangeModel().navigateToDiff(
      {path: this.path},
      this.patchNum,
      PARENT
    );
  }

  // Private but used in tests.
  handleDiffBaseAgainstLeft() {
    if (!this.isActiveChildView) return;
    assertIsDefined(this.path, 'path');
    assertIsDefined(this.patchNum, 'patchNum');

    if (this.basePatchNum === PARENT) {
      fireAlert(this, 'Left is already base.');
      return;
    }
    this.getChangeModel().navigateToDiff(
      {path: this.path},
      this.basePatchNum as RevisionPatchSetNum,
      PARENT
    );
  }

  // Private but used in tests.
  handleDiffAgainstLatest() {
    if (!this.isActiveChildView) return;
    assertIsDefined(this.path, 'path');
    assertIsDefined(this.patchNum, 'patchNum');

    if (this.patchNum === this.latestPatchNum) {
      fireAlert(this, 'Latest is already selected.');
      return;
    }

    this.getChangeModel().navigateToDiff(
      {path: this.path},
      this.latestPatchNum,
      this.basePatchNum
    );
  }

  // Private but used in tests.
  handleDiffRightAgainstLatest() {
    if (!this.isActiveChildView) return;
    assertIsDefined(this.path, 'path');
    assertIsDefined(this.patchNum, 'patchNum');

    if (this.patchNum === this.latestPatchNum) {
      fireAlert(this, 'Right is already latest.');
      return;
    }

    this.getChangeModel().navigateToDiff(
      {path: this.path},
      this.latestPatchNum,
      this.patchNum as BasePatchSetNum
    );
  }

  // Private but used in tests.
  handleDiffBaseAgainstLatest() {
    if (!this.isActiveChildView) return;
    assertIsDefined(this.path, 'path');
    assertIsDefined(this.patchNum, 'patchNum');

    if (this.patchNum === this.latestPatchNum && this.basePatchNum === PARENT) {
      fireAlert(this, 'Already diffing base against latest.');
      return;
    }

    this.getChangeModel().navigateToDiff(
      {path: this.path},
      this.latestPatchNum,
      PARENT
    );
  }

  // Private but used in tests.
  computeFileNum(files: DropdownItem[]) {
    if (!this.path || !files) return undefined;

    return files.findIndex(({value}) => value === this.path) + 1;
  }

  // Private but used in tests.
  computeFileNumClass(fileNum?: number, files?: DropdownItem[]) {
    if (files && fileNum && fileNum > 0) {
      return 'show';
    }
    return '';
  }

  private handleToggleAllDiffContext() {
    assertIsDefined(this.diffHost, 'diffHost');
    this.isShowingEntireFile = !this.isShowingEntireFile;
    this.diffHost.toggleAllContext();
  }

  private handleNextUnreviewedFile() {
    this.setReviewed(true);
    this.navigateToUnreviewedFile('next');
  }

  private navigateToNextFileWithCommentThread() {
    if (!this.path) return;
    if (!this.files?.sortedPaths) return;
    const range = this.patchRange;
    if (!range) return;
    if (!this.change) return;
    const hasComment = (path: string) =>
      this.changeComments?.getCommentsForPath(path, range)?.length ?? 0 > 0;
    const filesWithComments = this.files.sortedPaths.filter(
      file => file === this.path || hasComment(file)
    );
    this.navToFile(filesWithComments, 1, true);
  }

  private computeCanEdit() {
    return (
      !!this.change &&
      !!this.loggedIn &&
      changeIsOpen(this.change) &&
      !this.computeShowEditLinks()
    );
  }

  private computeShowEditLinks() {
    return !!this.editWeblinks && this.editWeblinks.length > 0;
  }

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

declare global {
  interface HTMLElementTagNameMap {
    'gr-diff-view': GrDiffView;
  }
}
