/**
 * @license
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import '../../../styles/shared-styles';
import '../../diff/gr-diff-cursor/gr-diff-cursor';
import '../../diff/gr-diff-host/gr-diff-host';
import '../../diff/gr-comment-api/gr-comment-api';
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-icons/gr-icons';
import '../../shared/gr-linked-text/gr-linked-text';
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-chip/gr-file-status-chip';
import {flush} from '@polymer/polymer/lib/legacy/polymer.dom';
import {PolymerElement} from '@polymer/polymer/polymer-element';
import {htmlTemplate} from './gr-file-list_html';
import {asyncForeach, debounce, DelayedTask} from '../../../utils/async-util';
import {
  KeyboardShortcutMixin,
  Shortcut,
} from '../../../mixins/keyboard-shortcut-mixin/keyboard-shortcut-mixin';
import {FilesExpandedState} from '../gr-file-list-constants';
import {pluralize} from '../../../utils/string-util';
import {GerritNav} from '../../core/gr-navigation/gr-navigation';
import {getPluginEndpoints} from '../../shared/gr-js-api-interface/gr-plugin-endpoints';
import {getPluginLoader} from '../../shared/gr-js-api-interface/gr-plugin-loader';
import {appContext} from '../../../services/app-context';
import {
  DiffViewMode,
  ScrollMode,
  SpecialFilePath,
} from '../../../constants/constants';
import {
  descendedFromClass,
  getKeyboardEvent,
  isShiftPressed,
  toggleClass,
} from '../../../utils/dom-util';
import {
  addUnmodifiedFiles,
  computeDisplayPath,
  computeTruncatedPath,
  isMagicPath,
  specialFilePathCompare,
} from '../../../utils/path-list-util';
import {customElement, observe, property} from '@polymer/decorators';
import {
  BasePatchSetNum,
  EditPatchSetNum,
  ElementPropertyDeepChange,
  FileInfo,
  FileNameToFileInfoMap,
  NumericChangeId,
  PatchRange,
} 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 '../../diff/gr-diff-cursor/gr-diff-cursor';
import {GrCursorManager} from '../../shared/gr-cursor-manager/gr-cursor-manager';
import {PolymerSpliceChange} from '@polymer/polymer/interfaces';
import {ChangeComments} from '../../diff/gr-comment-api/gr-comment-api';
import {CustomKeyboardEvent} from '../../../types/events';
import {ParsedChangeInfo, PatchSetFile} from '../../../types/types';
import {Timing} from '../../../constants/reporting';
import {RevisionInfo} from '../../shared/revision-info/revision-info';
import {preferences$} from '../../../services/user/user-model';
import {
  changeComments$,
  drafts$,
} from '../../../services/comments/comments-model';
import {Subject} from 'rxjs';
import {takeUntil} from 'rxjs/operators';
import {UIDraft} from '../../../utils/comment-util';

export const DEFAULT_NUM_FILES_SHOWN = 200;

const WARN_SHOW_ALL_THRESHOLD = 1000;
const LOADING_DEBOUNCE_INTERVAL = 100;

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 GrFileList {
  $: {
    diffPreferencesDialog: GrDiffPreferencesDialog;
  };
}

interface ReviewedFileInfo extends FileInfo {
  isReviewed?: boolean;
}
export interface NormalizedFileInfo extends ReviewedFileInfo {
  __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;
  deletionOffset: 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,
    deletionOffset: 0,
  };
}

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

export type FileNameToReviewedFileInfoMap = {[name: string]: ReviewedFileInfo};

/**
 * 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
 */

@customElement('gr-file-list')
export class GrFileList extends KeyboardShortcutMixin(PolymerElement) {
  static get template() {
    return htmlTemplate;
  }

  @property({type: Object})
  patchRange?: PatchRange;

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

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

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

  @property({type: Number, notify: true})
  selectedIndex = -1;

  @property({type: Object})
  keyEventTarget = document.body;

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

  @property({type: String, notify: true, observer: '_updateDiffPreferences'})
  diffViewMode?: DiffViewMode;

  @property({type: Boolean, observer: '_editModeChanged'})
  editMode?: boolean;

  @property({type: String, notify: true})
  filesExpanded = FilesExpandedState.NONE;

  @property({type: Object})
  _filesByPath?: FileNameToFileInfoMap;

  @property({type: Array, observer: '_filesChanged'})
  _files: NormalizedFileInfo[] = [];

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

  @property({type: Array})
  _reviewed?: string[] = [];

  @property({type: Object, notify: true, observer: '_updateDiffPreferences'})
  diffPrefs?: DiffPreferencesInfo;

  @property({type: Boolean})
  _showInlineDiffs?: boolean;

  @property({type: Number, notify: true})
  numFilesShown: number = DEFAULT_NUM_FILES_SHOWN;

  @property({type: Object, computed: '_calculatePatchChange(_files)'})
  _patchChange: PatchChange = createDefaultPatchChange();

  @property({type: Number})
  fileListIncrement: number = DEFAULT_NUM_FILES_SHOWN;

  @property({type: Boolean, computed: '_shouldHideChangeTotals(_patchChange)'})
  _hideChangeTotals = true;

  @property({
    type: Boolean,
    computed: '_shouldHideBinaryChangeTotals(_patchChange)',
  })
  _hideBinaryChangeTotals = true;

