/**
 * @license
 * Copyright (C) 2016 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.
 */
(function() {
  'use strict';

  // 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 Defs = {};

  /**
   * Object containing layout values to be used in rendering size-bars.
   * `max{Inserted,Deleted}` represent the largest values of the
   * `lines_inserted` and `lines_deleted` fields of the files respectively. The
   * `max{Addition,Deletion}Width` represent the width of the graphic allocated
   * to the insertion or deletion side respectively. Finally, the
   * `deletionOffset` value represents the x-position for the deletion bar.
   *
   * @typedef {{
   *    maxInserted: number,
   *    maxDeleted: number,
   *    maxAdditionWidth: number,
   *    maxDeletionWidth: number,
   *    deletionOffset: number,
   * }}
   */
  Defs.LayoutStats;

  Polymer({
    is: 'gr-file-list',

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

    properties: {
      /** @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,
      _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,
      _localPrefs: 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,

      _expandedFilePaths: {
        type: Array,
        value() { return []; },
      },
      _displayLine: Boolean,
      _loading: {
        type: Boolean,
        observer: '_loadingChanged',
      },
      /** @type {Defs.LayoutStats|undefined} */
      _sizeBarLayout: {
        type: Object,
        computed: '_computeSizeBarLayout(_shownFiles.*)',
      },

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

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

    behaviors: [
      Gerrit.AsyncForeachBehavior,
      Gerrit.DomUtilBehavior,
      Gerrit.KeyboardShortcutBehavior,
      Gerrit.PatchSetBehavior,
      Gerrit.PathListBehavior,
    ],

    observers: [
      '_expandedPathsChanged(_expandedFilePaths.splices)',
      '_computeFiles(_filesByPath, changeComments, patchRange, _reviewed, ' +
          '_loading)',
    ],

    keyBindings: {
      esc: '_handleEscKey',
    },

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

        // Final two are actually handled by gr-comment-thread.
        [this.Shortcut.EXPAND_ALL_COMMENT_THREADS]: null,
        [this.Shortcut.COLLAPSE_ALL_COMMENT_THREADS]: null,
      };
    },
    listeners: {
      keydown: '_scopedKeydownHandler',
    },

    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 => {
        return this._loggedIn = loggedIn;
      }).then(loggedIn => {
        if (!loggedIn) { return; }

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

      this._localPrefs = this.$.storage.getPreferences();
      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() {
      return Polymer.dom(this.root).querySelectorAll('gr-diff-host');
    },

    openDiffPrefs() {
      this.$.diffPreferences.open();
    },

    _calculatePatchChange(files) {
      const filesNoCommitMsg = files.filter(files => {
        return files.__path !== '/COMMIT_MSG';
      });

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

    _togglePathExpanded(path) {
      // Is the path in the list of expanded diffs? IF so remove it, otherwise
      // add it to the list.
      const pathIndex = this._expandedFilePaths.indexOf(path);
      if (pathIndex === -1) {
        this.push('_expandedFilePaths', path);
      } else {
        this.splice('_expandedFilePaths', pathIndex, 1);
      }
    },

    _togglePathExpandedByIndex(index) {
      this._togglePathExpanded(this._files[index].__path);
    },

    _updateDiffPreferences() {
      if (!this.diffs.length) { return; }
      // Re-render all expanded diffs sequentially.
      this.$.reporting.time(EXPAND_ALL_TIMING_LABEL);
      this._renderInOrder(this._expandedFilePaths, this.diffs,
          this._expandedFilePaths.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 newPaths = [];
      let path;
      for (let i = 0; i < this._shownFiles.length; i++) {
        path = this._shownFiles[i].__path;
        if (!this._expandedFilePaths.includes(path)) {
          newPaths.push(path);
        }
      }

      this.splice(...['_expandedFilePaths', 0, 0].concat(newPaths));
    },

    collapseAllDiffs() {
      this._showInlineDiffs = false;
      this._expandedFilePaths = [];
      this.filesExpanded = this._computeExpandedFiles(
          this._expandedFilePaths.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) {
      const unresolvedCount =
          changeComments.computeUnresolvedNum(patchRange.basePatchNum, path) +
          changeComments.computeUnresolvedNum(patchRange.patchNum, path);
      const commentCount =
          changeComments.computeCommentCount(patchRange.basePatchNum, path) +
          changeComments.computeCommentCount(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) {
      const draftCount =
          changeComments.computeDraftCount(patchRange.basePatchNum, path) +
          changeComments.computeDraftCount(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) {
      const draftCount =
          changeComments.computeDraftCount(patchRange.basePatchNum, path) +
          changeComments.computeDraftCount(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) {
      const commentCount =
          changeComments.computeCommentCount(patchRange.basePatchNum, path) +
          changeComments.computeCommentCount(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.set(['_shownFiles', index, 'isReviewed'], reviewed);
      }

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

    /**
     * The closure compiler doesn't realize this.specialFilePathCompare is
     * valid.
     * @suppress {checkTypes}
     */
    _normalizeChangeFilesResponse(response) {
      if (!response) { return []; }
      const paths = Object.keys(response).sort(this.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;
        files.push(info);
      }
      return files;
    },

    /**
     * Handle all events from the file list dom-repeat so event handleers don't
     * have to get registered for potentially very long lists.
     */
    _handleFileListTap(e) {
      // Traverse upwards to find the row element if the target is not the row.
      let row = e.target;
      while (!row.classList.contains('row') && row.parentElement) {
        row = row.parentElement;
      }

      const path = row.dataset.path;
      // Handle checkbox mark as reviewed.
      if (e.target.classList.contains('markReviewed')) {
        e.preventDefault();
        return this._reviewFile(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 || this.descendedFromClass(e.target, 'pathLink')) { return; }

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

      e.preventDefault();
      this._togglePathExpanded(path);
    },

    _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._togglePathExpandedByIndex(this.$.fileCursor.index);
    },

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

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

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

      const isRangeSelected = this.diffs.some(diff => {
        return diff.isRangeSelected();
      }, this);
      if (!isRangeSelected) {
        e.preventDefault();
        this._addDraftAtTarget();
      }
    },

    _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();
      Gerrit.Nav.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; }
      Gerrit.Nav.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, patchNum, basePatchNum, path, editMode) {
      // TODO(kaspern): Fix editing for commit messages and merge lists.
      if (editMode && path !== this.COMMIT_MESSAGE_PATH &&
          path !== this.MERGE_LIST_PATH) {
        return Gerrit.Nav.getEditUrlForDiff(change, path, patchNum,
            basePatchNum);
      }
      return Gerrit.Nav.getUrlForDiff(change, path, patchNum, 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 = [baseClass];
      if (path === this.COMMIT_MESSAGE_PATH || path === this.MERGE_LIST_PATH) {
        classes.push('invisible');
      }
      return classes.join(' ');
    },

    _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) {
      // Await all promises resolving from reload. @See Issue 9057
      if (loading) { return; }

      const commentedPaths = changeComments.getPaths(patchRange);
      const files = Object.assign({}, filesByPath);
      Object.keys(commentedPaths).forEach(commentedPath => {
        if (files.hasOwnProperty(commentedPath)) { return; }
        files[commentedPath] = {status: 'U'};
      });
      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) {
      const previousNumFilesShown = this._shownFiles ?
          this._shownFiles.length : 0;

      const filesShown = files.base.slice(0, numFilesShown);
      this.fire('files-shown-changed', {length: filesShown.length});

      // 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() {
      Polymer.dom.flush();
      const files = Polymer.dom(this.root).querySelectorAll('.file-row');
      this.$.fileCursor.stops = files;
      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) {
      const rev = this.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';
    },

    _isFileExpanded(path, expandedFilesRecord) {
      return expandedFilesRecord.base.includes(path);
    },

    _onLineSelected(e, detail) {
      this.$.diffCursor.moveToLineNumber(detail.number, detail.side,
          detail.path);
    },

    _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.
     */
    _expandedPathsChanged(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._expandedFilePaths.indexOf(diff.path) === -1);
      this._clearCollapsedDiffs(collapsedDiffs);

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

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

      // Find the paths introduced by the new index splices:
      const newPaths = 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.
      Polymer.dom.flush();

      this.$.reporting.time(EXPAND_ALL_TIMING_LABEL);

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

      this._updateDiffCursor();
      this.$.diffCursor.handleDiffUpdate();
    },

    _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
     * continung.
     * @param  {!Array<string>} paths
     * @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(paths, diffElements, initialCount) {
      let iter = 0;

      return (new Promise(resolve => {
        this.fire('reload-drafts', {resolve});
      })).then(() => {
        return this.asyncForeach(paths, (path, cancel) => {
          this._cancelForEachDiff = cancel;

          iter++;
          console.log('Expanding diff', iter, 'of', initialCount, ':',
              path);
          const diffElem = this._findDiffByPath(path, diffElements);
          diffElem.comments = this.changeComments.getCommentsBySideForPath(
              path, 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.log('Finished expanding', initialCount, 'diff(s)');
          this.$.reporting.timeEndWithAverage(EXPAND_ALL_TIMING_LABEL,
              EXPAND_ALL_AVG_TIMING_LABEL, initialCount);
          this.$.diffCursor.handleDiffUpdate();
        });
      });
    },

    /** 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._expandedFilePaths.includes(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 => {
        return Object.assign(c, {__commentSide: threadEl.commentSide});
      });
      Polymer.dom.flush();
      return;
    },

    _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 !== this.COMMIT_MESSAGE_PATH && path !== this.MERGE_LIST_PATH;
    },

    /**
     * Compute size bar layout values from the file list.
     * @return {Defs.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 {Defs.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 {Defs.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 {Defs.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 {Defs.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}`;
    },

    /**
     * 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)';
    },
  });
})();
