/**
 * @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.js';
import '../../diff/gr-diff-cursor/gr-diff-cursor.js';
import '../../diff/gr-diff-host/gr-diff-host.js';
import '../../diff/gr-diff-preferences-dialog/gr-diff-preferences-dialog.js';
import '../../edit/gr-edit-file-controls/gr-edit-file-controls.js';
import '../../shared/gr-button/gr-button.js';
import '../../shared/gr-cursor-manager/gr-cursor-manager.js';
import '../../shared/gr-icons/gr-icons.js';
import '../../shared/gr-linked-text/gr-linked-text.js';
import '../../shared/gr-rest-api-interface/gr-rest-api-interface.js';
import '../../shared/gr-select/gr-select.js';
import '../../shared/gr-tooltip-content/gr-tooltip-content.js';
import '../../shared/gr-copy-clipboard/gr-copy-clipboard.js';
import {flush} from '@polymer/polymer/lib/legacy/polymer.dom.js';
import {GestureEventListeners} from '@polymer/polymer/lib/mixins/gesture-event-listeners.js';
import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin.js';
import {PolymerElement} from '@polymer/polymer/polymer-element.js';
import {htmlTemplate} from './gr-file-list_html.js';
import {asyncForeach} from '../../../utils/async-util.js';
import {KeyboardShortcutMixin, Shortcut} from '../../../mixins/keyboard-shortcut-mixin/keyboard-shortcut-mixin.js';
import {GrFileListConstants} from '../gr-file-list-constants.js';
import {GrCountStringFormatter} from '../../shared/gr-count-string-formatter/gr-count-string-formatter.js';
import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';
import {getPluginEndpoints} from '../../shared/gr-js-api-interface/gr-plugin-endpoints.js';
import {getPluginLoader} from '../../shared/gr-js-api-interface/gr-plugin-loader.js';
import {appContext} from '../../../services/app-context.js';
import {SpecialFilePath} from '../../../constants/constants.js';
import {descendedFromClass} from '../../../utils/dom-util.js';
import {getRevisionByPatchNum} from '../../../utils/patch-set-util.js';
import {
  addUnmodifiedFiles,
  computeDisplayPath,
  computeTruncatedPath,
  isMagicPath,
  specialFilePathCompare,
} from '../../../utils/path-list-util.js';

// Maximum length for patch set descriptions.
const PATCH_DESC_MAX_LENGTH = 500;
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 RENDER_TIMING_LABEL = 'FileListRenderTime';
const RENDER_AVG_TIMING_LABEL = 'FileListRenderTimePerFile';
const EXPAND_ALL_TIMING_LABEL = 'ExpandAllDiffs';
const EXPAND_ALL_AVG_TIMING_LABEL = 'ExpandAllPerDiff';

const FileStatus = {
  A: 'Added',
  C: 'Copied',
  D: 'Deleted',
  M: 'Modified',
  R: 'Renamed',
  W: 'Rewritten',
  U: 'Unchanged',
};

const FILE_ROW_CLASS = 'file-row';

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

/**
 * @extends PolymerElement
 */