  @property({
    type: Array,
    computed: '_computeFilesShown(numFilesShown, _files)',
  })
  _shownFiles: NormalizedFileInfo[] = [];

  @property({type: Number})
  _reportinShownFilesIncrement = 0;

  @property({type: Array})
  _expandedFiles: PatchSetFile[] = [];

  @property({type: Boolean})
  _displayLine?: boolean;

  @property({type: Boolean, observer: '_loadingChanged'})
  _loading?: boolean;

  @property({type: Object, computed: '_computeSizeBarLayout(_shownFiles.*)'})
  _sizeBarLayout: SizeBarLayout = createDefaultSizeBarLayout();

  @property({type: Boolean})
  _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.
  @property({type: Array})
  _cleanlyMergedPaths: string[] = [];

  @property({type: Array})
  _cleanlyMergedOldPaths: string[] = [];

  private _cancelForEachDiff?: () => void;

  loadingTask?: DelayedTask;

  @property({
    type: Boolean,
    computed:
      '_computeShowDynamicColumns(_dynamicHeaderEndpoints, ' +
      '_dynamicContentEndpoints, _dynamicSummaryEndpoints)',
  })
  _showDynamicColumns = false;

  @property({
    type: Boolean,
    computed:
      '_computeShowPrependedDynamicColumns(' +
      '_dynamicPrependedHeaderEndpoints, _dynamicPrependedContentEndpoints)',
  })
  _showPrependedDynamicColumns = false;

  @property({type: Array})
  _dynamicHeaderEndpoints?: string[];

  @property({type: Array})
  _dynamicContentEndpoints?: string[];

  @property({type: Array})
  _dynamicSummaryEndpoints?: string[];

  @property({type: Array})
  _dynamicPrependedHeaderEndpoints?: string[];

  @property({type: Array})
  _dynamicPrependedContentEndpoints?: string[];

  @property({type: Object})
  diffDrafts?: {[path: string]: UIDraft[]} = {};

  private readonly reporting = appContext.reportingService;

  private readonly restApiService = appContext.restApiService;

  disconnected$ = new Subject();

  get keyBindings() {
    return {
      esc: '_handleEscKey',
    };
  }

  keyboardShortcuts() {
    return {
      [Shortcut.LEFT_PANE]: '_handleLeftPane',
      [Shortcut.RIGHT_PANE]: '_handleRightPane',
      [Shortcut.TOGGLE_INLINE_DIFF]: '_handleToggleInlineDiff',
      [Shortcut.TOGGLE_ALL_INLINE_DIFFS]: '_handleToggleAllInlineDiffs',
      [Shortcut.TOGGLE_HIDE_ALL_COMMENT_THREADS]:
        '_handleToggleHideAllCommentThreads',
      [Shortcut.CURSOR_NEXT_FILE]: '_handleCursorNext',
      [Shortcut.CURSOR_PREV_FILE]: '_handleCursorPrev',
      [Shortcut.NEXT_LINE]: '_handleCursorNext',
      [Shortcut.PREV_LINE]: '_handleCursorPrev',
      [Shortcut.NEW_COMMENT]: '_handleNewComment',
      [Shortcut.OPEN_LAST_FILE]: '_handleOpenLastFile',
      [Shortcut.OPEN_FIRST_FILE]: '_handleOpenFirstFile',
      [Shortcut.OPEN_FILE]: '_handleOpenFile',
      [Shortcut.NEXT_CHUNK]: '_handleNextChunk',
      [Shortcut.PREV_CHUNK]: '_handlePrevChunk',
      [Shortcut.TOGGLE_FILE_REVIEWED]: '_handleToggleFileReviewed',
      [Shortcut.TOGGLE_LEFT_PANE]: '_handleToggleLeftPane',

      // Final two are actually handled by gr-comment-thread.
      [Shortcut.EXPAND_ALL_COMMENT_THREADS]: null,
      [Shortcut.COLLAPSE_ALL_COMMENT_THREADS]: null,
    };
  }

  private fileCursor = new GrCursorManager();

  private diffCursor = new GrDiffCursor();

  constructor() {
    super();
    this.fileCursor.scrollMode = ScrollMode.KEEP_VISIBLE;
    this.fileCursor.cursorTargetClass = 'selected';
    this.fileCursor.focusOnMove = true;
    this.addEventListener('keydown', e => this._scopedKeydownHandler(e));
  }

  /** @override */
  connectedCallback() {
    super.connectedCallback();
    drafts$.pipe(takeUntil(this.disconnected$)).subscribe(drafts => {
      this.diffDrafts = drafts;
    });
    changeComments$
      .pipe(takeUntil(this.disconnected$))
      .subscribe(changeComments => {
        this.changeComments = changeComments;
      });
    getPluginLoader()
      .awaitPluginsLoaded()
      .then(() => {
        this._dynamicHeaderEndpoints = getPluginEndpoints().getDynamicEndpoints(
          'change-view-file-list-header'
        );
        this._dynamicContentEndpoints = getPluginEndpoints().getDynamicEndpoints(
          'change-view-file-list-content'
        );
        this._dynamicPrependedHeaderEndpoints = getPluginEndpoints().getDynamicEndpoints(
          'change-view-file-list-header-prepend'
        );
        this._dynamicPrependedContentEndpoints = getPluginEndpoints().getDynamicEndpoints(
          'change-view-file-list-content-prepend'
        );
        this._dynamicSummaryEndpoints = getPluginEndpoints().getDynamicEndpoints(
          'change-view-file-list-summary'
        );

        if (
          this._dynamicHeaderEndpoints.length !==
          this._dynamicContentEndpoints.length
        ) {
          this.reporting.error(new Error('dynamic header/content mismatch'));
        }
        if (
          this._dynamicPrependedHeaderEndpoints.length !==
          this._dynamicPrependedContentEndpoints.length
        ) {
          this.reporting.error(new Error('dynamic header/content mismatch'));
        }
        if (
          this._dynamicHeaderEndpoints.length !==
          this._dynamicSummaryEndpoints.length
        ) {
          this.reporting.error(new Error('dynamic header/content mismatch'));
        }
      });
  }

