/**
 * @license
 * Copyright 2015 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import '../../../styles/gr-a11y-styles';
import '../../../styles/shared-styles';
import '../../diff/gr-diff-host/gr-diff-host';
import '../../diff/gr-diff-preferences-dialog/gr-diff-preferences-dialog';
import '../../edit/gr-edit-file-controls/gr-edit-file-controls';
import '../../shared/gr-button/gr-button';
import '../../shared/gr-cursor-manager/gr-cursor-manager';
import '../../shared/gr-icon/gr-icon';
import '../../shared/gr-select/gr-select';
import '../../shared/gr-tooltip-content/gr-tooltip-content';
import '../../shared/gr-copy-clipboard/gr-copy-clipboard';
import '../../shared/gr-file-status/gr-file-status';
import '../gr-comments-summary/gr-comments-summary';
import {assertIsDefined} from '../../../utils/common-util';
import {asyncForeach} from '../../../utils/async-util';
import {FilesExpandedState} from '../gr-file-list-constants';
import {diffFilePaths, pluralize} from '../../../utils/string-util';
import {navigationToken} from '../../core/gr-navigation/gr-navigation';
import {getAppContext} from '../../../services/app-context';
import {
  DiffViewMode,
  FileInfoStatus,
  ScrollMode,
  SpecialFilePath,
} from '../../../constants/constants';
import {descendedFromClass, Key} from '../../../utils/dom-util';
import {
  computeDisplayPath,
  computeTruncatedPath,
  isMagicPath,
} from '../../../utils/path-list-util';
import {customElement, property, query, state} from 'lit/decorators.js';
import {
  BasePatchSetNum,
  EDIT,
  FileInfo,
  NumericChangeId,
  PARENT,
  PatchRange,
  RevisionPatchSetNum,
} from '../../../types/common';
import {DiffPreferencesInfo} from '../../../types/diff';
import {GrDiffHost} from '../../diff/gr-diff-host/gr-diff-host';
import {GrDiffPreferencesDialog} from '../../diff/gr-diff-preferences-dialog/gr-diff-preferences-dialog';
import {GrDiffCursor} from '../../../embed/diff/gr-diff-cursor/gr-diff-cursor';
import {GrCursorManager} from '../../shared/gr-cursor-manager/gr-cursor-manager';
import {ChangeComments} from '../../diff/gr-comment-api/gr-comment-api';
import {ParsedChangeInfo, PatchSetFile} from '../../../types/types';
import {Timing, Interaction} from '../../../constants/reporting';
import {RevisionInfo} from '../../shared/revision-info/revision-info';
import {select} from '../../../utils/observable-util';
import {resolve} from '../../../models/dependency';
import {browserModelToken} from '../../../models/browser/browser-model';
import {commentsModelToken} from '../../../models/comments/comments-model';
import {RunResult, checksModelToken} from '../../../models/checks/checks-model';
import {changeModelToken} from '../../../models/change/change-model';
import {filesModelToken} from '../../../models/change/files-model';
import {ShortcutController} from '../../lit/shortcut-controller';
import {
  css,
  html,
  LitElement,
  nothing,
  PropertyValues,
  TemplateResult,
} from 'lit';
import {Shortcut} from '../../../services/shortcuts/shortcuts-config';
import {fire} from '../../../utils/event-util';
import {a11yStyles} from '../../../styles/gr-a11y-styles';
import {sharedStyles} from '../../../styles/shared-styles';
import {ValueChangedEvent} from '../../../types/events';
import {subscribe} from '../../lit/subscription-controller';
import {when} from 'lit/directives/when.js';
import {classMap} from 'lit/directives/class-map.js';
import {incrementalRepeat} from '../../lit/incremental-repeat';
import {ifDefined} from 'lit/directives/if-defined.js';
import {
  createChangeUrl,
  changeViewModelToken,
} from '../../../models/views/change';
import {userModelToken} from '../../../models/user/user-model';
import {pluginLoaderToken} from '../../shared/gr-js-api-interface/gr-plugin-loader';
import {FileMode, fileModeToString} from '../../../utils/file-util';
import {ChecksIcon, iconFor} from '../../../models/checks/checks-util';

export const DEFAULT_NUM_FILES_SHOWN = 200;

const WARN_SHOW_ALL_THRESHOLD = 1000;

const SIZE_BAR_MAX_WIDTH = 61;
const SIZE_BAR_GAP_WIDTH = 1;
const SIZE_BAR_MIN_WIDTH = 1.5;

const FILE_ROW_CLASS = 'file-row';

export interface NormalizedFileInfo extends FileInfo {
  __path: string;
}

interface PatchChange {
  inserted: number;
  deleted: number;
  size_delta_inserted: number;
  size_delta_deleted: number;
  total_size: number;
}

function createDefaultPatchChange(): PatchChange {
  // Use function instead of const to prevent unexpected changes in the default
  // values.
  return {
    inserted: 0,
    deleted: 0,
    size_delta_inserted: 0,
    size_delta_deleted: 0,
    total_size: 0,
  };
}

interface SizeBarLayout {
  maxInserted: number;
  maxDeleted: number;
  maxAdditionWidth: number;
  maxDeletionWidth: number;
  additionOffset: number;
}

function createDefaultSizeBarLayout(): SizeBarLayout {
  // Use function instead of const to prevent unexpected changes in the default
  // values.
  return {
    maxInserted: 0,
    maxDeleted: 0,
    maxAdditionWidth: 0,
    maxDeletionWidth: 0,
    additionOffset: 0,
  };
}

interface FileRow {
  file: PatchSetFile;
  element: HTMLElement;
}

/**
 * Type for FileInfo
 *
 * This should match with the type returned from `files` API plus
 * additional info like `__path`.
 *
 * @typedef {Object} FileInfo
 * @property {string} __path
 * @property {?string} old_path
 * @property {number} size
 * @property {number} size_delta - fallback to 0 if not present in api
 * @property {number} lines_deleted - fallback to 0 if not present in api
 * @property {number} lines_inserted - fallback to 0 if not present in api
 */

declare global {
  interface HTMLElementEventMap {
    'files-shown-changed': CustomEvent<{length: number}>;
    'files-expanded-changed': ValueChangedEvent<FilesExpandedState>;
    'diff-prefs-changed': ValueChangedEvent<DiffPreferencesInfo>;
  }
  interface HTMLElementTagNameMap {
    'gr-file-list': GrFileList;
  }
}
@customElement('gr-file-list')
export class GrFileList extends LitElement {
  @query('#diffPreferencesDialog')
  diffPreferencesDialog?: GrDiffPreferencesDialog;

  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;

  @property({type: Number})
  changeNum?: NumericChangeId;

  @property({type: Object})
  changeComments?: ChangeComments;

  @property({type: Array})
  checkResults?: RunResult[];

  @state() selectedIndex = 0;

  @property({type: Object})
  change?: ParsedChangeInfo;

  @state()
  diffViewMode?: DiffViewMode;

  @property({type: Boolean})
  editMode = false;

  private _filesExpanded = FilesExpandedState.NONE;

  get filesExpanded() {
    return this._filesExpanded;
  }

  set filesExpanded(filesExpanded: FilesExpandedState) {
    if (this._filesExpanded === filesExpanded) return;
    const oldFilesExpanded = this._filesExpanded;
    this._filesExpanded = filesExpanded;
    fire(this, 'files-expanded-changed', {value: this._filesExpanded});
    this.requestUpdate('filesExpanded', oldFilesExpanded);
  }

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

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

  @state() private filesRightBase: NormalizedFileInfo[] = [];

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

  /**
   * List of paths of files that are marked as reviewed. Direct model
   * subscription.
   */
  @state()
  reviewed: string[] = [];

  @state()
  diffPrefs?: DiffPreferencesInfo;

  @state() numFilesShown = 0;

  @state()
  fileListIncrement: number = DEFAULT_NUM_FILES_SHOWN;

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

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

  // For merge commits vs Auto Merge, an extra file row is shown detailing the
  // files that were merged without conflict. These files are also passed to any
  // plugins.
  @state()
  private cleanlyMergedPaths: string[] = [];

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

  private cancelForEachDiff?: () => void;

  @state()
  private dynamicHeaderEndpoints?: string[];

  @state()
  private dynamicContentEndpoints?: string[];

  @state()
  private dynamicSummaryEndpoints?: string[];

  @state()
  private dynamicPrependedHeaderEndpoints?: string[];

  @state()
  private dynamicPrependedContentEndpoints?: string[];

  private readonly reporting = getAppContext().reportingService;

  private readonly restApiService = getAppContext().restApiService;

  private readonly getPluginLoader = resolve(this, pluginLoaderToken);

  private readonly getUserModel = resolve(this, userModelToken);

  private readonly getChangeModel = resolve(this, changeModelToken);

  private readonly getFilesModel = resolve(this, filesModelToken);

  private readonly getCommentsModel = resolve(this, commentsModelToken);

  private readonly getChecksModel = resolve(this, checksModelToken);

  private readonly getBrowserModel = resolve(this, browserModelToken);

  shortcutsController = new ShortcutController(this);

  private readonly getNavigation = resolve(this, navigationToken);

  private readonly getViewModel = resolve(this, changeViewModelToken);

  // private but used in test
  fileCursor = new GrCursorManager();

  // private but used in test
  diffCursor?: GrDiffCursor;