class GrFileList extends KeyboardShortcutMixin(
    GestureEventListeners(
        LegacyElementMixin(PolymerElement))) {
  static get template() { return htmlTemplate; }

  static get is() { return 'gr-file-list'; }
  /**
   * Fired when a draft refresh should get triggered
   *
   * @event reload-drafts
   */

  static get properties() {
    return {
    /** @type {?} */
      patchRange: Object,
      patchNum: String,
      changeNum: String,
      /** @type {?} */
      changeComments: Object,
      drafts: Object,
      revisions: Array,
      projectConfig: Object,
      selectedIndex: {
        type: Number,
        notify: true,
      },
      keyEventTarget: {
        type: Object,
        value() { return document.body; },
      },
      /** @type {?} */
      change: Object,
      diffViewMode: {
        type: String,
        notify: true,
        observer: '_updateDiffPreferences',
      },
      editMode: {
        type: Boolean,
        observer: '_editModeChanged',
      },
      filesExpanded: {
        type: String,
        value: GrFileListConstants.FilesExpandedState.NONE,
        notify: true,
      },
      _filesByPath: Object,

      /** @type {!Array<FileInfo>} */
      _files: {
        type: Array,
        observer: '_filesChanged',
        value() { return []; },
      },
      _loggedIn: {
        type: Boolean,
        value: false,
      },
      _reviewed: {
        type: Array,
        value() { return []; },
      },
      diffPrefs: {
        type: Object,
        notify: true,
        observer: '_updateDiffPreferences',
      },
      /** @type {?} */
      _userPrefs: Object,
      _showInlineDiffs: Boolean,
      numFilesShown: {
        type: Number,
        notify: true,
      },
      /** @type {?} */
      _patchChange: {
        type: Object,
        computed: '_calculatePatchChange(_files)',
      },
      fileListIncrement: Number,
      _hideChangeTotals: {
        type: Boolean,
        computed: '_shouldHideChangeTotals(_patchChange)',
      },
      _hideBinaryChangeTotals: {
        type: Boolean,
        computed: '_shouldHideBinaryChangeTotals(_patchChange)',
      },

      _shownFiles: {
        type: Array,
        computed: '_computeFilesShown(numFilesShown, _files)',
      },

      /**
       * The amount of files added to the shown files list the last time it was
       * updated. This is used for reporting the average render time.
       */
      _reportinShownFilesIncrement: Number,

      /** @type {!Array<Gerrit.FileRange>} */
      _expandedFiles: {
        type: Array,
        value() { return []; },
      },
      _displayLine: Boolean,
      _loading: {
        type: Boolean,
        observer: '_loadingChanged',
      },
      /** @type {Gerrit.LayoutStats|undefined} */
      _sizeBarLayout: {
        type: Object,
        computed: '_computeSizeBarLayout(_shownFiles.*)',
      },

      _showSizeBars: {
        type: Boolean,
        value: true,
        computed: '_computeShowSizeBars(_userPrefs)',
      },

      /** @type {Function} */
      _cancelForEachDiff: Function,

      _showDynamicColumns: {
        type: Boolean,
        computed: '_computeShowDynamicColumns(_dynamicHeaderEndpoints, ' +
                '_dynamicContentEndpoints, _dynamicSummaryEndpoints)',
      },
      _showPrependedDynamicColumns: {
        type: Boolean,
        computed: '_computeShowPrependedDynamicColumns(' +
        '_dynamicPrependedHeaderEndpoints, _dynamicPrependedContentEndpoints)',
      },
      /** @type {Array<string>} */
      _dynamicHeaderEndpoints: {
        type: Array,
      },
      /** @type {Array<string>} */
      _dynamicContentEndpoints: {
        type: Array,
      },
      /** @type {Array<string>} */
      _dynamicSummaryEndpoints: {
        type: Array,
      },
      /** @type {Array<string>} */
      _dynamicPrependedHeaderEndpoints: {
        type: Array,
      },
      /** @type {Array<string>} */
      _dynamicPrependedContentEndpoints: {
        type: Array,
      },
    };
  }

  static get observers() {
    return [
      '_expandedFilesChanged(_expandedFiles.splices)',
      '_computeFiles(_filesByPath, changeComments, patchRange, _reviewed, ' +
        '_loading)',
    ];
  }

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

  constructor() {
    super();
    this.reporting = appContext.reportingService;
  }

  /** @override */
  created() {
    super.created();
    this.addEventListener('keydown',
        e => this._scopedKeydownHandler(e));
  }

  /** @override */
  attached() {
    super.attached();
    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) {
            console.warn(
                'Different number of dynamic file-list header and content.');
          }
          if (this._dynamicPrependedHeaderEndpoints.length !==
        this._dynamicPrependedContentEndpoints.length) {
            console.warn(
                'Different number of dynamic file-list header and content.');
          }
          if (this._dynamicHeaderEndpoints.length !==
          this._dynamicSummaryEndpoints.length) {
            console.warn(
                'Different number of dynamic file-list headers and summary.');
          }
        });
  }

  /** @override */
  detached() {
    super.detached();
    this._cancelDiffs();
  }

  /**
   * 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) {
    if (e.keyCode === 13) {
      // Enter.
      this._handleOpenFile(e);
    }
  }

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

    this._loading = true;

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

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

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

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

  get diffs() {
    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) {
    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,
      };
    }, {inserted: 0, deleted: 0, size_delta_inserted: 0,
      size_delta_deleted: 0, total_size: 0});
  }

  _getDiffPreferences() {
    return this.$.restAPI.getDiffPreferences();
  }

  _getPreferences() {
    return this.$.restAPI.getPreferences();
  }

  _toggleFileExpanded(file) {
    // 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) {
    this._toggleFileExpanded(this._computeFileRange(this._files[index]));
  }

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

  _forEachDiff(fn) {
    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 = [];
    let path;
    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._computeFileRange(this._shownFiles[i]));
      }
    }

    this.splice(...['_expandedFiles', 0, 0].concat(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.
   *
   * @param {!Object} changeComments
   * @param {!Object} patchRange
   * @param {string} path
   * @return {string}
   */
  _computeCommentsString(changeComments, patchRange, path) {
    if ([changeComments, patchRange, path].includes(undefined)) {
      return '';
    }
    const unresolvedCount =
        changeComments.computeUnresolvedNum({
          patchNum: patchRange.basePatchNum,
          path,
        }) +
        changeComments.computeUnresolvedNum({
          patchNum: patchRange.patchNum,
          path,
        });
    const commentCount =
        changeComments.computeCommentCount({
          patchNum: patchRange.basePatchNum,
          path,
        }) +
        changeComments.computeCommentCount({
          patchNum: patchRange.patchNum,
          path,
        });
    const commentString = GrCountStringFormatter.computePluralString(
        commentCount, 'comment');
    const unresolvedString = GrCountStringFormatter.computeString(
        unresolvedCount, 'unresolved');

    return commentString +
        // Add a space if both comments and unresolved
        (commentString && unresolvedString ? ' ' : '') +
        // Add parentheses around unresolved if it exists.
        (unresolvedString ? `(${unresolvedString})` : '');
  }

  /**
   * Computes a string with the number of drafts.
   *
   * @param {!Object} changeComments
   * @param {!Object} patchRange
   * @param {string} path
   * @return {string}
   */
  _computeDraftsString(changeComments, patchRange, path) {
    if ([changeComments, patchRange, path].includes(undefined)) {
      return '';
    }
    const draftCount =
        changeComments.computeDraftCount({
          patchNum: patchRange.basePatchNum,
          path,
        }) +
        changeComments.computeDraftCount({
          patchNum: patchRange.patchNum,
          path,
        });
    return GrCountStringFormatter.computePluralString(draftCount, 'draft');
  }

  /**
   * Computes a shortened string with the number of drafts.
   *
   * @param {!Object} changeComments
   * @param {!Object} patchRange
   * @param {string} path
   * @return {string}
   */
  _computeDraftsStringMobile(changeComments, patchRange, path) {
    if ([changeComments, patchRange, path].includes(undefined)) {
      return '';
    }
    const draftCount =
        changeComments.computeDraftCount({
          patchNum: patchRange.basePatchNum,
          path,
        }) +
        changeComments.computeDraftCount({
          patchNum: patchRange.patchNum,
          path,
        });
    return GrCountStringFormatter.computeShortString(draftCount, 'd');
  }

  /**
   * Computes a shortened string with the number of comments.
   *
   * @param {!Object} changeComments
   * @param {!Object} patchRange
   * @param {string} path
   * @return {string}
   */
  _computeCommentsStringMobile(changeComments, patchRange, path) {
    if ([changeComments, patchRange, path].includes(undefined)) {
      return '';
    }
    const commentCount =
        changeComments.computeCommentCount({
          patchNum: patchRange.basePatchNum,
          path,
        }) +
        changeComments.computeCommentCount({
          patchNum: patchRange.patchNum,
          path,
        });
    return GrCountStringFormatter.computeShortString(commentCount, 'c');
  }

  /**
   * @param {string} path
   * @param {boolean=} opt_reviewed
   */
  _reviewFile(path, opt_reviewed) {
    if (this.editMode) { return; }
    const index = this._files.findIndex(file => file.__path === path);
    const reviewed = opt_reviewed || !this._files[index].isReviewed;

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

    this._saveReviewedState(path, reviewed);
  }

  _saveReviewedState(path, reviewed) {
    return this.$.restAPI.saveFileReviewed(this.changeNum,
        this.patchRange.patchNum, path, reviewed);
  }

  _getLoggedIn() {
    return this.$.restAPI.getLoggedIn();
  }

  _getReviewedFiles() {
    if (this.editMode) { return Promise.resolve([]); }
    return this.$.restAPI.getReviewedFiles(this.changeNum,
        this.patchRange.patchNum);
  }

  _getFiles() {
    return this.$.restAPI.getChangeOrEditFiles(
        this.changeNum, this.patchRange);
  }

  /**
   *
   * @returns {!Array<FileInfo>}
   */
  _normalizeChangeFilesResponse(response) {
    if (!response) { return []; }
    const paths = Object.keys(response).sort(specialFilePathCompare);
    const files = [];
    for (let i = 0; i < paths.length; i++) {
      const info = response[paths[i]];
      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) {
    if (e.type === 'click') {
      return true;
    }
    const isSpaceOrEnter = (e.key === 'Enter' || e.key === ' ');
    return e.type === 'keydown' && isSpaceOrEnter;
  }

  _fileActionClick(e, fileAction) {
    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) {
    this._fileActionClick(e,
        file => this._reviewFile(file.path));
  }

  _expandedClick(e) {
    this._fileActionClick(e,
        file => this._toggleFileExpanded(file));
  }

  /**
   * Handle all events from the file list dom-repeat so event handleers don't
   * have to get registered for potentially very long lists.
   */
  _handleFileListClick(e) {
    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, 'pathLink')) { return; }

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

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

  _getFileRowFromEvent(e) {
    // Traverse upwards to find the row element if the target is not the row.
    let row = e.target;
    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']),
      element: row,
    };
  }

  /**
   * Generates file range from file info object.
   *
   * @param {FileInfo} file
   * @returns {Gerrit.FileRange}
   */
  _computeFileRange(file) {
    const fileData = {
      path: file.__path,
    };
    if (file.old_path) {
      fileData.basePath = file.old_path;
    }
    return fileData;
  }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  _handleNewComment(e) {
    if (this.shouldSuppressKeyboardShortcut(e) ||
        this.modifierPressed(e)) { return; }
    e.preventDefault();
    this.$.diffCursor.createCommentInPlace();
  }

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

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

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

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

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

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

    this._openSelectedFile();
  }

  _handleNextChunk(e) {
    if (this.shouldSuppressKeyboardShortcut(e) ||
        (this.modifierPressed(e) && !this.isModifierPressed(e, 'shiftKey')) ||
        this._noDiffsExpanded()) {
      return;
    }

    e.preventDefault();
    if (this.isModifierPressed(e, 'shiftKey')) {
      this.$.diffCursor.moveToNextCommentThread();
    } else {
      this.$.diffCursor.moveToNextChunk();
    }
  }

  _handlePrevChunk(e) {
    if (this.shouldSuppressKeyboardShortcut(e) ||
        (this.modifierPressed(e) && !this.isModifierPressed(e, 'shiftKey')) ||
        this._noDiffsExpanded()) {
      return;
    }

    e.preventDefault();
    if (this.isModifierPressed(e, 'shiftKey')) {
      this.$.diffCursor.moveToPreviousCommentThread();
    } else {
      this.$.diffCursor.moveToPreviousChunk();
    }
  }

  _handleToggleFileReviewed(e) {
    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) {
    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();
    GerritNav.navigateToDiff(this.change, diff.path,
        diff.patchRange.patchNum, this.patchRange.basePatchNum);
  }

  /**
   * @param {number=} opt_index
   */
  _openSelectedFile(opt_index) {
    if (opt_index != null) {
      this.$.fileCursor.setCursorAtIndex(opt_index);
    }
    if (!this._files[this.$.fileCursor.index]) { return; }
    GerritNav.navigateToDiff(this.change,
        this._files[this.$.fileCursor.index].__path, this.patchRange.patchNum,
        this.patchRange.basePatchNum);
  }

  _addDraftAtTarget() {
    const diff = this.$.diffCursor.getTargetDiffElement();
    const target = this.$.diffCursor.getTargetLineElement();
    if (diff && target) {
      diff.addDraftAtLine(target);
    }
  }

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

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

  _computeFileStatus(status) {
    return status || 'M';
  }

  _computeDiffURL(change, patchRange, path, editMode) {
    // Polymer 2: check for undefined
    if ([change, patchRange, path, editMode]
        .some(arg => arg === undefined)) {
      return;
    }
    if (editMode && path !== SpecialFilePath.MERGE_LIST) {
      return GerritNav.getEditUrlForDiff(change, path, patchRange.patchNum,
          patchRange.basePatchNum);
    }
    return GerritNav.getUrlForDiff(change, path, patchRange.patchNum,
        patchRange.basePatchNum);
  }

  _formatBytes(bytes) {
    if (bytes == 0) 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 ? '+' : '';
    return prepend + parseFloat((bytes / Math.pow(bits, exponent))
        .toFixed(decimals)) + ' ' + sizes[exponent];
  }

  _formatPercentage(size, delta) {
    const oldSize = size - delta;

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

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

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

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

  _computeStatusClass(file) {
    const classStr = this._computeClass('status', file.__path);
    return `${classStr} ${this._computeFileStatus(file.status)}`;
  }

  _computePathClass(path, expandedFilesRecord) {
    return this._isFileExpanded(path, expandedFilesRecord) ? 'expanded' : '';
  }

  _computeShowHideIcon(path, expandedFilesRecord) {
    return this._isFileExpanded(path, expandedFilesRecord) ?
      'gr-icons:expand-less' : 'gr-icons:expand-more';
  }

  _computeFiles(filesByPath, changeComments, patchRange, reviewed, loading) {
    // Polymer 2: check for undefined
    if ([
      filesByPath,
      changeComments,
      patchRange,
      reviewed,
      loading,
    ].includes(undefined)) {
      return;
    }

    // Await all promises resolving from reload. @See Issue 9057
    if (loading || !changeComments) { return; }

    const commentedPaths = changeComments.getPaths(patchRange);
    const files = {...filesByPath};
    addUnmodifiedFiles(files, commentedPaths);
    const reviewedSet = new Set(reviewed || []);
    for (const filePath in files) {
      if (!files.hasOwnProperty(filePath)) { continue; }
      files[filePath].isReviewed = reviewedSet.has(filePath);
    }

    this._files = this._normalizeChangeFilesResponse(files);
  }

  _computeFilesShown(numFilesShown, files) {
    // Polymer 2: check for undefined
    if ([numFilesShown, files].includes(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(RENDER_TIMING_LABEL);

    // 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.splice(
        ...['diffs', 0, this.$.diffCursor.diffs.length].concat(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, files) {
    return numFilesShown >= files.length ? 'invisible' : '';
  }

  _computeIncrementText(numFilesShown, files) {
    if (!files) { return ''; }
    const text =
        Math.min(this.fileListIncrement, files.length - numFilesShown);
    return 'Show ' + text + ' more';
  }

  _computeShowAllText(files) {
    if (!files) { return ''; }
    return 'Show all ' + files.length + ' files';
  }

  _computeWarnShowAll(files) {
    return files.length > WARN_SHOW_ALL_THRESHOLD;
  }

  _computeShowAllWarning(files) {
    if (!this._computeWarnShowAll(files)) { return ''; }
    return 'Warning: showing all ' + files.length +
        ' files may take several seconds.';
  }

  _showAllFiles() {
    this.numFilesShown = this._files.length;
  }

  _computePatchSetDescription(revisions, patchNum) {
    // Polymer 2: check for undefined
    if ([revisions, patchNum].includes(undefined)) {
      return '';
    }

    const rev = getRevisionByPatchNum(revisions, patchNum);
    return (rev && rev.description) ?
      rev.description.substring(0, PATCH_DESC_MAX_LENGTH) : '';
  }

  /**
   * Get a descriptive label for use in the status indicator's tooltip and
   * ARIA label.
   *
   * @param {string} status
   * @return {string}
   */
  _computeFileStatusLabel(status) {
    const statusCode = this._computeFileStatus(status);
    return FileStatus.hasOwnProperty(statusCode) ?
      FileStatus[statusCode] : 'Status Unknown';
  }

  /**
   * 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.
   *
   * @param {object} val
   * @return {string} 'true' if val is true-like, otherwise false
   */
  _booleanToString(val) {
    return val ? 'true' : 'false';
  }

  _isFileExpanded(path, expandedFilesRecord) {
    return expandedFilesRecord.base.some(f => f.path === path);
  }

  _isFileExpandedStr(path, expandedFilesRecord) {
    return this._booleanToString(
        this._isFileExpanded(path, expandedFilesRecord));
  }

  _computeExpandedFiles(expandedCount, totalCount) {
    if (expandedCount === 0) {
      return GrFileListConstants.FilesExpandedState.NONE;
    } else if (expandedCount === totalCount) {
      return GrFileListConstants.FilesExpandedState.ALL;
    }
    return GrFileListConstants.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 {!Array} record The splice record in the expanded paths list.
   */
  _expandedFilesChanged(record) {
    // 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(EXPAND_ALL_TIMING_LABEL);

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

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

  _clearCollapsedDiffs(collapsedDiffs) {
    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  {!Array<Gerrit.FileRange>} files
   * @param  {!NodeList<!Object>} diffElements (GrDiffHostElement)
   * @param  {number} initialCount The total number of paths in the pass. This
   *   is used to generate log messages.
   * @return {!Promise}
   */
  _renderInOrder(files, diffElements, initialCount) {
    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) {
        console.warn(`Did not find <gr-diff-host> element for ${path}`);
        return Promise.resolve();
      }
      diffElem.comments = this.changeComments.getCommentsBySideForFile(
          file, this.patchRange, this.projectConfig);
      const promises = [diffElem.reload()];
      if (this._loggedIn && !this.diffPrefs.manual_review) {
        promises.push(this._reviewFile(path, true));
      }
      return Promise.all(promises);
    }).then(() => {
      this._cancelForEachDiff = null;
      this._nextRenderParams = null;
      console.info('Finished expanding', initialCount, 'diff(s)');
      this.reporting.timeEndWithAverage(EXPAND_ALL_TIMING_LABEL,
          EXPAND_ALL_AVG_TIMING_LABEL, 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.
   *
   * @param  {string} path
   * @param  {!NodeList<!Object>} diffElements (GrDiffElement)
   * @return {!Object|undefined} (GrDiffElement)
   */
  _findDiffByPath(path, diffElements) {
    for (let i = 0; i < diffElements.length; i++) {
      if (diffElements[i].path === path) {
        return diffElements[i];
      }
    }
  }

  /**
   * Reset the comments of a modified thread
   *
   * @param  {string} rootId
   * @param  {string} path
   */
  reloadCommentsForThreadWithRootId(rootId, path) {
    // 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);

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

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

    // Comments are not returned with the commentSide attribute from
    // the api, but it's necessary to be stored on the diff's
    // comments due to use in the _handleCommentUpdate function.
    // The comment thread already has a side associated with it, so
    // set the comment's side to match.
    threadEl.comments = newComments.map(c => Object.assign(
        c, {__commentSide: threadEl.commentSide}
    ));
    flush();
  }

  _handleEscKey(e) {
    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.
   *
   * @param {boolean} loading
   */
  _loadingChanged(loading) {
    this.debounce('loading-change', () => {
      // 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) {
    this.classList.toggle('editMode', editMode);
  }

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

  _computeReviewedText(isReviewed) {
    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.
   *
   * @param {string} path
   * @return {boolean}
   */
  _showBarsForPath(path) {
    return path !== SpecialFilePath.COMMIT_MESSAGE &&
      path !== SpecialFilePath.MERGE_LIST;
  }

  /**
   * Compute size bar layout values from the file list.
   *
   * @return {Gerrit.LayoutStats|undefined}
   *
   */
  _computeSizeBarLayout(shownFilesRecord) {
    if (!shownFilesRecord || !shownFilesRecord.base) { return undefined; }
    const stats = {
      maxInserted: 0,
      maxDeleted: 0,
      maxAdditionWidth: 0,
      maxDeletionWidth: 0,
      deletionOffset: 0,
    };
    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.
   *
   * @param {Object} file
   * @param {Gerrit.LayoutStats} stats
   * @return {number}
   */
  _computeBarAdditionWidth(file, stats) {
    if (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.
   *
   * @param {Object} file
   * @param {Gerrit.LayoutStats} stats
   * @return {number}
   */
  _computeBarAdditionX(file, stats) {
    return stats.maxAdditionWidth -
        this._computeBarAdditionWidth(file, stats);
  }

  /**
   * Get the width of the deletion bar for a file.
   *
   * @param {Object} file
   * @param {Gerrit.LayoutStats} stats
   * @return {number}
   */
  _computeBarDeletionWidth(file, stats) {
    if (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.
   *
   * @param {Gerrit.LayoutStats} stats
   *
   * @return {number}
   */
  _computeBarDeletionX(stats) {
    return stats.deletionOffset;
  }

  _computeShowSizeBars(userPrefs) {
    return !!userPrefs.size_bar_in_change_table;
  }

  _computeSizeBarsClass(showSizeBars, path) {
    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, contentEndpoints, summaryEndpoints) {
    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, contentEndpoints) {
    return headerEndpoints && contentEndpoints &&
           headerEndpoints.length &&
           headerEndpoints.length === contentEndpoints.length;
  }

  /**
   * Returns true if none of the inline diffs have been expanded.
   *
   * @return {boolean}
   */
  _noDiffsExpanded() {
    return this.filesExpanded === GrFileListConstants.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 {number} index The index of the row being rendered.
   * @return {string} an empty string.
   */
  _reportRenderedRow(index) {
    if (index === this._shownFiles.length - 1) {
      this.async(() => {
        this.reporting.timeEndWithAverage(RENDER_TIMING_LABEL,
            RENDER_AVG_TIMING_LABEL, this._reportinShownFilesIncrement);
      }, 1);
    }
    return '';
  }

  _reviewedTitle(reviewed) {
    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) {
    return computeDisplayPath(path);
  }

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

customElements.define(GrFileList.is, GrFileList);