  /** @override */
  disconnectedCallback() {
    this.disconnected$.next();
    this.diffCursor.dispose();
    this.fileCursor.unsetCursor();
    this._cancelDiffs();
    this.loadingTask?.cancel();
    super.disconnectedCallback();
  }

  /**
   * Iron-a11y-keys-behavior catches keyboard events globally. Some keyboard
   * events must be scoped to a component level (e.g. `enter`) in order to not
   * override native browser functionality.
   *
   * Context: Issue 7277
   */
  _scopedKeydownHandler(e: KeyboardEvent) {
    if (e.keyCode === 13) {
      // TODO(TS): e is not an instance of CustomKeyboardEvent.
      // However, to fix it we should fix keyboard-shortcut-mixin first
      // The keyboard-shortcut-mixin will be updated in a separate change
      this._handleOpenFile((e as unknown) as CustomKeyboardEvent);
    }
  }

  reload() {
    if (!this.changeNum || !this.patchRange?.patchNum) {
      return Promise.resolve();
    }
    const changeNum = this.changeNum;
    const patchRange = this.patchRange;

    this._loading = true;

    this.collapseAllDiffs();
    const promises = [];

    promises.push(
      this.restApiService
        .getChangeOrEditFiles(changeNum, patchRange)
        .then(filesByPath => {
          this._filesByPath = filesByPath;
        })
    );

    promises.push(
      this._getLoggedIn()
        .then(loggedIn => (this._loggedIn = loggedIn))
        .then(loggedIn => {
          if (!loggedIn) {
            return;
          }

          return this._getReviewedFiles(changeNum, patchRange).then(
            reviewed => {
              this._reviewed = reviewed;
            }
          );
        })
    );

    promises.push(
      this._getDiffPreferences().then(prefs => {
        this.diffPrefs = prefs;
      })
    );

    preferences$.pipe(takeUntil(this.disconnected$)).subscribe(prefs => {
      this._showSizeBars = !!prefs?.size_bar_in_change_table;
    });

    return Promise.all(promises).then(() => {
      this._loading = false;
      this._detectChromiteButler();
      this.reporting.fileListDisplayed();
    });
  }