  static override get styles() {
    return [
      a11yStyles,
      sharedStyles,
      css`
        :host {
          display: block;
        }
        .row {
          align-items: center;
          border-top: 1px solid var(--border-color);
          display: flex;
          min-height: calc(var(--line-height-normal) + 2 * var(--spacing-s));
          padding: var(--spacing-xs) var(--spacing-l);
        }
        /* The class defines a content visible only to screen readers */
        .noCommentsScreenReaderText {
          opacity: 0;
          max-width: 1px;
          overflow: hidden;
          display: none;
          vertical-align: top;
        }
        div[role='gridcell']
          > div.comments
          > span:empty
          + span:empty
          + span.noCommentsScreenReaderText {
          /* inline-block instead of block, such that it can control width */
          display: inline-block;
        }
        :host(.editMode) .hideOnEdit {
          display: none;
        }
        .showOnEdit {
          display: none;
        }
        :host(.editMode) .showOnEdit {
          display: initial;
        }
        .invisible {
          visibility: hidden;
        }
        .header-row {
          background-color: var(--background-color-secondary);
        }
        .controlRow {
          align-items: center;
          display: flex;
          height: 2.25em;
          justify-content: center;
        }
        .controlRow.invisible,
        .show-hide.invisible {
          display: none;
        }
        .reviewed {
          align-items: center;
          display: inline-flex;
        }
        .reviewed {
          display: inline-block;
          text-align: left;
          width: 1.5em;
        }
        .file-row {
          cursor: pointer;
        }
        .file-row.expanded {
          border-bottom: 1px solid var(--border-color);
          position: -webkit-sticky;
          position: sticky;
          top: 0;
          /* Has to visible above the diff view, and by default has a lower
            z-index. setting to 1 places it directly above. */
          z-index: 1;
        }
        .file-row:hover {
          background-color: var(--hover-background-color);
        }
        .file-row.selected {
          background-color: var(--selection-background-color);
        }
        .file-row.expanded,
        .file-row.expanded:hover {
          background-color: var(--expanded-background-color);
        }
        .status {
          margin-right: var(--spacing-m);
          display: flex;
          width: 20px;
          justify-content: flex-end;
        }
        .status.extended {
          width: 56px;
        }
        .status > * {
          display: block;
        }
        .header-row .status .content {
          width: 20px;
          text-align: center;
        }
        .path {
          flex: 1;
          /* Wrap it into multiple lines if too long. */
          white-space: normal;
          word-break: break-word;
        }
        .oldPath {
          color: var(--deemphasized-text-color);
        }
        .header-stats {
          text-align: center;
          min-width: 7.5em;
        }
        .stats {
          text-align: right;
          min-width: 7.5em;
        }
        .comments {
          padding-left: var(--spacing-l);
          min-width: 7.5em;
          white-space: nowrap;
        }
        .row:not(.header-row) .stats,
        .total-stats {
          font-family: var(--monospace-font-family);
          font-size: var(--font-size-mono);
          line-height: var(--line-height-mono);
          display: flex;
        }
        .sizeBars {
          margin-left: var(--spacing-m);
          min-width: 7em;
          text-align: center;
        }
        .sizeBars.hide {
          display: none;
        }
        .added,
        .removed {
          display: inline-block;
          min-width: 3.5em;
        }
        .added {
          color: var(--positive-green-text-color);
          text-align: left;
          min-width: 4em;
          padding-left: var(--spacing-s);
        }
        .removed {
          color: var(--negative-red-text-color);
        }
        .drafts {
          color: var(--error-foreground);
          font-weight: var(--font-weight-bold);
        }
        .show-hide-icon:focus {
          outline: none;
        }
        .show-hide {
          margin-left: var(--spacing-s);
          width: 1.9em;
        }
        .fileListButton {
          margin: var(--spacing-m);
        }
        .totalChanges {
          justify-content: flex-end;
          text-align: right;
        }
        .warning {
          color: var(--deemphasized-text-color);
        }
        input.show-hide {
          display: none;
        }
        label.show-hide {
          cursor: pointer;
          display: block;
          min-width: 2em;
        }
        gr-diff {
          display: block;
          overflow-x: auto;
        }
        .matchingFilePath {
          color: var(--deemphasized-text-color);
        }
        .newFilePath {
          color: var(--primary-text-color);
        }
        .fileName {
          color: var(--link-color);
        }
        .truncatedFileName {
          display: none;
        }
        .mobile {
          display: none;
        }
        .reviewed {
          margin-left: var(--spacing-xxl);
          width: 15em;
        }
        .reviewedSwitch {
          color: var(--link-color);
          opacity: 0;
          justify-content: flex-end;
          width: 100%;
        }
        .reviewedSwitch:hover {
          cursor: pointer;
          opacity: 100;
        }
        .showParentButton {
          line-height: var(--line-height-normal);
          margin-bottom: calc(var(--spacing-s) * -1);
          margin-left: var(--spacing-m);
          margin-top: calc(var(--spacing-s) * -1);
        }
        .row:focus {
          outline: none;
        }
        .row:hover .reviewedSwitch,
        .row:focus-within .reviewedSwitch,
        .row.expanded .reviewedSwitch {
          opacity: 100;
        }
        .reviewedLabel {
          color: var(--deemphasized-text-color);
          margin-right: var(--spacing-l);
          opacity: 0;
        }
        .reviewedLabel.isReviewed {
          display: initial;
          opacity: 100;
        }
        .editFileControls {
          width: 7em;
        }
        .markReviewed:focus {
          outline: none;
        }
        .markReviewed,
        .pathLink {
          display: inline-block;
          margin: -2px 0;
          padding: var(--spacing-s) 0;
          text-decoration: none;
        }
        .pathLink:hover span.fullFileName,
        .pathLink:hover span.truncatedFileName {
          text-decoration: underline;
        }

        /** copy on file path **/
        .pathLink gr-copy-clipboard,
        .oldPath gr-copy-clipboard {
          display: inline-block;
          visibility: hidden;
          vertical-align: bottom;
          --gr-button-padding: 0px;
        }
        .row:focus-within gr-copy-clipboard,
        .row:hover gr-copy-clipboard {
          visibility: visible;
        }

        .file-status-arrow {
          font-size: 16px;
          position: relative;
          top: 2px;
          display: block;
        }
        .file-mode-warning {
          font-size: 16px;
          position: relative;
          top: 2px;
          color: var(--warning-foreground);
        }
        .file-mode-content {
          display: inline-block;
          color: var(--deemphasized-text-color);
        }

        @media screen and (max-width: 1200px) {
          gr-endpoint-decorator.extra-col {
            display: none;
          }
        }

        @media screen and (max-width: 1000px) {
          .reviewed {
            display: none;
          }
        }

        @media screen and (max-width: 800px) {
          .desktop {
            display: none;
          }
          .mobile {
            display: block;
          }
          .row.selected {
            background-color: var(--view-background-color);
          }
          .stats {
            display: none;
          }
          .reviewed,
          .status {
            justify-content: flex-start;
          }
          .comments {
            min-width: initial;
          }
          .expanded .fullFileName,
          .truncatedFileName {
            display: inline;
          }
          .expanded .truncatedFileName,
          .fullFileName {
            display: none;
          }
        }
        :host(.hideComments) {
          --gr-comment-thread-display: none;
        }
        .checkChip {
          display: inline-flex;
          align-items: center;
          gap: var(--spacing-xs);
          border: 1px solid;
          border-radius: 999px;
          padding: var(--spacing-xxs) var(--spacing-m) var(--spacing-xxs)
            var(--spacing-s);
          vertical-align: top;
          position: relative;
          top: 2px;
          font-size: var(--font-size-small);
          font-weight: var(--font-weight-normal);
          line-height: var(--line-height-small);
          color: var(--primary-text-color);
          & gr-icon {
            font-size: var(--line-height-small);
          }
          &.info {
            border-color: var(--info-foreground);
            background-color: var(--info-background);
            & gr-icon {
              color: var(--info-foreground);
            }
          }
          &.warning {
            border-color: var(--warning-foreground);
            background-color: var(--warning-background);
            & gr-icon {
              color: var(--warning-foreground);
            }
          }
          &.error {
            border-color: var(--error-foreground);
            background-color: var(--error-background);
            & gr-icon {
              color: var(--error-foreground);
            }
          }
        }
      `,
    ];
  }

