// 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.
  var PATCH_DESC_MAX_LENGTH = 500;
  var WARN_SHOW_ALL_THRESHOLD = 1000;
  var COMMIT_MESSAGE_PATH = '/COMMIT_MSG';

  var FileStatus = {
    A: 'Added',
    C: 'Copied',
    D: 'Deleted',
    R: 'Renamed',
    W: 'Rewritten',
  };

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

    properties: {
      patchRange: {
        type: Object,
        observer: '_updateSelected',
      },
      patchNum: String,
      changeNum: String,
      comments: Object,
      drafts: Object,
      revisions: Object,
      projectConfig: Object,
      selectedIndex: {
        type: Number,
        notify: true,
      },
      keyEventTarget: {
        type: Object,
        value: function() { return document.body; },
      },
      change: Object,
      diffViewMode: {
        type: String,
        notify: true,
      },
      _files: {
        type: Array,
        observer: '_filesChanged',
        value: function() { return []; },
      },
      _loggedIn: {
        type: Boolean,
        value: false,
      },
      _reviewed: {
        type: Array,
        value: function() { return []; },
      },
      _diffAgainst: String,
      _diffPrefs: Object,
      _userPrefs: Object,
      _localPrefs: Object,
      _showInlineDiffs: Boolean,
      numFilesShown: {
        type: Number,
        notify: true,
      },
      _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.*)',
      },
      // Caps the number of files that can be shown and have the 'show diffs' /
      // 'hide diffs' buttons still be functional.
      _maxFilesForBulkActions: {
        type: Number,
        readOnly: true,
        value: 225,
      },
      _expandedFilePaths: {
        type: Array,
        value: function() { return []; },
      },
    },

    behaviors: [
      Gerrit.BaseUrlBehavior,
      Gerrit.KeyboardShortcutBehavior,
      Gerrit.PatchSetBehavior,
      Gerrit.URLEncodingBehavior,
    ],

    observers: [
      '_expandedPathsChanged(_expandedFilePaths.splices)',
      '_setReviewedFiles(_shownFiles, _files, _reviewed.*, _loggedIn)',
    ],

    keyBindings: {
      'shift+left': '_handleShiftLeftKey',
      'shift+right': '_handleShiftRightKey',
      'i': '_handleIKey',
      'shift+i': '_handleCapitalIKey',
      'down j': '_handleDownKey',
      'up k': '_handleUpKey',
      'c': '_handleCKey',
      '[': '_handleLeftBracketKey',
      ']': '_handleRightBracketKey',
      'o enter': '_handleEnterKey',
      'n': '_handleNKey',
      'p': '_handlePKey',
      'shift+a': '_handleCapitalAKey',
    },

    reload: function() {
      if (!this.changeNum || !this.patchRange.patchNum) {
        return Promise.resolve();
      }
      this._collapseAllDiffs();
      var promises = [];
      var _this = this;

      promises.push(this._getFiles().then(function(files) {
        _this._files = files;
      }));
      promises.push(this._getLoggedIn().then(function(loggedIn) {
        return _this._loggedIn = loggedIn;
      }).then(function(loggedIn) {
        if (!loggedIn) { return; }

        return _this._getReviewedFiles().then(function(reviewed) {
          _this._reviewed = reviewed;
        });
      }));

      this._localPrefs = this.$.storage.getPreferences();
      promises.push(this._getDiffPreferences().then(function(prefs) {
        this._diffPrefs = prefs;
      }.bind(this)));

      promises.push(this._getPreferences().then(function(prefs) {
        this._userPrefs = prefs;
        if (!this.diffViewMode) {
          this.set('diffViewMode', prefs.default_diff_view);
        }
      }.bind(this)));
    },

    get diffs() {
      return Polymer.dom(this.root).querySelectorAll('gr-diff');
    },

    _calculatePatchChange: function(files) {
      var filesNoCommitMsg = files.filter(function(files) {
        return files.__path !== '/COMMIT_MSG';
      });

      return filesNoCommitMsg.reduce(function(acc, obj) {
        var inserted = obj.lines_inserted ? obj.lines_inserted : 0;
        var deleted = obj.lines_deleted ? obj.lines_deleted : 0;
        var total_size = (obj.size && obj.binary) ? obj.size : 0;
        var size_delta_inserted =
            obj.binary && obj.size_delta > 0 ? obj.size_delta : 0;
        var 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: function() {
      return this.$.restAPI.getDiffPreferences();
    },

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

    _computePatchSets: function(revisionRecord) {
      var revisions = revisionRecord.base;
      var patchNums = [];
      for (var commit in revisions) {
        if (revisions.hasOwnProperty(commit)) {
          patchNums.push({
            num: revisions[commit]._number,
            desc: revisions[commit].description,
          });
        }
      }
      return patchNums.sort(function(a, b) { return a.num - b.num; });
    },

    _computePatchSetDisabled: function(patchNum, currentPatchNum) {
      return parseInt(patchNum, 10) >= parseInt(currentPatchNum, 10);
    },

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

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

    _handlePatchChange: function(e) {
      var patchRange = Object.assign({}, this.patchRange);
      patchRange.basePatchNum = Polymer.dom(e).rootTarget.value;
      page.show(this.encodeURL('/c/' + this.changeNum + '/' +
          this._patchRangeStr(patchRange), true));
    },

    _forEachDiff: function(fn) {
      var diffs = this.diffs;
      for (var i = 0; i < diffs.length; i++) {
        fn(diffs[i]);
      }
    },

    _expandAllDiffs: function(e) {
      this._showInlineDiffs = true;

      // Find the list of paths that are in the file list, but not in the
      // expanded list.
      var newPaths = [];
      var path;
      for (var i = 0; i < this._shownFiles.length; i++) {
        path = this._shownFiles[i].__path;
        if (this._expandedFilePaths.indexOf(path) === -1) {
          newPaths.push(path);
        }
      }

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

    _collapseAllDiffs: function(e) {
      this._showInlineDiffs = false;
      this._expandedFilePaths = [];
      this.$.diffCursor.handleDiffUpdate();
    },

    _computeCommentsString: function(comments, patchNum, path) {
      return this._computeCountString(comments, patchNum, path, 'comment');
    },

    _computeDraftsString: function(drafts, patchNum, path) {
      return this._computeCountString(drafts, patchNum, path, 'draft');
    },

    _computeDraftsStringMobile: function(drafts, patchNum, path) {
      var draftCount = this._computeCountString(drafts, patchNum, path);
      return draftCount ? draftCount + 'd' : '';
    },

    _computeCommentsStringMobile: function(comments, patchNum, path) {
      var commentCount = this._computeCountString(comments, patchNum, path);
      return commentCount ? commentCount + 'c' : '';
    },

    _getCommentsForPath: function(comments, patchNum, path) {
      return (comments[path] || []).filter(function(c) {
        return parseInt(c.patch_set, 10) === parseInt(patchNum, 10);
      });
    },

    _computeCountString: function(comments, patchNum, path, opt_noun) {
      if (!comments) { return ''; }

      var patchComments = this._getCommentsForPath(comments, patchNum, path);
      var num = patchComments.length;
      if (num === 0) { return ''; }
      if (!opt_noun) { return num; }
      var output = num + ' ' + opt_noun + (num > 1 ? 's' : '');
      return output;
    },

    /**
     * Computes a string counting the number of unresolved comment threads in a
     * given file and path.
     *
     * @param {Object} comments
     * @param {Object} drafts
     * @param {number} patchNum
     * @param {string} path
     * @return {string}
     */
    _computeUnresolvedString: function(comments, drafts, patchNum, path) {
      comments = this._getCommentsForPath(comments, patchNum, path);
      drafts = this._getCommentsForPath(drafts, patchNum, path);
      comments = comments.concat(drafts);

      // Create an object where every comment ID is the key of an unresolved
      // comment.

      var idMap = comments.reduce(function(acc, comment) {
        if (comment.unresolved) {
          acc[comment.id] = true;
        }
        return acc;
      }, {});

      // Set false for the comments that are marked as parents.
      comments.forEach(function(comment) {
        idMap[comment.in_reply_to] = false;
      });

      // The unresolved comments are the comments that still have true.
      var unresolvedLeaves = Object.keys(idMap).filter(function(key) {
        return idMap[key];
      });

      return unresolvedLeaves.length === 0 ?
          '' : '(' + unresolvedLeaves.length + ' unresolved)';
    },

    _computeReviewed: function(file, _reviewed) {
      return _reviewed.indexOf(file.__path) !== -1;
    },

    _handleReviewedChange: function(e) {
      this._reviewFile(Polymer.dom(e).rootTarget.getAttribute('data-path'));
    },

    _reviewFile: function(path) {
      var index = this._reviewed.indexOf(path);
      var reviewed = index !== -1;
      if (reviewed) {
        this.splice('_reviewed', index, 1);
      } else {
        this.push('_reviewed', path);
      }

      this._saveReviewedState(path, !reviewed);
    },

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

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

    _getReviewedFiles: function() {
      return this.$.restAPI.getReviewedFiles(this.changeNum,
          this.patchRange.patchNum);
    },

    _getFiles: function() {
      return this.$.restAPI.getChangeFilesAsSpeciallySortedArray(
          this.changeNum, this.patchRange).then(function(files) {
            // Append UI-specific properties.
            return files.map(function(file) {
              return file;
            });
          });
    },

    /**
     * Handle all events from the file list dom-repeat so event handleers don't
     * have to get registered for potentially very long lists.
     */
    _handleFileListTap: function(e) {
      // Handle checkbox mark as reviewed.
      if (e.target.classList.contains('reviewed')) {
        return this._handleReviewedChange(e);
      }

      // Check to see if the file should be expanded.
      var path = e.target.dataset.path || e.target.parentElement.dataset.path;

      // If the user prefers to expand inline diffs rather than opening the diff
      // view, intercept the click event.
      if (!path || e.detail.sourceEvent.metaKey ||
          e.detail.sourceEvent.ctrlKey) {
          return;
      }
      if (e.target.dataset.expand ||
          this._userPrefs && this._userPrefs.expand_inline_diffs) {
        e.preventDefault();
        this._togglePathExpanded(path);
      }
    },

    _handleShiftLeftKey: function(e) {
      if (this.shouldSuppressKeyboardShortcut(e)) { return; }
      if (!this._showInlineDiffs) { return; }

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

    _handleShiftRightKey: function(e) {
      if (this.shouldSuppressKeyboardShortcut(e)) { return; }
      if (!this._showInlineDiffs) { return; }

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

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

      e.preventDefault();
      this._togglePathExpandedByIndex(this.$.fileCursor.index);
    },

    _handleCapitalIKey: function(e) {
      if (this.shouldSuppressKeyboardShortcut(e)) { return; }

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

    _handleDownKey: function(e) {
      if (this.shouldSuppressKeyboardShortcut(e) || this.modifierPressed(e)) {
        return;
      }

      e.preventDefault();
      if (this._showInlineDiffs) {
        this.$.diffCursor.moveDown();
      } else {
        this.$.fileCursor.next();
        this.selectedIndex = this.$.fileCursor.index;
      }
    },

    _handleUpKey: function(e) {
      if (this.shouldSuppressKeyboardShortcut(e) || this.modifierPressed(e)) {
        return;
      }

      e.preventDefault();
      if (this._showInlineDiffs) {
        this.$.diffCursor.moveUp();
      } else {
        this.$.fileCursor.previous();
        this.selectedIndex = this.$.fileCursor.index;
      }
    },

    _handleCKey: function(e) {
      if (this.shouldSuppressKeyboardShortcut(e) ||
          this.modifierPressed(e)) { return; }

      var isRangeSelected = this.diffs.some(function(diff) {
        return diff.isRangeSelected();
      }, this);
      if (this._showInlineDiffs && !isRangeSelected) {
        e.preventDefault();
        this._addDraftAtTarget();
      }
    },

    _handleLeftBracketKey: function(e) {
      if (this.shouldSuppressKeyboardShortcut(e)) { return; }

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

    _handleRightBracketKey: function(e) {
      if (this.shouldSuppressKeyboardShortcut(e)) { return; }

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

    _handleEnterKey: function(e) {
      if (this.shouldSuppressKeyboardShortcut(e) ||
          this.modifierPressed(e)) { return; }

      // Use native handling if an anchor is selected. @see Issue 5754
      if (e.detail && e.detail.keyboardEvent && e.detail.keyboardEvent.target &&
          e.detail.keyboardEvent.target.tagName === 'A') { return; }

      e.preventDefault();
      if (this._showInlineDiffs) {
        this._openCursorFile();
      } else {
        this._openSelectedFile();
      }
    },

    _handleNKey: function(e) {
      if (this.shouldSuppressKeyboardShortcut(e) ||
          this.modifierPressed(e) && !this.isModifierPressed(e, 'shiftKey')) {
        return;
      }
      if (!this._showInlineDiffs) { return; }

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

    _handlePKey: function(e) {
      if (this.shouldSuppressKeyboardShortcut(e) ||
          this.modifierPressed(e) && !this.isModifierPressed(e, 'shiftKey')) {
        return;
      }
      if (!this._showInlineDiffs) { return; }

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

    _handleCapitalAKey: function(e) {
      if (this.shouldSuppressKeyboardShortcut(e)) { return; }

      e.preventDefault();
      this._forEachDiff(function(diff) {
        diff.toggleLeftDiff();
      });
    },

    _toggleInlineDiffs: function() {
      if (this._showInlineDiffs) {
        this._collapseAllDiffs();
      } else {
        this._expandAllDiffs();
      }
    },

    _openCursorFile: function() {
      var diff = this.$.diffCursor.getTargetDiffElement();
      page.show(this._computeDiffURL(diff.changeNum, diff.patchRange,
          diff.path));
    },

    _openSelectedFile: function(opt_index) {
      if (opt_index != null) {
        this.$.fileCursor.setCursorAtIndex(opt_index);
      }
      if (!this._files[this.$.fileCursor.index]) { return; }
      page.show(this._computeDiffURL(this.changeNum, this.patchRange,
          this._files[this.$.fileCursor.index].__path));
    },

    _addDraftAtTarget: function() {
      var diff = this.$.diffCursor.getTargetDiffElement();
      var target = this.$.diffCursor.getTargetLineElement();
      if (diff && target) {
        diff.addDraftAtLine(target);
      }
    },

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

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

    _computeFileStatus: function(status) {
      return status || 'M';
    },

    _computeDiffURL: function(changeNum, patchRange, path) {
      return this.encodeURL(this.getBaseUrl() + '/c/' + changeNum + '/' +
          this._patchRangeStr(patchRange) + '/' + path, true);
    },

    _patchRangeStr: function(patchRange) {
      return patchRange.basePatchNum !== 'PARENT' ?
          patchRange.basePatchNum + '..' + patchRange.patchNum :
          patchRange.patchNum + '';
    },

    _computeFileDisplayName: function(path) {
      return path === COMMIT_MESSAGE_PATH ? 'Commit message' : path;
    },

    _computeTruncatedFileDisplayName: function(path) {
      return path === COMMIT_MESSAGE_PATH ?
          'Commit message' : util.truncatePath(path);
    },

    _formatBytes: function(bytes) {
      if (bytes == 0) return '+/-0 B';
      var bits = 1024;
      var decimals = 1;
      var sizes = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
      var exponent = Math.floor(Math.log(Math.abs(bytes)) / Math.log(bits));
      var prepend = bytes > 0 ? '+' : '';
      return prepend + parseFloat((bytes / Math.pow(bits, exponent))
          .toFixed(decimals)) + ' ' + sizes[exponent];
    },

    _formatPercentage: function(size, delta) {
      var oldSize = size - delta;

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

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

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

    _computeClass: function(baseClass, path) {
      var classes = [baseClass];
      if (path === COMMIT_MESSAGE_PATH) {
        classes.push('invisible');
      }
      return classes.join(' ');
    },

    _computeExpandInlineClass: function(userPrefs) {
      return userPrefs.expand_inline_diffs ? 'expandInline' : '';
    },

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

    _computeShowHideText: function(path, expandedFilesRecord) {
      return this._isFileExpanded(path, expandedFilesRecord) ? '▼' : '◀';
    },

    _computeFilesShown: function(numFilesShown, files) {
      return files.base.slice(0, numFilesShown);
    },

    _setReviewedFiles: function(shownFiles, files, reviewedRecord, loggedIn) {
      if (!loggedIn) { return; }
      var reviewed = reviewedRecord.base;
      var fileReviewed;
      for (var i = 0; i < files.length; i++) {
        fileReviewed = this._computeReviewed(files[i], reviewed);
        this._files[i].isReviewed = fileReviewed;
        if (i < shownFiles.length) {
          this.set(['_shownFiles', i, 'isReviewed'], fileReviewed);
        }
      }
    },

    _updateDiffCursor: function() {
      var diffElements = Polymer.dom(this.root).querySelectorAll('gr-diff');

      // Overwrite the cursor's list of diffs:
      this.$.diffCursor.splice.apply(this.$.diffCursor,
          ['diffs', 0, this.$.diffCursor.diffs.length].concat(diffElements));
    },

    _filesChanged: function() {
      Polymer.dom.flush();
      var files = Polymer.dom(this.root).querySelectorAll('.file-row');
      this.$.fileCursor.stops = files;
      this.$.fileCursor.setCursorAtIndex(this.selectedIndex, true);
    },

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

    _computeFileListButtonHidden: function(numFilesShown, files) {
      return numFilesShown >= files.length;
    },

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

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

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

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

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

    _updateSelected: function(patchRange) {
      this._diffAgainst = patchRange.basePatchNum;
    },

    /**
     * _getDiffViewMode: Get the diff view (side-by-side or unified) based on
     * the current state.
     *
     * The expected behavior is to use the mode specified in the user's
     * preferences unless they have manually chosen the alternative view.
     *
     * Use side-by-side if there is no view mode or preferences.
     *
     * @return {String}
     */
    _getDiffViewMode: function(diffViewMode, userPrefs) {
      if (diffViewMode) {
        return diffViewMode;
      } else if (userPrefs) {
        return this.diffViewMode = userPrefs.default_diff_view;
      }
      return 'SIDE_BY_SIDE';
    },

    _fileListActionsVisible: function(shownFilesRecord,
        maxFilesForBulkActions) {
      return shownFilesRecord.base.length <= maxFilesForBulkActions;
    },

    _computePatchSetDescription: function(revisions, patchNum) {
      var rev = this.getRevisionByPatchNum(revisions, patchNum);
      return (rev && rev.description) ?
          rev.description.substring(0, PATCH_DESC_MAX_LENGTH) : '';
    },

    _computeFileStatusLabel: function(status) {
      var statusCode = this._computeFileStatus(status);
      return FileStatus.hasOwnProperty(statusCode) ?
          FileStatus[statusCode] : 'Status Unknown';
    },

    _isFileExpanded: function(path, expandedFilesRecord) {
      return expandedFilesRecord.base.indexOf(path) !== -1;
    },

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

    /**
     * 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  {splice} record The splice record in the expanded paths list.
     */
    _expandedPathsChanged: function(record) {
      if (!record) { return; }

      // Find the paths introduced by the new index splices:
      var newPaths = record.indexSplices
          .map(function(splice) {
            return splice.object.slice(splice.index,
                splice.index + splice.addedCount);
          })
          .reduce(function(acc, paths) { return acc.concat(paths); }, []);

      var timerName = 'Expand ' + newPaths.length + ' diffs';
      this.$.reporting.time(timerName);

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

      this._renderInOrder(newPaths, this.diffs, newPaths.length)
          .then(function() {
            this.$.reporting.timeEnd(timerName);
            this.$.diffCursor.handleDiffUpdate();
          }.bind(this));
      this._updateDiffCursor();
      this.$.diffCursor.handleDiffUpdate();
    },

    /**
     * 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<!GrDiffElement>} diffElements
     * @param  {Number} initialCount The total number of paths in the pass. This
     *   is used to generate log messages.
     * @return {!Promise}
     */
    _renderInOrder: function(paths, diffElements, initialCount) {
      if (!paths.length) {
        console.log('Finished expanding', initialCount, 'diff(s)');
        return Promise.resolve();
      }
      console.log('Expanding diff', 1 + initialCount - paths.length, 'of',
          initialCount, ':', paths[0]);
      var diffElem = this._findDiffByPath(paths[0], diffElements);
      var promises = [diffElem.reload()];
      if (this._isLoggedIn) {
        promises.push(this._reviewFile(paths[0]));
      }
      return Promise.all(promises).then(function() {
        return this._renderInOrder(paths.slice(1), diffElements, initialCount);
      }.bind(this));
    },

    /**
     * In the given NodeList of diff elements, find the diff for the given path.
     * @param  {!String} path
     * @param  {!NodeList<!GrDiffElement>} diffElements
     * @return {!GrDiffElement}
     */
    _findDiffByPath: function(path, diffElements) {
      for (var i = 0; i < diffElements.length; i++) {
        if (diffElements[i].path === path) {
          return diffElements[i];
        }
      }
    },
  });
})();