  @observe('_filesByPath')
  async _updateCleanlyMergedPaths(filesByPath?: FileNameToFileInfoMap) {
    // 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.patchRange?.patchNum &&
      new RevisionInfo(this.change).isMergeCommit(this.patchRange.patchNum) &&
      this.patchRange.basePatchNum === 'PARENT' &&
      this.patchRange.patchNum !== EditPatchSetNum
    ) {
      const allFilesByPath = await this.restApiService.getChangeOrEditFiles(
        this.changeNum,
        {
          basePatchNum: -1 as BasePatchSetNum, // -1 is first (target) parent
          patchNum: this.patchRange.patchNum,
        }
      );
      if (!allFilesByPath || !filesByPath) return;
      const conflictingPaths = Object.keys(filesByPath);
      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 = [];
    }
  }

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

  get diffs(): GrDiffHost[] {
    const diffs = this.root!.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'
    );
  }

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

  _calculatePatchChange(files: NormalizedFileInfo[]): PatchChange {
    const magicFilesExcluded = files.filter(
      files => !isMagicPath(files.__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 > 0 ? obj.size_delta : 0;
      const size_delta_deleted =
        obj.binary && 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());
  }

  _getDiffPreferences() {
    return this.restApiService.getDiffPreferences();
  }

  _getPreferences() {
    return this.restApiService.getPreferences();
  }

  private _toggleFileExpanded(file: PatchSetFile) {
    // Is the path in the list of expanded diffs? IF so remove it, otherwise
    // add it to the list.
    const pathIndex = this._expandedFiles.findIndex(f => f.path === file.path);
    if (pathIndex === -1) {
      this.push('_expandedFiles', file);
    } else {
      this.splice('_expandedFiles', pathIndex, 1);
    }
  }

  _toggleFileExpandedByIndex(index: number) {
    this._toggleFileExpanded(this._computePatchSetFile(this._files[index]));
  }

  _updateDiffPreferences() {
    if (!this.diffs.length) {
      return;
    }
    // Re-render all expanded diffs sequentially.
    this.reporting.time(Timing.FILE_EXPAND_ALL);
    this._renderInOrder(
      this._expandedFiles,
      this.diffs,
      this._expandedFiles.length
    );
  }

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

  expandAllDiffs() {
    this._showInlineDiffs = true;

    // 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._shownFiles.length; i++) {
      path = this._shownFiles[i].__path;
      if (!this._expandedFiles.some(f => f.path === path)) {
        newFiles.push(this._computePatchSetFile(this._shownFiles[i]));
      }
    }

    this.splice('_expandedFiles', 0, 0, ...newFiles);
  }

  collapseAllDiffs() {
    this._showInlineDiffs = false;
    this._expandedFiles = [];
    this.filesExpanded = this._computeExpandedFiles(
      this._expandedFiles.length,
      this._files.length
    );
    this.diffCursor.handleDiffUpdate();
  }

  /**
   * Computes a string with the number of comments and unresolved comments.
   */
  _computeCommentsString(
    changeComments?: ChangeComments,
    patchRange?: PatchRange,
    file?: NormalizedFileInfo
  ) {
    if (
      changeComments === undefined ||
      patchRange === undefined ||
      file?.__path === undefined
    ) {
      return '';
    }
    return changeComments.computeCommentsString(patchRange, file.__path, file);
  }

  /**
   * Computes a string with the number of drafts.
   */
  _computeDraftsString(
    changeComments?: ChangeComments,
    patchRange?: PatchRange,
    file?: NormalizedFileInfo
  ) {
    if (changeComments === undefined) return '';
    const draftCount = changeComments.computeDraftCountForFile(
      patchRange,
      file
    );
    if (draftCount === 0) return '';
    return pluralize(Number(draftCount), 'draft');
  }

  /**
   * Computes a shortened string with the number of drafts.
   */
  _computeDraftsStringMobile(
    changeComments?: ChangeComments,
    patchRange?: PatchRange,
    file?: NormalizedFileInfo
  ) {
    if (changeComments === undefined) return '';
    const draftCount = changeComments.computeDraftCountForFile(
      patchRange,
      file
    );
    return draftCount === 0 ? '' : `${draftCount}d`;
  }

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

  private _reviewFile(path: string, reviewed?: boolean) {
    if (this.editMode) {
      return Promise.resolve();
    }
    const index = this._files.findIndex(file => file.__path === path);
    reviewed = reviewed || !this._files[index].isReviewed;

    this.set(['_files', index, 'isReviewed'], reviewed);
    if (index < this._shownFiles.length) {
      this.notifyPath(`_shownFiles.${index}.isReviewed`);
    }

    return this._saveReviewedState(path, reviewed);
  }

  _saveReviewedState(path: string, reviewed: boolean) {
    if (!this.changeNum || !this.patchRange) {
      throw new Error('changeNum and patchRange must be set');
    }

    return this.restApiService.saveFileReviewed(
      this.changeNum,
      this.patchRange.patchNum,
      path,
      reviewed
    );
  }

  _getLoggedIn() {
    return this.restApiService.getLoggedIn();
  }

  _getReviewedFiles(changeNum: NumericChangeId, patchRange: PatchRange) {
    if (this.editMode) {
      return Promise.resolve([]);
    }
    return this.restApiService.getReviewedFiles(changeNum, patchRange.patchNum);
  }

  _normalizeChangeFilesResponse(
    response: FileNameToReviewedFileInfoMap
  ): NormalizedFileInfo[] {
    const paths = Object.keys(response).sort(specialFilePathCompare);
    const files: NormalizedFileInfo[] = [];
    for (let i = 0; i < paths.length; i++) {
      // TODO(TS): make copy instead of as NormalizedFileInfo
      const info = response[paths[i]] as NormalizedFileInfo;
      info.__path = paths[i];
      info.lines_inserted = info.lines_inserted || 0;
      info.lines_deleted = info.lines_deleted || 0;
      info.size_delta = info.size_delta || 0;
      files.push(info);
    }
    return files;
  }

  /**
   * 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
   */
  _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;
  }

  _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);
    }
  }

  _reviewedClick(e: MouseEvent | KeyboardEvent) {
    this._fileActionClick(e, file => this._reviewFile(file.path));
  }

  _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.
   */
  _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);
  }

  _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.
   */
  _computePatchSetFile(file: NormalizedFileInfo): PatchSetFile {
    const fileData: PatchSetFile = {
      path: file.__path,
    };
    if (file.old_path) {
      fileData.basePath = file.old_path;
    }
    return fileData;
  }

  _handleLeftPane(e: CustomKeyboardEvent) {
    if (this.shouldSuppressKeyboardShortcut(e) || this._noDiffsExpanded()) {
      return;
    }

    e.preventDefault();
    this.diffCursor.moveLeft();
  }

  _handleRightPane(e: CustomKeyboardEvent) {
    if (this.shouldSuppressKeyboardShortcut(e) || this._noDiffsExpanded()) {
      return;
    }

    e.preventDefault();
    this.diffCursor.moveRight();
  }

  _handleToggleInlineDiff(e: CustomKeyboardEvent) {
    if (
      this.shouldSuppressKeyboardShortcut(e) ||
      this.modifierPressed(e) ||
      this.fileCursor.index === -1
    ) {
      return;
    }

    e.preventDefault();
    this._toggleFileExpandedByIndex(this.fileCursor.index);
  }

  _handleToggleAllInlineDiffs(e: CustomKeyboardEvent) {
    if (this.shouldSuppressKeyboardShortcut(e)) {
      return;
    }

    e.preventDefault();
    this._toggleInlineDiffs();
  }

  _handleToggleHideAllCommentThreads(e: CustomKeyboardEvent) {
    if (this.shouldSuppressKeyboardShortcut(e) || this.modifierPressed(e)) {
      return;
    }

    e.preventDefault();
    toggleClass(this, 'hideComments');
  }

  _handleCursorNext(e: CustomKeyboardEvent) {
    if (this.shouldSuppressKeyboardShortcut(e) || this.modifierPressed(e)) {
      return;
    }

    if (this._showInlineDiffs) {
      e.preventDefault();
      this.diffCursor.moveDown();
      this._displayLine = true;
    } else {
      // Down key
      if (getKeyboardEvent(e).keyCode === 40) {
        return;
      }
      e.preventDefault();
      this.fileCursor.next({circular: true});
      this.selectedIndex = this.fileCursor.index;
    }
  }

  _handleCursorPrev(e: CustomKeyboardEvent) {
    if (this.shouldSuppressKeyboardShortcut(e) || this.modifierPressed(e)) {
      return;
    }

    if (this._showInlineDiffs) {
      e.preventDefault();
      this.diffCursor.moveUp();
      this._displayLine = true;
    } else {
      // Up key
      if (getKeyboardEvent(e).keyCode === 38) {
        return;
      }
      e.preventDefault();
      this.fileCursor.previous({circular: true});
      this.selectedIndex = this.fileCursor.index;
    }
  }

  _handleNewComment(e: CustomKeyboardEvent) {
    if (this.shouldSuppressKeyboardShortcut(e) || this.modifierPressed(e)) {
      return;
    }
    e.preventDefault();
    this.classList.remove('hideComments');
    this.diffCursor.createCommentInPlace();
  }

  _handleOpenLastFile(e: CustomKeyboardEvent) {
    // Check for meta key to avoid overriding native chrome shortcut.
    if (this.shouldSuppressKeyboardShortcut(e) || getKeyboardEvent(e).metaKey) {
      return;
    }

    e.preventDefault();
    this._openSelectedFile(this._files.length - 1);
  }

  _handleOpenFirstFile(e: CustomKeyboardEvent) {
    // Check for meta key to avoid overriding native chrome shortcut.
    if (this.shouldSuppressKeyboardShortcut(e) || getKeyboardEvent(e).metaKey) {
      return;
    }

    e.preventDefault();
    this._openSelectedFile(0);
  }

  _handleOpenFile(e: CustomKeyboardEvent) {
    if (this.shouldSuppressKeyboardShortcut(e) || this.modifierPressed(e)) {
      return;
    }
    e.preventDefault();

    if (this._showInlineDiffs) {
      this._openCursorFile();
      return;
    }

    this._openSelectedFile();
  }

  _handleNextChunk(e: CustomKeyboardEvent) {
    if (
      this.shouldSuppressKeyboardShortcut(e) ||
      (this.modifierPressed(e) && !isShiftPressed(e)) ||
      this._noDiffsExpanded()
    ) {
      return;
    }

    e.preventDefault();
    if (isShiftPressed(e)) {
      this.diffCursor.moveToNextCommentThread();
    } else {
      this.diffCursor.moveToNextChunk();
    }
  }

  _handlePrevChunk(e: CustomKeyboardEvent) {
    if (
      this.shouldSuppressKeyboardShortcut(e) ||
      (this.modifierPressed(e) && !isShiftPressed(e)) ||
      this._noDiffsExpanded()
    ) {
      return;
    }

    e.preventDefault();
    if (isShiftPressed(e)) {
      this.diffCursor.moveToPreviousCommentThread();
    } else {
      this.diffCursor.moveToPreviousChunk();
    }
  }

  _handleToggleFileReviewed(e: CustomKeyboardEvent) {
    if (this.shouldSuppressKeyboardShortcut(e) || this.modifierPressed(e)) {
      return;
    }

    e.preventDefault();
    if (!this._files[this.fileCursor.index]) {
      return;
    }
    this._reviewFile(this._files[this.fileCursor.index].__path);
  }

  _handleToggleLeftPane(e: CustomKeyboardEvent) {
    if (this.shouldSuppressKeyboardShortcut(e)) {
      return;
    }

    e.preventDefault();
    this._forEachDiff(diff => {
      diff.toggleLeftDiff();
    });
  }

  _toggleInlineDiffs() {
    if (this._showInlineDiffs) {
      this.collapseAllDiffs();
    } else {
      this.expandAllDiffs();
    }
  }

  _openCursorFile() {
    const diff = this.diffCursor.getTargetDiffElement();
    if (!this.change || !diff || !this.patchRange || !diff.path) {
      throw new Error('change, diff and patchRange must be all set and valid');
    }
    GerritNav.navigateToDiff(
      this.change,
      diff.path,
      this.patchRange.patchNum,
      this.patchRange.basePatchNum
    );
  }

  _openSelectedFile(index?: number) {
    if (index !== undefined) {
      this.fileCursor.setCursorAtIndex(index);
    }
    if (!this._files[this.fileCursor.index]) {
      return;
    }
    if (!this.change || !this.patchRange) {
      throw new Error('change and patchRange must be set');
    }
    GerritNav.navigateToDiff(
      this.change,
      this._files[this.fileCursor.index].__path,
      this.patchRange.patchNum,
      this.patchRange.basePatchNum
    );
  }

  _shouldHideChangeTotals(_patchChange: PatchChange): boolean {
    return _patchChange.inserted === 0 && _patchChange.deleted === 0;
  }

  _shouldHideBinaryChangeTotals(_patchChange: PatchChange) {
    return (
      _patchChange.size_delta_inserted === 0 &&
      _patchChange.size_delta_deleted === 0
    );
  }

  _computeDiffURL(
    change?: ParsedChangeInfo,
    patchRange?: PatchRange,
    path?: string,
    editMode?: boolean
  ) {
    // Polymer 2: check for undefined
    if (
      change === undefined ||
      patchRange === undefined ||
      path === undefined ||
      editMode === undefined
    ) {
      return;
    }
    if (editMode && path !== SpecialFilePath.MERGE_LIST) {
      return GerritNav.getEditUrlForDiff(change, path, patchRange.patchNum);
    }
    return GerritNav.getUrlForDiff(
      change,
      path,
      patchRange.patchNum,
      patchRange.basePatchNum
    );
  }

  _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]}`;
  }

  _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}%)`;
  }

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

  _computeClass(baseClass?: string, path?: string) {
    const classes = [];
    if (baseClass) {
      classes.push(baseClass);
    }
    if (
      path === SpecialFilePath.COMMIT_MESSAGE ||
      path === SpecialFilePath.MERGE_LIST
    ) {
      classes.push('invisible');
    }
    return classes.join(' ');
  }

  _computePathClass(
    path: string | undefined,
    expandedFilesRecord: ElementPropertyDeepChange<GrFileList, '_expandedFiles'>
  ) {
    return this._isFileExpanded(path, expandedFilesRecord) ? 'expanded' : '';
  }

  _computeShowHideIcon(
    path: string | undefined,
    expandedFilesRecord: ElementPropertyDeepChange<GrFileList, '_expandedFiles'>
  ) {
    return this._isFileExpanded(path, expandedFilesRecord)
      ? 'gr-icons:expand-less'
      : 'gr-icons:expand-more';
  }

  _computeShowNumCleanlyMerged(cleanlyMergedPaths: string[]): boolean {
    return cleanlyMergedPaths.length > 0;
  }

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

  _handleShowParent1(): void {
    if (!this.change || !this.patchRange) return;
    GerritNav.navigateToChange(
      this.change,
      this.patchRange.patchNum,
      -1 as BasePatchSetNum // Parent 1
    );
  }

  @observe(
    '_filesByPath',
    'changeComments',
    'patchRange',
    '_reviewed',
    '_loading'
  )
  _computeFiles(
    filesByPath?: FileNameToFileInfoMap,
    changeComments?: ChangeComments,
    patchRange?: PatchRange,
    reviewed?: string[],
    loading?: boolean
  ) {
    // Polymer 2: check for undefined
    if (
      filesByPath === undefined ||
      changeComments === undefined ||
      patchRange === undefined ||
      reviewed === undefined ||
      loading === undefined
    ) {
      return;
    }
    // Await all promises resolving from reload. @See Issue 9057
    if (loading || !changeComments) {
      return;
    }
    const commentedPaths = changeComments.getPaths(patchRange);
    const files: FileNameToReviewedFileInfoMap = {...filesByPath};
    addUnmodifiedFiles(files, commentedPaths);
    const reviewedSet = new Set(reviewed || []);
    for (const [filePath, reviewedFileInfo] of Object.entries(files)) {
      reviewedFileInfo.isReviewed = reviewedSet.has(filePath);
    }
    this._files = this._normalizeChangeFilesResponse(files);
  }

  _computeFilesShown(
    numFilesShown: number,
    files: NormalizedFileInfo[]
  ): NormalizedFileInfo[] | undefined {
    // Polymer 2: check for undefined
    if (numFilesShown === undefined || files === undefined) return undefined;

    const previousNumFilesShown = this._shownFiles
      ? this._shownFiles.length
      : 0;

    const filesShown = files.slice(0, numFilesShown);
    this.dispatchEvent(
      new CustomEvent('files-shown-changed', {
        detail: {length: filesShown.length},
        composed: true,
        bubbles: true,
      })
    );

    // Start the timer for the rendering work hwere because this is where the
    // _shownFiles property is being set, and _shownFiles is used in the
    // dom-repeat binding.
    this.reporting.time(Timing.FILE_RENDER);

    // How many more files are being shown (if it's an increase).
    this._reportinShownFilesIncrement = Math.max(
      0,
      filesShown.length - previousNumFilesShown
    );

    return filesShown;
  }

  _updateDiffCursor() {
    // Overwrite the cursor's list of diffs:
    this.diffCursor.replaceDiffs(this.diffs);
  }

  _filesChanged() {
    if (this._files && this._files.length > 0) {
      flush();
      this.fileCursor.stops = Array.from(
        this.root!.querySelectorAll(`.${FILE_ROW_CLASS}`)
      );
      this.fileCursor.setCursorAtIndex(this.selectedIndex, true);
    }
  }

  _incrementNumFilesShown() {
    this.numFilesShown += this.fileListIncrement;
  }

  _computeFileListControlClass(
    numFilesShown?: number,
    files?: NormalizedFileInfo[]
  ) {
    if (numFilesShown === undefined || files === undefined) return 'invisible';
    return numFilesShown >= files.length ? 'invisible' : '';
  }

  _computeIncrementText(numFilesShown?: number, files?: NormalizedFileInfo[]) {
    if (numFilesShown === undefined || files === undefined) return '';
    const text = Math.min(this.fileListIncrement, files.length - numFilesShown);
    return `Show ${text} more`;
  }

  _computeShowAllText(files: NormalizedFileInfo[]) {
    if (!files) {
      return '';
    }
    return `Show all ${files.length} files`;
  }

  _computeWarnShowAll(files: NormalizedFileInfo[]) {
    return files.length > WARN_SHOW_ALL_THRESHOLD;
  }

  _computeShowAllWarning(files: NormalizedFileInfo[]) {
    if (!this._computeWarnShowAll(files)) {
      return '';
    }
    return `Warning: showing all ${files.length} files may take several seconds.`;
  }

  _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
   */
  _booleanToString(val?: unknown) {
    return val ? 'true' : 'false';
  }

  _isFileExpanded(
    path: string | undefined,
    expandedFilesRecord: ElementPropertyDeepChange<GrFileList, '_expandedFiles'>
  ) {
    return expandedFilesRecord.base.some(f => f.path === path);
  }

  _isFileExpandedStr(
    path: string | undefined,
    expandedFilesRecord: ElementPropertyDeepChange<GrFileList, '_expandedFiles'>
  ) {
    return this._booleanToString(
      this._isFileExpanded(path, expandedFilesRecord)
    );
  }

  private _computeExpandedFiles(
    expandedCount: number,
    totalCount: number
  ): FilesExpandedState {
    if (expandedCount === 0) {
      return FilesExpandedState.NONE;
    } else if (expandedCount === totalCount) {
      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 record The splice record in the expanded paths list.
   */
  @observe('_expandedFiles.splices')
  _expandedFilesChanged(record?: PolymerSpliceChange<PatchSetFile[]>) {
    // Clear content for any diffs that are not open so if they get re-opened
    // the stale content does not flash before it is cleared and reloaded.
    const collapsedDiffs = this.diffs.filter(
      diff => this._expandedFiles.findIndex(f => f.path === diff.path) === -1
    );
    this._clearCollapsedDiffs(collapsedDiffs);

    if (!record) {
      return;
    } // Happens after "Collapse all" clicked.

    this.filesExpanded = this._computeExpandedFiles(
      this._expandedFiles.length,
      this._files.length
    );

    // Find the paths introduced by the new index splices:
    const newFiles = record.indexSplices
      .map(splice =>
        splice.object.slice(splice.index, splice.index + splice.addedCount)
      )
      .reduce((acc, paths) => acc.concat(paths), []);

    // Required so that the newly created diff view is included in this.diffs.
    flush();

    this.reporting.time(Timing.FILE_EXPAND_ALL);

    if (newFiles.length) {
      this._renderInOrder(newFiles, this.diffs, newFiles.length);
    }

    this._updateDiffCursor();
    this.diffCursor.reInitAndUpdateStops();
  }

  private _clearCollapsedDiffs(collapsedDiffs: GrDiffHost[]) {
    for (const diff of collapsedDiffs) {
      diff.cancel();
      diff.clearDiffContent();
    }
  }

  /**
   * 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.
   *
   * @param initialCount The total number of paths in the pass. This
   * is used to generate log messages.
   */
  private _renderInOrder(
    files: PatchSetFile[],
    diffElements: GrDiffHost[],
    initialCount: number
  ) {
    let iter = 0;

    for (const file of files) {
      const path = file.path;
      const diffElem = this._findDiffByPath(path, diffElements);
      if (diffElem) {
        diffElem.prefetchDiff();
      }
    }

    asyncForeach(files, (file, cancel) => {
      const path = file.path;
      this._cancelForEachDiff = cancel;

      iter++;
      console.info('Expanding diff', iter, 'of', initialCount, ':', path);
      const diffElem = this._findDiffByPath(path, diffElements);
      if (!diffElem) {
        this.reporting.error(
          new Error(`Did not find <gr-diff-host> element for ${path}`)
        );
        return Promise.resolve();
      }
      if (!this.diffPrefs) {
        throw new Error('diffPrefs must be set');
      }

      const promises: Array<Promise<unknown>> = [diffElem.reload()];
      if (this._loggedIn && !this.diffPrefs.manual_review) {
        promises.push(this._reviewFile(path, true));
      }
      return Promise.all(promises);
    }).then(() => {
      this._cancelForEachDiff = undefined;
      console.info('Finished expanding', initialCount, 'diff(s)');
      this.reporting.timeEndWithAverage(
        Timing.FILE_EXPAND_ALL,
        Timing.FILE_EXPAND_ALL_AVG,
        initialCount
      );
      /* 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 handleDiffUpdate 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 */
  _cancelDiffs() {
    if (this._cancelForEachDiff) {
      this._cancelForEachDiff();
    }
    this._forEachDiff(d => d.cancel());
  }

  /**
   * 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;
  }

  _handleEscKey(e: CustomKeyboardEvent) {
    if (this.shouldSuppressKeyboardShortcut(e) || this.modifierPressed(e)) {
      return;
    }
    e.preventDefault();
    this._displayLine = false;
  }

  /**
   * Update the loading class for the file list rows. The update is inside a
   * debouncer so that the file list doesn't flash gray when the API requests
   * are reasonably fast.
   */
  _loadingChanged(loading?: boolean) {
    this.loadingTask = debounce(
      this.loadingTask,
      () => {
        // Only show set the loading if there have been files loaded to show. In
        // this way, the gray loading style is not shown on initial loads.
        this.classList.toggle('loading', loading && !!this._files.length);
      },
      LOADING_DEBOUNCE_INTERVAL
    );
  }

  _editModeChanged(editMode?: boolean) {
    this.classList.toggle('editMode', editMode);
  }

  _computeReviewedClass(isReviewed?: boolean) {
    return isReviewed ? 'isReviewed' : '';
  }

  _computeReviewedText(isReviewed?: boolean) {
    return isReviewed ? 'MARK UNREVIEWED' : 'MARK REVIEWED';
  }

  /**
   * Given a file path, return whether that path should have visible size bars
   * and be included in the size bars calculation.
   */
  _showBarsForPath(path?: string) {
    return (
      path !== SpecialFilePath.COMMIT_MESSAGE &&
      path !== SpecialFilePath.MERGE_LIST
    );
  }

  /**
   * Compute size bar layout values from the file list.
   */
  _computeSizeBarLayout(
    shownFilesRecord?: ElementPropertyDeepChange<GrFileList, '_shownFiles'>
  ) {
    const stats: SizeBarLayout = createDefaultSizeBarLayout();
    if (!shownFilesRecord || !shownFilesRecord.base) {
      return stats;
    }
    shownFilesRecord.base
      .filter(f => this._showBarsForPath(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.deletionOffset = stats.maxAdditionWidth + SIZE_BAR_GAP_WIDTH;
    }
    return stats;
  }

  /**
   * Get the width of the addition bar for a file.
   */
  _computeBarAdditionWidth(file?: NormalizedFileInfo, stats?: SizeBarLayout) {
    if (
      !file ||
      !stats ||
      stats.maxInserted === 0 ||
      !file.lines_inserted ||
      !this._showBarsForPath(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.
   */
  _computeBarAdditionX(file?: NormalizedFileInfo, stats?: SizeBarLayout) {
    if (!file || !stats) return;
    return stats.maxAdditionWidth - this._computeBarAdditionWidth(file, stats);
  }

  /**
   * Get the width of the deletion bar for a file.
   */
  _computeBarDeletionWidth(file?: NormalizedFileInfo, stats?: SizeBarLayout) {
    if (
      !file ||
      !stats ||
      stats.maxDeleted === 0 ||
      !file.lines_deleted ||
      !this._showBarsForPath(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.
   */
  _computeBarDeletionX(stats: SizeBarLayout) {
    return stats.deletionOffset;
  }

  _computeSizeBarsClass(showSizeBars?: boolean, path?: string) {
    let hideClass = '';
    if (!showSizeBars) {
      hideClass = 'hide';
    } else if (!this._showBarsForPath(path)) {
      hideClass = 'invisible';
    }
    return `sizeBars desktop ${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.
   */
  _computeShowDynamicColumns(
    headerEndpoints?: string,
    contentEndpoints?: string,
    summaryEndpoints?: string
  ) {
    return (
      headerEndpoints &&
      contentEndpoints &&
      summaryEndpoints &&
      headerEndpoints.length &&
      headerEndpoints.length === contentEndpoints.length &&
      headerEndpoints.length === summaryEndpoints.length
    );
  }

  /**
   * Shows registered dynamic prepended columns iff the 'header', 'content'
   * endpoints are registered the exact same number of times.
   */
  _computeShowPrependedDynamicColumns(
    headerEndpoints?: string,
    contentEndpoints?: string
  ) {
    return (
      headerEndpoints &&
      contentEndpoints &&
      headerEndpoints.length &&
      headerEndpoints.length === contentEndpoints.length
    );
  }

  /**
   * Returns true if none of the inline diffs have been expanded.
   */
  _noDiffsExpanded() {
    return this.filesExpanded === FilesExpandedState.NONE;
  }

  /**
   * Method to call via binding when each file list row is rendered. This
   * allows approximate detection of when the dom-repeat has completed
   * rendering.
   *
   * @param index The index of the row being rendered.
   */
  _reportRenderedRow(index: number) {
    if (index === this._shownFiles.length - 1) {
      setTimeout(() => {
        this.reporting.timeEndWithAverage(
          Timing.FILE_RENDER,
          Timing.FILE_RENDER_AVG,
          this._reportinShownFilesIncrement
        );
      }, 1);
    }
    return '';
  }

  _reviewedTitle(reviewed?: boolean) {
    if (reviewed) {
      return 'Mark as not reviewed (shortcut: r)';
    }

    return 'Mark as reviewed (shortcut: r)';
  }

  _handleReloadingDiffPreference() {
    this._getDiffPreferences().then(prefs => {
      this.diffPrefs = prefs;
    });
  }

  /**
   * Wrapper for using in the element template and computed properties
   */
  _computeDisplayPath(path: string) {
    return computeDisplayPath(path);
  }

  /**
   * Wrapper for using in the element template and computed properties
   */
  _computeTruncatedPath(path: string) {
    return computeTruncatedPath(path);
  }

  _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;
  }
}

declare global {
  interface HTMLElementTagNameMap {
    'gr-file-list': GrFileList;
  }
}