  constructor() {
    super();
    this.fileCursor.scrollMode = ScrollMode.KEEP_VISIBLE;
    this.fileCursor.cursorTargetClass = 'selected';
    this.fileCursor.focusOnMove = true;
    this.shortcutsController.addAbstract(Shortcut.LEFT_PANE, _ =>
      this.handleLeftPane()
    );
    this.shortcutsController.addAbstract(Shortcut.RIGHT_PANE, _ =>
      this.handleRightPane()
    );
    this.shortcutsController.addAbstract(Shortcut.TOGGLE_INLINE_DIFF, _ =>
      this.handleToggleInlineDiff()
    );
    this.shortcutsController.addAbstract(Shortcut.TOGGLE_ALL_INLINE_DIFFS, _ =>
      this.toggleInlineDiffs()
    );
    this.shortcutsController.addAbstract(
      Shortcut.TOGGLE_HIDE_ALL_COMMENT_THREADS,
      _ => this.classList.toggle('hideComments')
    );
    this.shortcutsController.addAbstract(
      Shortcut.CURSOR_NEXT_FILE,
      e => this.handleCursorNext(e),
      {preventDefault: false}
    );
    this.shortcutsController.addAbstract(
      Shortcut.CURSOR_PREV_FILE,
      e => this.handleCursorPrev(e),
      {preventDefault: false}
    );
    // This is already been taken care of by CURSOR_NEXT_FILE above. The two
    // shortcuts share the same bindings. It depends on whether all files
    // are expanded whether the cursor moves to the next file or line.
    this.shortcutsController.addAbstract(Shortcut.NEXT_LINE, _ => {}, {
      preventDefault: false,
    }); // docOnly
    // This is already been taken care of by CURSOR_PREV_FILE above. The two
    // shortcuts share the same bindings. It depends on whether all files
    // are expanded whether the cursor moves to the previous file or line.
    this.shortcutsController.addAbstract(Shortcut.PREV_LINE, _ => {}, {
      preventDefault: false,
    }); // docOnly
    this.shortcutsController.addAbstract(Shortcut.NEW_COMMENT, _ =>
      this.handleNewComment()
    );
    this.shortcutsController.addAbstract(Shortcut.OPEN_LAST_FILE, _ =>
      this.openSelectedFile(this.files.length - 1)
    );
    this.shortcutsController.addAbstract(Shortcut.OPEN_FIRST_FILE, _ =>
      this.openSelectedFile(0)
    );
    this.shortcutsController.addAbstract(Shortcut.OPEN_FILE, _ =>
      this.handleOpenFile()
    );
    this.shortcutsController.addAbstract(Shortcut.NEXT_CHUNK, _ =>
      this.handleNextChunk()
    );
    this.shortcutsController.addAbstract(Shortcut.PREV_CHUNK, _ =>
      this.handlePrevChunk()
    );
    this.shortcutsController.addAbstract(Shortcut.NEXT_COMMENT_THREAD, _ =>
      this.handleNextComment()
    );
    this.shortcutsController.addAbstract(Shortcut.PREV_COMMENT_THREAD, _ =>
      this.handlePrevComment()
    );
    this.shortcutsController.addAbstract(Shortcut.TOGGLE_FILE_REVIEWED, _ =>
      this.handleToggleFileReviewed()
    );
    this.shortcutsController.addAbstract(Shortcut.TOGGLE_LEFT_PANE, _ =>
      this.handleToggleLeftPane()
    );
    this.shortcutsController.addAbstract(
      Shortcut.EXPAND_ALL_COMMENT_THREADS,
      _ => {}
    ); // docOnly
    this.shortcutsController.addAbstract(
      Shortcut.COLLAPSE_ALL_COMMENT_THREADS,
      _ => {}
    ); // docOnly
    this.shortcutsController.addLocal(
      {key: Key.ENTER},
      _ => this.handleOpenFile(),
      {
        shouldSuppress: true,
      }
    );
    subscribe(
      this,
      () => this.getCommentsModel().changeComments$,
      changeComments => {
        this.changeComments = changeComments;
      }
    );
    subscribe(
      this,
      () => this.getChecksModel().allResultsSelected$,
      results => {
        this.checkResults = results;
      }
    );
    subscribe(
      this,
      () => this.getFilesModel().filesIncludingUnmodified$,
      files => {
        this.files = [...files];
      }
    );
    subscribe(
      this,
      () => this.getFilesModel().filesLeftBase$,
      files => {
        this.filesLeftBase = [...files];
      }
    );
    subscribe(
      this,
      () => this.getFilesModel().filesRightBase$,
      files => {
        this.filesRightBase = [...files];
      }
    );
    subscribe(
      this,
      () => this.getBrowserModel().diffViewMode$,
      diffView => {
        this.diffViewMode = diffView;
      }
    );
    subscribe(
      this,
      () => this.getUserModel().diffPreferences$,
      diffPreferences => {
        this.diffPrefs = diffPreferences;
      }
    );
    subscribe(
      this,
      () =>
        select(
          this.getUserModel().preferences$,
          prefs => !!prefs?.size_bar_in_change_table
        ),
      sizeBarInChangeTable => {
        this.showSizeBars = sizeBarInChangeTable;
      }
    );
    subscribe(
      this,
      () => this.getUserModel().loggedIn$,
      loggedIn => {
        this.loggedIn = loggedIn;
      }
    );
    subscribe(
      this,
      () => this.getChangeModel().reviewedFiles$,
      reviewedFiles => {
        this.reviewed = reviewedFiles ?? [];
      }
    );
    subscribe(
      this,
      () => this.getChangeModel().patchNum$,
      x => (this.patchNum = x)
    );
    subscribe(
      this,
      () => this.getChangeModel().basePatchNum$,
      x => (this.basePatchNum = x)
    );
  }

  override willUpdate(changedProperties: PropertyValues): void {
    if (
      changedProperties.has('patchNum') ||
      changedProperties.has('basePatchNum')
    ) {
      this.resetFileState();
      this.collapseAllDiffs();
    }
    if (
      changedProperties.has('diffPrefs') ||
      changedProperties.has('diffViewMode')
    ) {
      this.updateDiffPreferences();
    }
    if (changedProperties.has('files')) {
      this.filesChanged();
      this.numFilesShown = Math.min(this.files.length, DEFAULT_NUM_FILES_SHOWN);
      fire(this, 'files-shown-changed', {length: this.numFilesShown});
    }
    if (changedProperties.has('expandedFiles')) {
      this.expandedFilesChanged(changedProperties.get('expandedFiles'));
    }
    if (changedProperties.has('numFilesShown')) {
      fire(this, 'files-shown-changed', {length: this.numFilesShown});
    }
  }

  override connectedCallback() {
    super.connectedCallback();

    this.getPluginLoader()
      .awaitPluginsLoaded()
      .then(() => {
        this.dynamicHeaderEndpoints =
          this.getPluginLoader().pluginEndPoints.getDynamicEndpoints(
            'change-view-file-list-header'
          );
        this.dynamicContentEndpoints =
          this.getPluginLoader().pluginEndPoints.getDynamicEndpoints(
            'change-view-file-list-content'
          );
        this.dynamicPrependedHeaderEndpoints =
          this.getPluginLoader().pluginEndPoints.getDynamicEndpoints(
            'change-view-file-list-header-prepend'
          );
        this.dynamicPrependedContentEndpoints =
          this.getPluginLoader().pluginEndPoints.getDynamicEndpoints(
            'change-view-file-list-content-prepend'
          );
        this.dynamicSummaryEndpoints =
          this.getPluginLoader().pluginEndPoints.getDynamicEndpoints(
            'change-view-file-list-summary'
          );

        if (
          this.dynamicHeaderEndpoints.length !==
          this.dynamicContentEndpoints.length
        ) {
          this.reporting.error(
            'Plugin change-view-file-list',
            new Error('dynamic header/content mismatch')
          );
        }
        if (
          this.dynamicPrependedHeaderEndpoints.length !==
          this.dynamicPrependedContentEndpoints.length
        ) {
          this.reporting.error(
            'Plugin change-view-file-list',
            new Error('dynamic prepend header/content mismatch')
          );
        }
        if (
          this.dynamicHeaderEndpoints.length !==
          this.dynamicSummaryEndpoints.length
        ) {
          this.reporting.error(
            'Plugin change-view-file-list',
            new Error('dynamic header/summary mismatch')
          );
        }
      });
    this.diffCursor = new GrDiffCursor();
    this.diffCursor.replaceDiffs(this.diffs);
  }

  override disconnectedCallback() {
    this.diffCursor?.dispose();
    this.fileCursor.unsetCursor();
    this.cancelDiffs();
    super.disconnectedCallback();
  }

  protected override async getUpdateComplete(): Promise<boolean> {
    const result = await super.getUpdateComplete();
    await Promise.all(this.diffs.map(d => d.updateComplete));
    return result;
  }

  override render() {
    this.classList.toggle('editMode', this.editMode);
    const patchChange = this.calculatePatchChange();
    return html`
      <h3 class="assistive-tech-only">File list</h3>
      ${this.renderContainer()} ${this.renderChangeTotals(patchChange)}
      ${this.renderBinaryTotals(patchChange)} ${this.renderControlRow()}
      <gr-diff-preferences-dialog id="diffPreferencesDialog">
      </gr-diff-preferences-dialog>
    `;
  }

  private renderContainer() {
    return html`
      <div
        id="container"
        @click=${(e: MouseEvent) => this.handleFileListClick(e)}
        role="grid"
        aria-label="Files list"
      >
        ${this.renderHeaderRow()} ${this.renderShownFiles()}
        ${when(this.computeShowNumCleanlyMerged(), () =>
          this.renderCleanlyMerged()
        )}
      </div>
    `;
  }

  private renderHeaderRow() {
    const showPrependedDynamicColumns =
      this.computeShowPrependedDynamicColumns();
    const showDynamicColumns = this.computeShowDynamicColumns();
    return html` <div class="header-row row" role="row">
      <!-- endpoint: change-view-file-list-header-prepend -->
      ${when(showPrependedDynamicColumns, () =>
        this.renderPrependedHeaderEndpoints()
      )}
      ${this.renderFileStatus()}
      <div class="path" role="columnheader">File</div>
      <div class="comments desktop" role="columnheader">Comments</div>
      <div class="comments mobile" role="columnheader" title="Comments">C</div>
      ${when(
        this.showSizeBars,
        () => html`<div class="sizeBars desktop" role="columnheader">Size</div>`
      )}
      <div class="header-stats" role="columnheader">Delta</div>
      <!-- endpoint: change-view-file-list-header -->
      ${when(showDynamicColumns, () => this.renderDynamicHeaderEndpoints())}
      <!-- Empty div here exists to keep spacing in sync with file rows. -->
      <div
        class="reviewed hideOnEdit"
        ?hidden=${!this.loggedIn}
        aria-hidden="true"
      ></div>
      <div class="editFileControls showOnEdit" aria-hidden="true"></div>
      <div class="show-hide" aria-hidden="true"></div>
    </div>`;
  }

  private renderPrependedHeaderEndpoints() {
    return this.dynamicPrependedHeaderEndpoints?.map(
      headerEndpoint => html`
        <gr-endpoint-decorator
          class="prepended-col"
          .name=${headerEndpoint}
          role="columnheader"
        >
          <gr-endpoint-param name="change" .value=${this.change}>
          </gr-endpoint-param>
          <gr-endpoint-param name="patchRange" .value=${this.patchRange}>
          </gr-endpoint-param>
          <gr-endpoint-param name="files" .value=${this.files}>
          </gr-endpoint-param>
        </gr-endpoint-decorator>
      `
    );
  }

  private renderDynamicHeaderEndpoints() {
    return this.dynamicHeaderEndpoints?.map(
      headerEndpoint => html`
        <gr-endpoint-decorator
          class="extra-col"
          .name=${headerEndpoint}
          role="columnheader"
        >
          <gr-endpoint-param name="change" .value=${this.change}>
          </gr-endpoint-param>
        </gr-endpoint-decorator>
      `
    );
  }

