/**
 * @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-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,
  ElementPropertyDeepChange,
  FileInfo,
  FileNameToFileInfoMap,
  NumericChangeId,
  PatchRange,
  PreferencesInfo,
  UrlEncodedCommentId,
} 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';

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

  /**
   * Fired when a draft refresh should get triggered
   *
   * @event reload-drafts
   */

  @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: Object})
  _userPrefs?: PreferencesInfo;

  @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, computed: '_computeShowSizeBars(_userPrefs)'})
  _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[];

  private readonly reporting = appContext.reportingService;

  private readonly restApiService = appContext.restApiService;

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

    promises.push(
      this._getPreferences().then(prefs => {
        this._userPrefs = prefs;
      })
    );

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

  @observe('_filesByPath')
  async _updateCleanlyMergedPaths(
    // changeNum?: NumericChangeId,
    // change?: ParsedChangeInfo,
    // patchRange?: PatchRange,
    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'
    ) {
      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
  ) {
    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
  ) {
    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();
      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();
      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();
      }
    }

    return new Promise(resolve => {
      this.dispatchEvent(
        new CustomEvent('reload-drafts', {
          detail: {resolve},
          composed: true,
          bubbles: true,
        })
      );
    }).then(() =>
      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.changeComments || !this.patchRange || !this.diffPrefs) {
          throw new Error(
            'changeComments, patchRange and diffPrefs must be set'
          );
        }

        diffElem.threads = this.changeComments.getThreadsBySideForFile(
          file,
          this.patchRange
        );
        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;
  }

  /**
   * Reset the comments of a modified thread
   */
  reloadCommentsForThreadWithRootId(rootId: UrlEncodedCommentId, path: string) {
    // Don't bother continuing if we already know that the path that contains
    // the updated comment thread is not expanded.
    if (!this._expandedFiles.some(f => f.path === path)) {
      return;
    }
    const diff = this.diffs.find(d => d.path === path);

    if (!diff) {
      throw new Error("Can't find diff by path");
    }

    const threadEl = diff.getThreadEls().find(t => t.rootId === rootId);
    if (!threadEl) {
      return;
    }

    if (!this.changeComments) {
      throw new Error('changeComments must be set');
    }

    const newComments = this.changeComments.getCommentsForThread(rootId);

    // If newComments is null, it means that a single draft was
    // removed from a thread in the thread view, and the thread should
    // no longer exist. Remove the existing thread element in the diff
    // view.
    if (!newComments) {
      threadEl.fireRemoveSelf();
      return;
    }

    threadEl.comments = newComments.map(c => {
      return {...c};
    });
    flush();
  }

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

  _computeShowSizeBars(userPrefs?: PreferencesInfo) {
    return !!userPrefs?.size_bar_in_change_table;
  }

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