  private renderShownFiles() {
    const showDynamicColumns = this.computeShowDynamicColumns();
    const showPrependedDynamicColumns =
      this.computeShowPrependedDynamicColumns();
    const sizeBarLayout = this.computeSizeBarLayout();

    return incrementalRepeat({
      values: this.files,
      mapFn: (f, i) =>
        this.renderFileRow(
          f as NormalizedFileInfo,
          i,
          sizeBarLayout,
          showDynamicColumns,
          showPrependedDynamicColumns
        ),
      initialCount: this.fileListIncrement,
      targetFrameRate: 1,
      startAt: 0,
      endAt: this.numFilesShown,
    });
  }

  private renderFileRow(
    file: NormalizedFileInfo,
    index: number,
    sizeBarLayout: SizeBarLayout,
    showDynamicColumns: boolean,
    showPrependedDynamicColumns: boolean
  ) {
    const previousFileName = this.files[index - 1]?.__path;
    const patchSetFile = this.computePatchSetFile(file);
    return html` <div class="stickyArea">
      <div
        class=${`file-row row ${this.computePathClass(file.__path)}`}
        data-file=${JSON.stringify(patchSetFile)}
        tabindex="-1"
        role="row"
        aria-label=${file.__path}
      >
        <!-- endpoint: change-view-file-list-content-prepend -->
        ${when(showPrependedDynamicColumns, () =>
          this.renderPrependedContentEndpointsForFile(file)
        )}
        ${this.renderFileStatus(file)}
        ${this.renderFilePath(file, previousFileName)}
        ${this.renderFileComments(file)}
        ${this.renderSizeBar(file, sizeBarLayout)} ${this.renderFileStats(file)}
        ${when(showDynamicColumns, () =>
          this.renderDynamicContentEndpointsForFile(file)
        )}
        <!-- endpoint: change-view-file-list-content -->
        ${this.renderReviewed(file)} ${this.renderFileControls(file)}
        ${this.renderShowHide(file)}
      </div>
      ${when(
        this.isFileExpanded(file.__path),
        () => html`
          <gr-diff-host
            ?noAutoRender=${true}
            ?showLoadFailure=${true}
            .changeNum=${this.changeNum}
            .change=${this.change}
            .patchRange=${this.patchRange}
            .file=${patchSetFile}
            .path=${file.__path}
            .projectName=${this.change?.project}
            ?noRenderOnPrefsChange=${true}
          ></gr-diff-host>
        `
      )}
    </div>`;
  }

  private renderPrependedContentEndpointsForFile(file: NormalizedFileInfo) {
    return this.dynamicPrependedContentEndpoints?.map(
      contentEndpoint => html`
        <gr-endpoint-decorator
          class="prepended-col"
          .name=${contentEndpoint}
          role="gridcell"
        >
          <gr-endpoint-param name="change" .value=${this.change}>
          </gr-endpoint-param>
          <gr-endpoint-param name="changeNum" .value=${this.changeNum}>
          </gr-endpoint-param>
          <gr-endpoint-param name="patchRange" .value=${this.patchRange}>
          </gr-endpoint-param>
          <gr-endpoint-param name="path" .value=${file.__path}>
          </gr-endpoint-param>
          <gr-endpoint-param name="oldPath" .value=${this.getOldPath(file)}>
          </gr-endpoint-param>
        </gr-endpoint-decorator>
      `
    );
  }

  private renderFileStatus(file?: NormalizedFileInfo) {
    const hasExtendedStatus = this.filesLeftBase.length > 0;
    const leftStatus = this.renderFileStatusLeft(file?.__path);
    const rightStatus = this.renderFileStatusRight(file);
    return html`<div
      class=${classMap({status: true, extended: hasExtendedStatus})}
      role="gridcell"
    >
      ${leftStatus}${rightStatus}
    </div>`;
  }

  private renderDivWithTooltip(
    content: TemplateResult | string,
    tooltip: string,
    cssClass = 'content'
  ) {
    return html`
      <gr-tooltip-content title=${tooltip} has-tooltip>
        <div class=${cssClass}>${content}</div>
      </gr-tooltip-content>
    `;
  }

  private renderFileStatusRight(file?: NormalizedFileInfo) {
    const hasExtendedStatus = this.filesLeftBase.length > 0;
    // no file means "header row"
    if (!file) {
      const psNum = this.patchNum;
      return hasExtendedStatus
        ? this.renderDivWithTooltip(`${psNum}`, `Patchset ${psNum}`)
        : nothing;
    }
    if (isMagicPath(file.__path)) return nothing;

    const fileWasAlreadyChanged = this.filesLeftBase.some(
      info => info.__path === file?.__path
    );
    const fileIsReverted =
      fileWasAlreadyChanged &&
      !this.filesRightBase.some(info => info.__path === file?.__path);
    const newlyChanged = hasExtendedStatus && !fileWasAlreadyChanged;

    const status = fileIsReverted
      ? FileInfoStatus.REVERTED
      : file?.status ?? FileInfoStatus.MODIFIED;
    const left = `patchset ${this.basePatchNum}`;
    const right = `patchset ${this.patchNum}`;
    const postfix = ` between ${left} and ${right}`;

    return html`<gr-file-status
      .status=${status}
      .labelPostfix=${postfix}
      ?newlyChanged=${newlyChanged}
    ></gr-file-status>`;
  }

  private renderFileStatusLeft(path?: string) {
    if (this.filesLeftBase.length === 0) return nothing;
    const arrow = html`
      <gr-icon
        icon="arrow_right_alt"
        class="file-status-arrow"
        aria-label="then"
      ></gr-icon>
    `;
    // no path means "header row"
    const psNum = this.basePatchNum;
    if (!path) {
      return html`
        ${this.renderDivWithTooltip(`${psNum}`, `Patchset ${psNum}`)} ${arrow}
      `;
    }
    if (isMagicPath(path)) return nothing;
    const file = this.filesLeftBase.find(info => info.__path === path);
    if (!file) return nothing;

    const status = file.status ?? FileInfoStatus.MODIFIED;
    const left = 'base';
    const right = `patchset ${this.basePatchNum}`;
    const postfix = ` between ${left} and ${right}`;

    return html`
      <gr-file-status
        .status=${status}
        .labelPostfix=${postfix}
      ></gr-file-status>
      ${arrow}
    `;
  }

  private renderFilePath(file: NormalizedFileInfo, previousFilePath?: string) {
    return html`
      <span class="path" role="gridcell">
        <a class="pathLink" href=${ifDefined(this.computeDiffURL(file.__path))}>
          <span title=${computeDisplayPath(file.__path)} class="fullFileName">
            ${this.renderStyledPath(file.__path, previousFilePath)}
          </span>
          <span
            title=${computeDisplayPath(file.__path)}
            class="truncatedFileName"
          >
            ${computeTruncatedPath(file.__path)}
          </span>
          ${this.renderFileMode(file)}
          <gr-copy-clipboard
            ?hideInput=${true}
            .text=${file.__path}
          ></gr-copy-clipboard>
        </a>
        ${when(
          file.old_path,
          () => html`
            <div class="oldPath" title=${ifDefined(file.old_path)}>
              ${file.old_path}
              <gr-copy-clipboard
                ?hideInput=${true}
                .text=${file.old_path}
              ></gr-copy-clipboard>
            </div>
          `
        )}
      </span>
    `;
  }

  private renderFileMode(file: NormalizedFileInfo) {
    const {old_mode, new_mode} = file;

    // For added, modified or deleted regular files we do not want to render
    // anything. Only if a file changed from something else to regular, then let
    // the user know.
    if (new_mode === undefined) return nothing;
    let newModeStr = fileModeToString(new_mode, false);
    if (new_mode === FileMode.REGULAR_FILE) {
      if (old_mode === undefined) return nothing;
      if (old_mode === FileMode.REGULAR_FILE) return nothing;
      newModeStr = `non-${fileModeToString(old_mode, false)}`;
    }

    const changed = old_mode !== undefined && old_mode !== new_mode;
    const icon = changed
      ? html`<gr-icon icon="warning" class="file-mode-warning"></gr-icon> `
      : '';
    const action = changed
      ? `changed from ${fileModeToString(old_mode)} to`
      : 'is';
    return this.renderDivWithTooltip(
      html`${icon}(${newModeStr})`,
      `file mode ${action} ${fileModeToString(new_mode)}`,
      'file-mode-content'
    );
  }

  private renderStyledPath(filePath: string, previousFilePath?: string) {
    const {matchingFolders, newFolders, fileName} = diffFilePaths(
      filePath,
      previousFilePath
    );
    return [
      matchingFolders.length > 0
        ? html`<span class="matchingFilePath">${matchingFolders}</span>`
        : nothing,
      newFolders.length > 0
        ? html`<span class="newFilePath">${newFolders}</span>`
        : nothing,
      html`<span class="fileName">${fileName}</span>`,
    ];
  }

  private renderFileComments(file: NormalizedFileInfo) {
    return html` <div role="gridcell">
      <div class="comments desktop">
        <span>${this.renderCommentsChips(file)}</span>
        <span>${this.renderChecksChips(file)}</span>
        <span class="noCommentsScreenReaderText">
          <!-- Screen readers read the following content only if 2 other
          spans in the parent div is empty. The content is not visible on
          the page.
          Without this span, screen readers don't navigate correctly inside
          table, because empty div doesn't rendered. For example, VoiceOver
          jumps back to the whole table.
          We can use &nbsp instead, but it sounds worse.
          -->
          No comments
        </span>
      </div>
      <div class="comments mobile">
        <span class="drafts">${this.computeDraftsStringMobile(file)}</span>
        <span>${this.computeCommentsStringMobile(file)}</span>
        <span class="noCommentsScreenReaderText">
          <!-- The same as for desktop comments -->
          No comments
        </span>
      </div>
    </div>`;
  }

  private renderSizeBar(
    file: NormalizedFileInfo,
    sizeBarLayout: SizeBarLayout
  ) {
    return html` <div class="desktop" role="gridcell">
      <!-- The content must be in a separate div. It guarantees, that
          gridcell always visible for screen readers.
          For example, without a nested div screen readers pronounce the
          "Commit message" row content with incorrect column headers.
        -->
      <div class=${this.computeSizeBarsClass(file.__path)} aria-hidden="true">
        <svg width="61" height="8">
          <rect
            x=${this.computeBarDeletionX(file, sizeBarLayout)}
            y="0"
            height="8"
            fill="var(--negative-red-text-color)"
            width=${this.computeBarDeletionWidth(file, sizeBarLayout)}
          ></rect>
          <rect
            x=${this.computeBarAdditionX(sizeBarLayout)}
            y="0"
            height="8"
            fill="var(--positive-green-text-color)"
            width=${this.computeBarAdditionWidth(file, sizeBarLayout)}
          ></rect>
        </svg>
      </div>
    </div>`;
  }

  private renderFileStats(file: NormalizedFileInfo) {
    return html` <div class="stats" role="gridcell">
      <!-- The content must be in a separate div. It guarantees, that
        gridcell always visible for screen readers.
        For example, without a nested div screen readers pronounce the
        "Commit message" row content with incorrect column headers.
        -->
      <div class=${this.computeClass('', file.__path)}>
        <span
          class="removed"
          tabindex="0"
          aria-label=${`${file.lines_deleted} removed`}
          ?hidden=${file.binary}
        >
          -${file.lines_deleted}
        </span>
        <span
          class="added"
          tabindex="0"
          aria-label=${`${file.lines_inserted} added`}
          ?hidden=${file.binary}
        >
          +${file.lines_inserted}
        </span>
        <span
          class=${ifDefined(this.computeBinaryClass(file.size_delta))}
          ?hidden=${!file.binary}
        >
          ${this.formatBytes(file.size_delta)}
          ${this.formatPercentage(file.size, file.size_delta)}
        </span>
      </div>
    </div>`;
  }

  private renderDynamicContentEndpointsForFile(file: NormalizedFileInfo) {
    return this.dynamicContentEndpoints?.map(
      contentEndpoint => html` <div
        class=${this.computeClass('', file.__path)}
        role="gridcell"
      >
        <gr-endpoint-decorator class="extra-col" .name=${contentEndpoint}>
          <gr-endpoint-param name="change" .value=${this.change}>
          </gr-endpoint-param>
          <gr-endpoint-param name="changeNum" .value=${this.changeNum}>
          </gr-endpoint-param>
          <gr-endpoint-param name="patchRange" .value=${this.patchRange}>
          </gr-endpoint-param>
          <gr-endpoint-param name="path" .value=${file.__path}>
          </gr-endpoint-param>
        </gr-endpoint-decorator>
      </div>`
    );
  }

  private renderReviewed(file: NormalizedFileInfo) {
    if (!this.loggedIn) return nothing;
    const isReviewed = this.reviewed.includes(file.__path);
    const reviewedTitle = `Mark as ${
      isReviewed ? 'not ' : ''
    }reviewed (shortcut: r)`;
    const reviewedText = isReviewed ? 'MARK UNREVIEWED' : 'MARK REVIEWED';
    return html` <div class="reviewed hideOnEdit" role="gridcell">
      <span
        class=${`reviewedLabel ${isReviewed ? 'isReviewed' : ''}`}
        aria-hidden=${this.booleanToString(!isReviewed)}
        >Reviewed</span
      >
      <!-- Do not use input type="checkbox" with hidden input and
              visible label here. Screen readers don't read/interract
              correctly with such input.
          -->
      <span
        class="reviewedSwitch"
        role="switch"
        tabindex="0"
        @click=${(e: MouseEvent) => this.reviewedClick(e)}
        @keydown=${(e: KeyboardEvent) => this.reviewedClick(e)}
        aria-label="Reviewed"
        aria-checked=${this.booleanToString(isReviewed)}
      >
        <!-- Trick with tabindex to avoid outline on mouse focus, but
            preserve focus outline for keyboard navigation -->
        <span tabindex="-1" class="markReviewed" title=${reviewedTitle}
          >${reviewedText}</span
        >
      </span>
    </div>`;
  }

  private renderFileControls(file: NormalizedFileInfo) {
    return html` <div
      class="editFileControls showOnEdit"
      role="gridcell"
      aria-hidden=${this.booleanToString(!this.editMode)}
    >
      ${when(
        this.editMode,
        () => html`
          <gr-edit-file-controls
            class=${this.computeClass(
              '',
              file.__path,
              /* showForCommitMessage */ true
            )}
            .filePath=${file.__path}
          ></gr-edit-file-controls>
        `
      )}
    </div>`;
  }

  private renderShowHide(file: NormalizedFileInfo) {
    const expanded = this.isFileExpanded(file.__path);
    return html` <div class="show-hide" role="gridcell">
      <!-- Do not use input type="checkbox" with hidden input and
            visible label here. Screen readers don't read/interract
            correctly with such input.
        -->
      <span
        class="show-hide"
        data-path=${file.__path}
        data-expand="true"
        role="switch"
        tabindex="0"
        aria-checked=${this.isFileExpandedStr(file.__path)}
        aria-label=${expanded ? 'collapse' : 'expand'}
        aria-description=${expanded
          ? 'Collapse diff of this file'
          : 'Expand diff of this file'}
        @click=${this.expandedClick}
        @keydown=${this.expandedClick}
      >
        <!-- Trick with tabindex to avoid outline on mouse focus, but
          preserve focus outline for keyboard navigation -->
        <gr-icon
          class="show-hide-icon"
          tabindex="-1"
          id="icon"
          icon=${expanded ? 'expand_less' : 'expand_more'}
        ></gr-icon>
      </span>
    </div>`;
  }

  private renderCleanlyMerged() {
    const showPrependedDynamicColumns =
      this.computeShowPrependedDynamicColumns();
    return html` <div class="row">
      <!-- endpoint: change-view-file-list-content-prepend -->
      ${when(showPrependedDynamicColumns, () =>
        this.renderPrependedContentEndpoints()
      )}
      <div role="gridcell">
        <div>
          <span class="cleanlyMergedText">
            ${this.computeCleanlyMergedText()}
          </span>
          <gr-button
            link
            class="showParentButton"
            @click=${this.handleShowParent1}
          >
            Show Parent 1
          </gr-button>
        </div>
      </div>
    </div>`;
  }

  private renderPrependedContentEndpoints() {
    return this.dynamicPrependedContentEndpoints?.map(
      contentEndpoint => html`
        <gr-endpoint-decorator
          class="prepended-col"
          .name=${contentEndpoint}
          role="gridcell"
        >
          <gr-endpoint-param name="change" .value=${this.change}>
          </gr-endpoint-param>
          <gr-endpoint-param name="changeNum" .value=${this.changeNum}>
          </gr-endpoint-param>
          <gr-endpoint-param name="patchRange" .value=${this.patchRange}>
          </gr-endpoint-param>
          <gr-endpoint-param
            name="cleanlyMergedPaths"
            .value=${this.cleanlyMergedPaths}
          >
          </gr-endpoint-param>
          <gr-endpoint-param
            name="cleanlyMergedOldPaths"
            .value=${this.cleanlyMergedOldPaths}
          >
          </gr-endpoint-param>
        </gr-endpoint-decorator>
      `
    );
  }

  private renderChangeTotals(patchChange: PatchChange) {
    const showDynamicColumns = this.computeShowDynamicColumns();
    if (this.shouldHideChangeTotals(patchChange)) return nothing;
    return html`
      <div class="row totalChanges">
        <div class="total-stats">
          <div>
            <span
              class="removed"
              tabindex="0"
              aria-label="Total ${patchChange.deleted} lines removed"
            >
              -${patchChange.deleted}
            </span>
            <span
              class="added"
              tabindex="0"
              aria-label="Total ${patchChange.inserted} lines added"
            >
              +${patchChange.inserted}
            </span>
          </div>
        </div>
        ${when(showDynamicColumns, () =>
          this.dynamicSummaryEndpoints?.map(
            summaryEndpoint => html`
              <gr-endpoint-decorator class="extra-col" name=${summaryEndpoint}>
                <gr-endpoint-param name="change" .value=${this.change}>
                </gr-endpoint-param>
                <gr-endpoint-param name="patchRange" .value=${this.patchRange}>
                </gr-endpoint-param>
              </gr-endpoint-decorator>
            `
          )
        )}

        <!-- Empty div here exists to keep spacing in sync with file rows. -->
        <div class="reviewed hideOnEdit" ?hidden=${!this.loggedIn}></div>
        <div class="editFileControls showOnEdit"></div>
        <div class="show-hide"></div>
      </div>
    `;
  }

  private renderBinaryTotals(patchChange: PatchChange) {
    if (this.shouldHideBinaryChangeTotals(patchChange)) return nothing;
    const deltaInserted = this.formatBytes(patchChange.size_delta_inserted);
    const deltaDeleted = this.formatBytes(patchChange.size_delta_deleted);
    return html`
      <div class="row totalChanges">
        <div class="total-stats">
          <span
            class="removed"
            aria-label="Total bytes removed: ${deltaDeleted}"
          >
            ${deltaDeleted}
            ${this.formatPercentage(
              patchChange.total_size,
              patchChange.size_delta_deleted
            )}
          </span>
          <span
            class="added"
            aria-label="Total bytes inserted: ${deltaInserted}"
          >
            ${deltaInserted}
            ${this.formatPercentage(
              patchChange.total_size,
              patchChange.size_delta_inserted
            )}
          </span>
        </div>
      </div>
    `;
  }

  private renderControlRow() {
    return html`<div
      class=${`row controlRow ${this.computeFileListControlClass()}`}
    >
      <gr-button
        class="fileListButton"
        id="incrementButton"
        link=""
        @click=${this.incrementNumFilesShown}
      >
        ${this.computeIncrementText()}
      </gr-button>
      <gr-tooltip-content
        ?has-tooltip=${this.computeWarnShowAll()}
        ?show-icon=${this.computeWarnShowAll()}
        .title=${this.computeShowAllWarning()}
      >
        <gr-button
          class="fileListButton"
          id="showAllButton"
          link=""
          @click=${this.showAllFiles}
        >
          ${this.computeShowAllText()}
        </gr-button>
      </gr-tooltip-content>
    </div>`;
  }

  renderCommentsChips(file?: NormalizedFileInfo) {
    if (!this.changeComments || !this.patchRange || !file?.__path) {
      return nothing;
    }
    const commentThreads = this.changeComments?.computeCommentsThreads(
      this.patchRange,
      file.__path,
      file
    );
    const draftCount = this.changeComments?.computeDraftCountForFile(
      this.patchRange,
      file
    );
    return html`<gr-comments-summary
      .commentThreads=${commentThreads}
      .draftCount=${draftCount}
      emptyWhenNoComments
    ></gr-comments-summary>`;
  }

  renderChecksChips(file?: NormalizedFileInfo) {
    if (!this.checkResults || !this.patchRange || !file?.__path) {
      return nothing;
    }

    const iconsByName: Record<string, ChecksIcon[]> = {};
    for (const result of this.checkResults ?? []) {
      if (
        result.codePointers === undefined ||
        !result.codePointers.some(pointer => pointer.path === file.__path)
      ) {
        continue;
      }
      const icon = iconFor(result.category);
      iconsByName[icon.name] ??= [];
      iconsByName[icon.name].push(icon);
    }

    return Object.values(iconsByName).map(
      icons =>
        html`
          <div class="checkChip ${icons[0].name}">
            <gr-icon icon=${icons[0].name} ?filled=${icons[0].filled}></gr-icon>
            <div>${icons.length}</div>
          </div>
        `
    );
  }

  protected override firstUpdated(): void {
    this.detectChromiteButler();
    this.reporting.fileListDisplayed();
  }

  // TODO: Move into files-model.
  // visible for testing
  async updateCleanlyMergedPaths() {
    // When viewing Auto Merge base vs a patchset, add an additional row that
    // knows how many files were cleanly merged. This requires an additional RPC
    // for the diffs between target parent and the patch set. The cleanly merged
    // files are all the files in the target RPC that weren't in the Auto Merge
    // RPC.
    if (
      this.change &&
      this.changeNum &&
      this.patchNum &&
      new RevisionInfo(this.change).isMergeCommit(this.patchNum) &&
      this.basePatchNum === PARENT &&
      this.patchNum !== EDIT
    ) {
      const allFilesByPath = await this.restApiService.getChangeOrEditFiles(
        this.changeNum,
        {
          basePatchNum: -1 as BasePatchSetNum, // -1 is first (target) parent
          patchNum: this.patchNum,
        }
      );
      if (!allFilesByPath) return;
      const conflictingPaths = this.files.map(f => f.__path);
      this.cleanlyMergedPaths = Object.keys(allFilesByPath).filter(
        path => !conflictingPaths.includes(path)
      );
      this.cleanlyMergedOldPaths = this.cleanlyMergedPaths
        .map(path => allFilesByPath[path].old_path)
        .filter((oldPath): oldPath is string => !!oldPath);
    } else {
      this.cleanlyMergedPaths = [];
      this.cleanlyMergedOldPaths = [];
    }
  }

  private detectChromiteButler() {
    const hasButler = !!document.getElementById('butler-suggested-owners');
    if (hasButler) {
      this.reporting.reportExtension('butler');
    }
  }

  get diffs(): GrDiffHost[] {
    const diffs = this.shadowRoot!.querySelectorAll('gr-diff-host');
    // It is possible that a bogus diff element is hanging around invisibly
    // from earlier with a different patch set choice and associated with a
    // different entry in the files array. So filter on visible items only.
    return Array.from(diffs).filter(
      el => !!el && !!el.style && el.style.display !== 'none'
    );
  }

  resetFileState() {
    this.numFilesShown = DEFAULT_NUM_FILES_SHOWN;
    this.selectedIndex = 0;
    this.fileCursor.setCursorAtIndex(this.selectedIndex, true);
  }

  openDiffPrefs() {
    this.diffPreferencesDialog?.open();
  }

  // Private but used in tests.
  calculatePatchChange(): PatchChange {
    const magicFilesExcluded = this.files.filter(
      file => !isMagicPath(file.__path)
    );

    return magicFilesExcluded.reduce((acc, obj) => {
      const inserted = obj.lines_inserted ? obj.lines_inserted : 0;
      const deleted = obj.lines_deleted ? obj.lines_deleted : 0;
      const total_size = obj.size && obj.binary ? obj.size : 0;
      const size_delta_inserted =
        obj.binary && obj.size_delta && obj.size_delta > 0 ? obj.size_delta : 0;
      const size_delta_deleted =
        obj.binary && obj.size_delta && obj.size_delta < 0 ? obj.size_delta : 0;

      return {
        inserted: acc.inserted + inserted,
        deleted: acc.deleted + deleted,
        size_delta_inserted: acc.size_delta_inserted + size_delta_inserted,
        size_delta_deleted: acc.size_delta_deleted + size_delta_deleted,
        total_size: acc.total_size + total_size,
      };
    }, createDefaultPatchChange());
  }

  // private but used in test
  toggleFileExpanded(file: PatchSetFile) {
    // Is the path in the list of expanded diffs? If so, remove it, otherwise
    // add it to the list.
    const indexInExpanded = this.expandedFiles.findIndex(
      f => f.path === file.path
    );
    if (indexInExpanded === -1) {
      this.reporting.reportInteraction(Interaction.FILE_LIST_DIFF_EXPANDED);
      this.expandedFiles = this.expandedFiles.concat([file]);
    } else {
      this.reporting.reportInteraction(Interaction.FILE_LIST_DIFF_COLLAPSED);
      this.expandedFiles = this.expandedFiles.filter(
        (_val, idx) => idx !== indexInExpanded
      );
    }
    const indexInAll = this.files.findIndex(f => f.__path === file.path);
    this.shadowRoot!.querySelectorAll(`.${FILE_ROW_CLASS}`)[
      indexInAll
    ].scrollIntoView({block: 'nearest'});
  }

  private toggleFileExpandedByIndex(index: number) {
    this.toggleFileExpanded(this.computePatchSetFile(this.files[index]));
  }

  // Private but used in tests.
  updateDiffPreferences() {
    if (!this.diffs.length) {
      return;
    }
    // Re-render all expanded diffs sequentially.
    this.renderInOrder(this.expandedFiles, this.diffs);
  }

  private forEachDiff(fn: (host: GrDiffHost) => void) {
    const diffs = this.diffs;
    for (let i = 0; i < diffs.length; i++) {
      fn(diffs[i]);
    }
  }

  expandAllDiffs() {
    // Find the list of paths that are in the file list, but not in the
    // expanded list.
    const newFiles: PatchSetFile[] = [];
    let path: string;
    for (let i = 0; i < this.numFilesShown; i++) {
      path = this.files[i].__path;
      if (!this.expandedFiles.some(f => f.path === path)) {
        newFiles.push(this.computePatchSetFile(this.files[i]));
      }
    }

    this.reporting.reportInteraction(Interaction.FILE_LIST_ALL_DIFFS_EXPANDED);
    this.expandedFiles = newFiles.concat(this.expandedFiles);
  }

  collapseAllDiffs() {
    this.reporting.reportInteraction(Interaction.FILE_LIST_ALL_DIFFS_COLLAPSED);
    this.expandedFiles = [];
  }

  /**
   * Computes a shortened string with the number of drafts.
   * Private but used in tests.
   */
  computeDraftsStringMobile(file?: NormalizedFileInfo) {
    if (this.changeComments === undefined) return '';
    const draftCount = this.changeComments.computeDraftCountForFile(
      this.patchRange,
      file
    );
    return draftCount === 0 ? '' : `${draftCount}d`;
  }

  /**
   * Computes a shortened string with the number of comments.
   */
  computeCommentsStringMobile(file?: NormalizedFileInfo) {
    if (
      this.changeComments === undefined ||
      this.patchRange === undefined ||
      file === undefined
    ) {
      return '';
    }
    const commentThreadCount =
      this.changeComments.computeCommentThreads({
        patchNum: this.patchRange.basePatchNum,
        path: file.__path,
      }).length +
      this.changeComments.computeCommentThreads({
        patchNum: this.patchRange.patchNum,
        path: file.__path,
      }).length;
    return commentThreadCount === 0 ? '' : `${commentThreadCount}c`;
  }

  // Private but used in tests.
  reviewFile(path: string, reviewed?: boolean) {
    if (this.editMode) return Promise.resolve();
    reviewed = reviewed ?? !this.reviewed.includes(path);
    return this._saveReviewedState(path, reviewed);
  }

  _saveReviewedState(path: string, reviewed: boolean) {
    assertIsDefined(this.changeNum, 'changeNum');
    assertIsDefined(this.patchRange, 'patchRange');

    return this.getChangeModel().setReviewedFilesStatus(
      this.changeNum,
      this.patchRange.patchNum,
      path,
      reviewed
    );
  }

  /**
   * Returns true if the event e is a click on an element.
   *
   * The click is: mouse click or pressing Enter or Space key
   * P.S> Screen readers sends click event as well
   */
  private isClickEvent(e: MouseEvent | KeyboardEvent) {
    if (e.type === 'click') {
      return true;
    }
    const ke = e as KeyboardEvent;
    const isSpaceOrEnter = ke.key === 'Enter' || ke.key === ' ';
    return ke.type === 'keydown' && isSpaceOrEnter;
  }

  private fileActionClick(
    e: MouseEvent | KeyboardEvent,
    fileAction: (file: PatchSetFile) => void
  ) {
    if (this.isClickEvent(e)) {
      const fileRow = this.getFileRowFromEvent(e);
      if (!fileRow) {
        return;
      }
      // Prevent default actions (e.g. scrolling for space key)
      e.preventDefault();
      // Prevent handleFileListClick handler call
      e.stopPropagation();
      this.fileCursor.setCursor(fileRow.element);
      fileAction(fileRow.file);
    }
  }

  // Private but used in tests.
  reviewedClick(e: MouseEvent | KeyboardEvent) {
    this.fileActionClick(e, file => this.reviewFile(file.path));
  }

  private expandedClick(e: MouseEvent | KeyboardEvent) {
    this.fileActionClick(e, file => this.toggleFileExpanded(file));
  }

  /**
   * Handle all events from the file list dom-repeat so event handlers don't
   * have to get registered for potentially very long lists.
   * Private but used in tests.
   */
  handleFileListClick(e: MouseEvent) {
    if (!e.target) {
      return;
    }
    const fileRow = this.getFileRowFromEvent(e);
    if (!fileRow) {
      return;
    }
    const file = fileRow.file;
    const path = file.path;
    // If a path cannot be interpreted from the click target (meaning it's not
    // somewhere in the row, e.g. diff content) or if the user clicked the
    // link, defer to the native behavior.
    if (!path || descendedFromClass(e.target as Element, 'pathLink')) {
      return;
    }

    // Disregard the event if the click target is in the edit controls.
    if (descendedFromClass(e.target as Element, 'editFileControls')) {
      return;
    }

    e.preventDefault();
    this.fileCursor.setCursor(fileRow.element);
    this.toggleFileExpanded(file);
  }

  private getFileRowFromEvent(e: Event): FileRow | null {
    // Traverse upwards to find the row element if the target is not the row.
    let row = e.target as HTMLElement;
    while (!row.classList.contains(FILE_ROW_CLASS) && row.parentElement) {
      row = row.parentElement;
    }

    // No action needed for item without a valid file
    if (!row.dataset['file']) {
      return null;
    }

    return {
      file: JSON.parse(row.dataset['file']) as PatchSetFile,
      element: row,
    };
  }

  /**
   * Generates file range from file info object.
   */
  private computePatchSetFile(file: NormalizedFileInfo): PatchSetFile {
    const fileData: PatchSetFile = {
      path: file.__path,
    };
    if (file.old_path) {
      fileData.basePath = file.old_path;
    }
    return fileData;
  }

  private handleLeftPane() {
    if (this.noDiffsExpanded()) return;
    this.diffCursor?.moveLeft();
  }

  private handleRightPane() {
    if (this.noDiffsExpanded()) return;
    this.diffCursor?.moveRight();
  }

  private handleToggleInlineDiff() {
    if (this.fileCursor.index === -1) return;
    this.toggleFileExpandedByIndex(this.fileCursor.index);
  }

  // Private but used in tests.
  handleCursorNext(e: KeyboardEvent) {
    // We want to allow users to use arrow keys for standard browser scrolling
    // when files are not expanded. That is also why we use the `preventDefault`
    // option when registering the shortcut.
    if (this.filesExpanded !== FilesExpandedState.ALL && e.key === Key.DOWN) {
      return;
    }

    e.preventDefault();
    e.stopPropagation();
    if (this.filesExpanded === FilesExpandedState.ALL) {
      this.diffCursor?.moveDown();
    } else {
      this.fileCursor.next({circular: true});
      this.selectedIndex = this.fileCursor.index;
    }
  }

  // Private but used in tests.
  handleCursorPrev(e: KeyboardEvent) {
    // We want to allow users to use arrow keys for standard browser scrolling
    // when files are not expanded. That is also why we use the `preventDefault`
    // option when registering the shortcut.
    if (this.filesExpanded !== FilesExpandedState.ALL && e.key === Key.UP) {
      return;
    }

    e.preventDefault();
    e.stopPropagation();
    if (this.filesExpanded === FilesExpandedState.ALL) {
      this.diffCursor?.moveUp();
    } else {
      this.fileCursor.previous({circular: true});
      this.selectedIndex = this.fileCursor.index;
    }
  }

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

  // Private but used in tests.
  handleOpenFile() {
    if (this.filesExpanded === FilesExpandedState.ALL) {
      this.openCursorFile();
      return;
    }
    this.openSelectedFile();
  }

  private handleNextChunk() {
    if (this.noDiffsExpanded()) return;
    this.diffCursor?.moveToNextChunk();
  }

  private handleNextComment() {
    if (this.noDiffsExpanded()) return;
    this.diffCursor?.moveToNextCommentThread();
  }

  private handlePrevChunk() {
    if (this.noDiffsExpanded()) return;
    this.diffCursor?.moveToPreviousChunk();
  }

  private handlePrevComment() {
    if (this.noDiffsExpanded()) return;
    this.diffCursor?.moveToPreviousCommentThread();
  }

  private handleToggleFileReviewed() {
    if (!this.files[this.fileCursor.index]) {
      return;
    }
    this.reviewFile(this.files[this.fileCursor.index].__path);
  }

  private handleToggleLeftPane() {
    this.forEachDiff(diff => {
      diff.toggleLeftDiff();
    });
  }

  private toggleInlineDiffs() {
    if (this.filesExpanded === FilesExpandedState.ALL) {
      this.collapseAllDiffs();
    } else {
      this.expandAllDiffs();
    }
  }

  // Private but used in tests.
  openCursorFile() {
    const diff = this.diffCursor?.getTargetDiffElement();
    if (!this.change || !diff || !this.patchNum || !diff.path) {
      throw new Error('change, diff and pacthNum must be all set and valid');
    }
    this.getNavigation().setUrl(
      this.getViewModel().diffUrl({
        diffView: {path: diff.path},
        patchNum: this.patchNum,
      })
    );
  }

  // Private but used in tests.
  openSelectedFile(index?: number) {
    if (index !== undefined) {
      this.fileCursor.setCursorAtIndex(index);
    }
    if (!this.files[this.fileCursor.index]) {
      return;
    }
    if (!this.change || !this.patchNum) {
      throw new Error('change and patchRange must be set');
    }
    this.getNavigation().setUrl(
      this.getViewModel().diffUrl({
        diffView: {path: this.files[this.fileCursor.index].__path},
        patchNum: this.patchNum,
      })
    );
  }

  // Private but used in tests.
  shouldHideChangeTotals(patchChange: PatchChange): boolean {
    return patchChange.inserted === 0 && patchChange.deleted === 0;
  }

  // Private but used in tests.
  shouldHideBinaryChangeTotals(patchChange: PatchChange) {
    return (
      patchChange.size_delta_inserted === 0 &&
      patchChange.size_delta_deleted === 0
    );
  }

  /** Returns an edit or diff URL depending on `editMode`. */
  // Private but used in tests
  computeDiffURL(path?: string): string | undefined {
    if (path === undefined) return;
    if (this.patchNum === undefined) return;

    if (this.editMode && path !== SpecialFilePath.MERGE_LIST) {
      return this.getViewModel().editUrl({
        patchNum: this.patchNum,
        editView: {path},
      });
    }
    return this.getViewModel().diffUrl({
      diffView: {path},
      patchNum: this.patchNum,
    });
  }

  // Private but used in tests.
  formatBytes(bytes?: number) {
    if (!bytes) return '+/-0 B';
    const bits = 1024;
    const decimals = 1;
    const sizes = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
    const exponent = Math.floor(Math.log(Math.abs(bytes)) / Math.log(bits));
    const prepend = bytes > 0 ? '+' : '';
    const value = parseFloat(
      (bytes / Math.pow(bits, exponent)).toFixed(decimals)
    );
    return `${prepend}${value} ${sizes[exponent]}`;
  }

  // Private but used in tests.
  formatPercentage(size?: number, delta?: number) {
    if (size === undefined || delta === undefined) {
      return '';
    }
    const oldSize = size - delta;

    if (oldSize === 0) {
      return '';
    }

    const percentage = Math.round(Math.abs((delta * 100) / oldSize));
    return `(${delta > 0 ? '+' : '-'}${percentage}%)`;
  }

  private computeBinaryClass(delta?: number) {
    if (!delta) {
      return;
    }
    return delta > 0 ? 'added' : 'removed';
  }

  // Private but used in tests.
  computeClass(baseClass = '', path?: string, showForCommitMessage = false) {
    const classes = [baseClass];
    if (
      !(showForCommitMessage && path === SpecialFilePath.COMMIT_MESSAGE) &&
      isMagicPath(path)
    ) {
      classes.push('invisible');
    }

    return classes.join(' ').trim();
  }

  private computePathClass(path: string | undefined) {
    return this.isFileExpanded(path) ? 'expanded' : '';
  }

  private computeShowNumCleanlyMerged(): boolean {
    return this.cleanlyMergedPaths.length > 0;
  }

  private computeCleanlyMergedText(): string {
    const fileCount = pluralize(this.cleanlyMergedPaths.length, 'file');
    return `${fileCount} merged cleanly in Parent 1`;
  }

  private handleShowParent1(): void {
    if (!this.change || !this.patchRange) return;
    this.getNavigation().setUrl(
      createChangeUrl({
        change: this.change,
        patchNum: this.patchRange.patchNum,
        basePatchNum: -1 as BasePatchSetNum, // Parent 1
      })
    );
  }

  // Private but used in tests.
  updateDiffCursor() {
    // Overwrite the cursor's list of diffs:
    this.diffCursor?.replaceDiffs(this.diffs);
  }

  async filesChanged() {
    if (this.expandedFiles.length > 0) this.expandedFiles = [];
    await this.updateCleanlyMergedPaths();
    if (!this.files || this.files.length === 0) return;
    await this.updateComplete;
    this.fileCursor.stops = Array.from(
      this.shadowRoot?.querySelectorAll(`.${FILE_ROW_CLASS}`) ?? []
    );
    this.fileCursor.setCursorAtIndex(this.selectedIndex, true);
  }

  private incrementNumFilesShown() {
    this.numFilesShown += this.fileListIncrement;
    if (this.numFilesShown > this.files.length) {
      this.numFilesShown = this.files.length;
    }
  }

  private computeFileListControlClass() {
    return this.numFilesShown >= this.files.length ? 'invisible' : '';
  }

  private computeIncrementText() {
    const text = Math.min(
      this.fileListIncrement,
      this.files.length - this.numFilesShown
    );
    return `Show ${text} more`;
  }

  private computeShowAllText() {
    return `Show all ${this.files.length} files`;
  }

  private computeWarnShowAll() {
    return this.files.length > WARN_SHOW_ALL_THRESHOLD;
  }

  private computeShowAllWarning() {
    if (!this.computeWarnShowAll()) {
      return '';
    }
    return `Warning: showing all ${this.files.length} files may take several seconds.`;
  }

  private showAllFiles() {
    this.numFilesShown = this.files.length;
  }

  /**
   * Converts any boolean-like variable to the string 'true' or 'false'
   *
   * This method is useful when you bind aria-checked attribute to a boolean
   * value. The aria-checked attribute is string attribute. Binding directly
   * to boolean variable causes problem on gerrit-CI.
   *
   * @return 'true' if val is true-like, otherwise false
   */
  private booleanToString(val?: unknown) {
    return val ? 'true' : 'false';
  }

  private isFileExpanded(path: string | undefined) {
    return this.expandedFiles.some(f => f.path === path);
  }

  private isFileExpandedStr(path: string | undefined) {
    return this.booleanToString(this.isFileExpanded(path));
  }

  private computeExpandedFiles(): FilesExpandedState {
    if (this.expandedFiles.length === 0) {
      return FilesExpandedState.NONE;
    } else if (this.expandedFiles.length === this.files.length) {
      return FilesExpandedState.ALL;
    }
    return FilesExpandedState.SOME;
  }

  /**
   * Handle splices to the list of expanded file paths. If there are any new
   * entries in the expanded list, then render each diff corresponding in
   * order by waiting for the previous diff to finish before starting the next
   * one.
   *
   * @param newFiles The new files that have been added.
   * Private but used in tests.
   */
  async expandedFilesChanged(oldFiles: Array<PatchSetFile>) {
    this.filesExpanded = this.computeExpandedFiles();

    const newFiles = this.expandedFiles.filter(
      file => (oldFiles ?? []).findIndex(f => f.path === file.path) === -1
    );

    // Required so that the newly created diff view is included in this.diffs.
    await this.updateComplete;

    if (newFiles.length) {
      await this.renderInOrder(newFiles, this.diffs);
    }
    this.updateDiffCursor();
    this.diffCursor?.reInitAndUpdateStops();
  }

  /**
   * Given an array of paths and a NodeList of diff elements, render the diff
   * for each path in order, awaiting the previous render to complete before
   * continuing.
   *
   * private but used in test
   *
   * @param initialCount The total number of paths in the pass.
   */
  async renderInOrder(files: PatchSetFile[], diffElements: GrDiffHost[]) {
    this.reporting.time(Timing.FILE_EXPAND_ALL);

    for (const file of files) {
      const path = file.path;
      const diffElem = this.findDiffByPath(path, diffElements);
      if (!diffElem) {
        this.reporting.error(
          'GrFileList',
          new Error(`Did not find <gr-diff-host> element for ${path}`)
        );
        return;
      }
      diffElem.prefetchDiff();
    }

    await asyncForeach(files, async (file, cancel) => {
      const path = file.path;
      this.cancelForEachDiff = cancel;

      const diffElem = this.findDiffByPath(path, diffElements);
      if (!diffElem) {
        this.reporting.error(
          'GrFileList',
          new Error(`Did not find <gr-diff-host> element for ${path}`)
        );
        return;
      }
      if (!this.diffPrefs) {
        throw new Error('diffPrefs must be set');
      }

      // When one file is expanded individually then automatically mark as
      // reviewed, if the user's diff prefs request it. Doing this for
      // "Expand All" would not be what the user wants, because there is no
      // control over which diffs were actually seen. And for lots of diffs
      // that would even be a problem for write QPS quota.
      if (
        this.loggedIn &&
        !this.diffPrefs.manual_review &&
        files.length === 1
      ) {
        await this.reviewFile(path, true);
      }
      await diffElem.reload();
    });

    this.cancelForEachDiff = undefined;
    this.reporting.timeEnd(Timing.FILE_EXPAND_ALL, {
      count: files.length,
      height: this.clientHeight,
    });
    /*
    * Block diff cursor from auto scrolling after files are done rendering.
    * This prevents the bug where the screen jumps to the first diff chunk
    * after files are done being rendered after the user has already begun
    * scrolling.
    * This also however results in the fact that the cursor does not auto
    * focus on the first diff chunk on a small screen. This is however, a use
    * case we are willing to not support for now.

    * Using reInit resulted in diffCursor.row being set which
    * prevented the issue of scrolling to top when we expand the second
    * file individually.
    */
    this.diffCursor?.reInitAndUpdateStops();
  }

  /** Cancel the rendering work of every diff in the list */
  private cancelDiffs() {
    if (this.cancelForEachDiff) {
      this.cancelForEachDiff();
    }
  }

  /**
   * In the given NodeList of diff elements, find the diff for the given path.
   */
  private findDiffByPath(path: string, diffElements: GrDiffHost[]) {
    for (let i = 0; i < diffElements.length; i++) {
      if (diffElements[i].path === path) {
        return diffElements[i];
      }
    }
    return undefined;
  }

  /**
   * Compute size bar layout values from the file list.
   * Private but used in tests.
   */
  computeSizeBarLayout() {
    const stats: SizeBarLayout = createDefaultSizeBarLayout();
    this.files
      .slice(0, this.numFilesShown)
      .filter(f => !isMagicPath(f.__path))
      .forEach(f => {
        if (f.lines_inserted) {
          stats.maxInserted = Math.max(stats.maxInserted, f.lines_inserted);
        }
        if (f.lines_deleted) {
          stats.maxDeleted = Math.max(stats.maxDeleted, f.lines_deleted);
        }
      });
    const ratio = stats.maxInserted / (stats.maxInserted + stats.maxDeleted);
    if (!isNaN(ratio)) {
      stats.maxAdditionWidth =
        (SIZE_BAR_MAX_WIDTH - SIZE_BAR_GAP_WIDTH) * ratio;
      stats.maxDeletionWidth =
        SIZE_BAR_MAX_WIDTH - SIZE_BAR_GAP_WIDTH - stats.maxAdditionWidth;
      stats.additionOffset = stats.maxDeletionWidth + SIZE_BAR_GAP_WIDTH;
    }
    return stats;
  }

  /**
   * Get the width of the addition bar for a file.
   * Private but used in tests.
   */
  computeBarAdditionWidth(file?: NormalizedFileInfo, stats?: SizeBarLayout) {
    if (
      !file ||
      !stats ||
      stats.maxInserted === 0 ||
      !file.lines_inserted ||
      !!isMagicPath(file.__path)
    ) {
      return 0;
    }
    const width =
      (stats.maxAdditionWidth * file.lines_inserted) / stats.maxInserted;
    return width === 0 ? 0 : Math.max(SIZE_BAR_MIN_WIDTH, width);
  }

  /**
   * Get the x-offset of the addition bar for a file.
   * Private but used in tests.
   */
  computeBarAdditionX(stats: SizeBarLayout) {
    return stats.additionOffset;
  }

  /**
   * Get the width of the deletion bar for a file.
   * Private but used in tests.
   */
  computeBarDeletionWidth(file?: NormalizedFileInfo, stats?: SizeBarLayout) {
    if (
      !file ||
      !stats ||
      stats.maxDeleted === 0 ||
      !file.lines_deleted ||
      !!isMagicPath(file.__path)
    ) {
      return 0;
    }
    const width =
      (stats.maxDeletionWidth * file.lines_deleted) / stats.maxDeleted;
    return width === 0 ? 0 : Math.max(SIZE_BAR_MIN_WIDTH, width);
  }

  /**
   * Get the x-offset of the deletion bar for a file.
   * Private but used in tests.
   */
  computeBarDeletionX(file?: NormalizedFileInfo, stats?: SizeBarLayout) {
    if (!file || !stats) return;
    return stats.maxDeletionWidth - this.computeBarDeletionWidth(file, stats);
  }

  // Private but used in tests.
  computeSizeBarsClass(path?: string) {
    let hideClass = '';
    if (!this.showSizeBars) {
      hideClass = 'hide';
    } else if (isMagicPath(path)) {
      hideClass = 'invisible';
    }
    return `sizeBars ${hideClass}`;
  }

  /**
   * Shows registered dynamic columns iff the 'header', 'content' and
   * 'summary' endpoints are registered the exact same number of times.
   * Ideally, there should be a better way to enforce the expectation of the
   * dependencies between dynamic endpoints.
   */
  private computeShowDynamicColumns() {
    return !!(
      this.dynamicHeaderEndpoints &&
      this.dynamicContentEndpoints &&
      this.dynamicSummaryEndpoints &&
      this.dynamicHeaderEndpoints.length &&
      this.dynamicHeaderEndpoints.length ===
        this.dynamicContentEndpoints.length &&
      this.dynamicHeaderEndpoints.length === this.dynamicSummaryEndpoints.length
    );
  }

  /**
   * Shows registered dynamic prepended columns iff the 'header', 'content'
   * endpoints are registered the exact same number of times.
   */
  private computeShowPrependedDynamicColumns() {
    return !!(
      this.dynamicPrependedHeaderEndpoints &&
      this.dynamicPrependedContentEndpoints &&
      this.dynamicPrependedHeaderEndpoints.length &&
      this.dynamicPrependedHeaderEndpoints.length ===
        this.dynamicPrependedContentEndpoints.length
    );
  }

  /**
   * Returns true if none of the inline diffs have been expanded.
   * Private but used in tests.
   */
  noDiffsExpanded() {
    return this.filesExpanded === FilesExpandedState.NONE;
  }

  private getOldPath(file: NormalizedFileInfo) {
    // The gr-endpoint-decorator is waiting until all gr-endpoint-param
    // values are updated.
    // The old_path property is undefined for added files, and the
    // gr-endpoint-param value bound to file.old_path is never updates.
    // As a results, the gr-endpoint-decorator doesn't work for added files.
    // As a workaround, this method returns null instead of undefined.
    return file.old_path ?? null;
  }
}
