/**
 * @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 '@polymer/iron-dropdown/iron-dropdown.js';
import '@polymer/iron-input/iron-input.js';
import '../../../styles/shared-styles.js';
import '../../shared/gr-button/gr-button.js';
import '../../shared/gr-dropdown/gr-dropdown.js';
import '../../shared/gr-dropdown-list/gr-dropdown-list.js';
import '../../shared/gr-fixed-panel/gr-fixed-panel.js';
import '../../shared/gr-icons/gr-icons.js';
import '../../shared/gr-rest-api-interface/gr-rest-api-interface.js';
import '../../shared/gr-select/gr-select.js';
import '../../shared/revision-info/revision-info.js';
import '../gr-comment-api/gr-comment-api.js';
import '../gr-diff-cursor/gr-diff-cursor.js';
import '../gr-apply-fix-dialog/gr-apply-fix-dialog.js';
import '../gr-diff-host/gr-diff-host.js';
import '../gr-diff-mode-selector/gr-diff-mode-selector.js';
import '../gr-diff-preferences-dialog/gr-diff-preferences-dialog.js';
import '../gr-patch-range-select/gr-patch-range-select.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
import {mixinBehaviors} from '@polymer/polymer/lib/legacy/class.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-diff-view_html.js';
import {PatchSetBehavior} from '../../../behaviors/gr-patch-set-behavior/gr-patch-set-behavior.js';
import {PathListBehavior} from '../../../behaviors/gr-path-list-behavior/gr-path-list-behavior.js';
import {KeyboardShortcutBehavior} from '../../../behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior.js';
import {RESTClientBehavior} from '../../../behaviors/rest-client-behavior/rest-client-behavior.js';
import {GrCountStringFormatter} from '../../shared/gr-count-string-formatter/gr-count-string-formatter.js';
import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';
import {RevisionInfo} from '../../shared/revision-info/revision-info.js';
import {appContext} from '../../../services/app-context.js';

const ERR_REVIEW_STATUS = 'Couldn’t change file review status.';
const MSG_LOADING_BLAME = 'Loading blame...';
const MSG_LOADED_BLAME = 'Blame loaded';

const PARENT = 'PARENT';

const DiffSides = {
  LEFT: 'left',
  RIGHT: 'right',
};

const DiffViewMode = {
  SIDE_BY_SIDE: 'SIDE_BY_SIDE',
  UNIFIED: 'UNIFIED_DIFF',
};

/**
 * @appliesMixin PatchSetMixin
 * @extends PolymerElement
 */
class GrDiffView extends mixinBehaviors( [
  KeyboardShortcutBehavior,
  PatchSetBehavior,
  PathListBehavior,
  RESTClientBehavior,
], GestureEventListeners(
    LegacyElementMixin(
        PolymerElement))) {
  static get template() { return htmlTemplate; }

  static get is() { return 'gr-diff-view'; }
  /**
   * Fired when the title of the page should change.
   *
   * @event title-change
   */

  /**
   * Fired when user tries to navigate away while comments are pending save.
   *
   * @event show-alert
   */

  static get properties() {
    return {
    /**
     * URL params passed from the router.
     */
      params: {
        type: Object,
        observer: '_paramsChanged',
      },
      keyEventTarget: {
        type: Object,
        value() { return document.body; },
      },
      /**
       * @type {{ diffMode: (string|undefined) }}
       */
      changeViewState: {
        type: Object,
        notify: true,
        value() { return {}; },
        observer: '_changeViewStateChanged',
      },
      disableDiffPrefs: {
        type: Boolean,
        value: false,
      },
      _diffPrefsDisabled: {
        type: Boolean,
        computed: '_computeDiffPrefsDisabled(disableDiffPrefs, _loggedIn)',
      },
      /** @type {?} */
      _patchRange: Object,
      /** @type {?} */
      _commitRange: Object,
      /**
       * @type {{
       *  subject: string,
       *  project: string,
       *  revisions: string,
       * }}
       */
      _change: Object,
      /** @type {?} */
      _changeComments: Object,
      _changeNum: String,
      /**
       * This is a DiffInfo object.
       * This is retrieved and owned by a child component.
       */
      _diff: Object,
      // An array specifically formatted to be used in a gr-dropdown-list
      // element for selected a file to view.
      _formattedFiles: {
        type: Array,
        computed: '_formatFilesForDropdown(_files, ' +
          '_patchRange.patchNum, _changeComments)',
      },
      // An sorted array of files, as returned by the rest API.
      _fileList: {
        type: Array,
        computed: '_getSortedFileList(_files)',
      },
      /**
       * Contains information about files as returned by the rest API.
       *
       * @type {{ sortedFileList: Array<string>, changeFilesByPath: Object }}
       */
      _files: {
        type: Object,
        value() { return {sortedFileList: [], changeFilesByPath: {}}; },
      },

      /** @type {Gerrit.FileRange} */
      _file: {
        type: Object,
        computed: '_getCurrentFile(_files, _path)',
      },

      _path: {
        type: String,
        observer: '_pathChanged',
      },
      _fileNum: {
        type: Number,
        computed: '_computeFileNum(_path, _formattedFiles)',
      },
      _loggedIn: {
        type: Boolean,
        value: false,
      },
      _loading: {
        type: Boolean,
        value: true,
      },
      _prefs: Object,
      _localPrefs: Object,
      _projectConfig: Object,
      _userPrefs: Object,
      _diffMode: {
        type: String,
        computed: '_getDiffViewMode(changeViewState.diffMode, _userPrefs)',
      },
      _isImageDiff: Boolean,
      _filesWeblinks: Object,

      /**
       * Map of paths in the current change and patch range that have comments
       * or drafts or robot comments.
       */
      _commentMap: Object,

      _commentsForDiff: Object,

      /**
       * Object to contain the path of the next and previous file in the current
       * change and patch range that has comments.
       */
      _commentSkips: {
        type: Object,
        computed: '_computeCommentSkips(_commentMap, _fileList, _path)',
      },
      _panelFloatingDisabled: {
        type: Boolean,
        value: () => window.PANEL_FLOATING_DISABLED,
      },
      _editMode: {
        type: Boolean,
        computed: '_computeEditMode(_patchRange.*)',
      },
      _isBlameLoaded: Boolean,
      _isBlameLoading: {
        type: Boolean,
        value: false,
      },
      _allPatchSets: {
        type: Array,
        computed: 'computeAllPatchSets(_change, _change.revisions.*)',
      },
      _revisionInfo: {
        type: Object,
        computed: '_getRevisionInfo(_change)',
      },
      _reviewedFiles: {
        type: Object,
        value: () => new Set(),
      },

      /**
       * gr-diff-view has gr-fixed-panel on top. The panel can
       * intersect a main element and partially hides a content of
       * the main element. To correctly calculates visibility of an
       * element, the cursor must know how much height occupied by a fixed
       * panel.
       * The scrollTopMargin defines margin occupied by fixed panel.
       */
      _scrollTopMargin: {
        type: Number,
        value: 0,
      },
    };
  }

  static get observers() {
    return [
      '_getProjectConfig(_change.project)',
      '_getFiles(_changeNum, _patchRange.*, _changeComments)',
      '_setReviewedObserver(_loggedIn, params.*, _prefs)',
      '_recomputeComments(_files.changeFilesByPath,' +
      '_path, _patchRange, _projectConfig)',
    ];
  }

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

  keyboardShortcuts() {
    return {
      [this.Shortcut.LEFT_PANE]: '_handleLeftPane',
      [this.Shortcut.RIGHT_PANE]: '_handleRightPane',
      [this.Shortcut.NEXT_LINE]: '_handleNextLineOrFileWithComments',
      [this.Shortcut.PREV_LINE]: '_handlePrevLineOrFileWithComments',
      [this.Shortcut.VISIBLE_LINE]: '_handleVisibleLine',
      [this.Shortcut.NEXT_FILE_WITH_COMMENTS]:
          '_handleNextLineOrFileWithComments',
      [this.Shortcut.PREV_FILE_WITH_COMMENTS]:
          '_handlePrevLineOrFileWithComments',
      [this.Shortcut.NEW_COMMENT]: '_handleNewComment',
      [this.Shortcut.SAVE_COMMENT]: null, // DOC_ONLY binding
      [this.Shortcut.NEXT_FILE]: '_handleNextFile',
      [this.Shortcut.PREV_FILE]: '_handlePrevFile',
      [this.Shortcut.NEXT_CHUNK]: '_handleNextChunkOrCommentThread',
      [this.Shortcut.NEXT_COMMENT_THREAD]: '_handleNextChunkOrCommentThread',
      [this.Shortcut.PREV_CHUNK]: '_handlePrevChunkOrCommentThread',
      [this.Shortcut.PREV_COMMENT_THREAD]: '_handlePrevChunkOrCommentThread',
      [this.Shortcut.OPEN_REPLY_DIALOG]:
          '_handleOpenReplyDialogOrToggleLeftPane',
      [this.Shortcut.TOGGLE_LEFT_PANE]:
          '_handleOpenReplyDialogOrToggleLeftPane',
      [this.Shortcut.UP_TO_CHANGE]: '_handleUpToChange',
      [this.Shortcut.OPEN_DIFF_PREFS]: '_handleCommaKey',
      [this.Shortcut.TOGGLE_DIFF_MODE]: '_handleToggleDiffMode',
      [this.Shortcut.TOGGLE_FILE_REVIEWED]: '_handleToggleFileReviewed',
      [this.Shortcut.EXPAND_ALL_DIFF_CONTEXT]: '_handleExpandAllDiffContext',
      [this.Shortcut.NEXT_UNREVIEWED_FILE]: '_handleNextUnreviewedFile',
      [this.Shortcut.TOGGLE_BLAME]: '_handleToggleBlame',
      [this.Shortcut.TOGGLE_HIDE_ALL_COMMENT_THREADS]:
          '_handleToggleHideAllCommentThreads',
      [this.Shortcut.DIFF_AGAINST_BASE]: '_handleDiffAgainstBase',
      [this.Shortcut.DIFF_AGAINST_LATEST]: '_handleDiffAgainstLatest',
      [this.Shortcut.DIFF_BASE_AGAINST_LEFT]: '_handleDiffBaseAgainstLeft',
      [this.Shortcut.DIFF_RIGHT_AGAINST_LATEST]:
        '_handleDiffRightAgainstLatest',
      [this.Shortcut.DIFF_BASE_AGAINST_LATEST]:
        '_handleDiffBaseAgainstLatest',

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

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

  /** @override */
  attached() {
    super.attached();
    this._getLoggedIn().then(loggedIn => {
      this._loggedIn = loggedIn;
    });

    this.addEventListener('open-fix-preview',
        this._onOpenFixPreview.bind(this));
    this.$.cursor.push('diffs', this.$.diffHost);

    const onRender = () => {
      this.$.diffHost.removeEventListener('render', onRender);
      this.$.cursor.reInitCursor();
    };
    this.$.diffHost.addEventListener('render', onRender);
  }

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

  _getProjectConfig(project) {
    return this.$.restAPI.getProjectConfig(project).then(
        config => {
          this._projectConfig = config;
        });
  }

  _getChangeDetail(changeNum) {
    return this.$.restAPI.getDiffChangeDetail(changeNum).then(change => {
      this._change = change;
      return change;
    });
  }

  _getChangeEdit(changeNum) {
    return this.$.restAPI.getChangeEdit(this._changeNum);
  }

  _getSortedFileList(files) {
    return files.sortedFileList;
  }

  /**
   * @param {!Object} files
   * @param {string} path
   * @returns {!Gerrit.FileRange}
   */
  _getCurrentFile(files, path) {
    if ([files, path].includes(undefined)) return;
    const fileInfo = files.changeFilesByPath[path];
    const fileRange = {path};
    if (fileInfo && fileInfo.old_path) {
      fileRange.basePath = fileInfo.old_path;
    }
    return fileRange;
  }

  _getFiles(changeNum, patchRangeRecord, changeComments) {
    // Polymer 2: check for undefined
    if ([changeNum, patchRangeRecord, patchRangeRecord.base, changeComments]
        .some(arg => arg === undefined)) {
      return Promise.resolve();
    }

    const patchRange = patchRangeRecord.base;
    return this.$.restAPI.getChangeFiles(
        changeNum, patchRange).then(changeFiles => {
      if (!changeFiles) return;
      const commentedPaths = changeComments.getPaths(patchRange);
      const files = Object.assign({}, changeFiles);
      this.addUnmodifiedFiles(files, commentedPaths);
      this._files = {
        sortedFileList: Object.keys(files).sort(this.specialFilePathCompare),
        changeFilesByPath: files,
      };
    });
  }

  _getDiffPreferences() {
    return this.$.restAPI.getDiffPreferences().then(prefs => {
      this._prefs = prefs;
    });
  }

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

  _getWindowWidth() {
    return window.innerWidth;
  }

  _handleReviewedChange(e) {
    this._setReviewed(dom(e).rootTarget.checked);
  }

  _setReviewed(reviewed) {
    if (this._editMode) { return; }
    this.$.reviewed.checked = reviewed;
    this._saveReviewedState(reviewed).catch(err => {
      this.dispatchEvent(new CustomEvent('show-alert', {
        detail: {message: ERR_REVIEW_STATUS},
        composed: true, bubbles: true,
      }));
      throw err;
    });
  }

  _saveReviewedState(reviewed) {
    return this.$.restAPI.saveFileReviewed(this._changeNum,
        this._patchRange.patchNum, this._path, reviewed);
  }

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

    e.preventDefault();
    this._setReviewed(!this.$.reviewed.checked);
  }

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

    e.preventDefault();
    this.$.diffHost.displayLine = false;
  }

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

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

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

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

  _handlePrevLineOrFileWithComments(e) {
    if (this.shouldSuppressKeyboardShortcut(e)) { return; }
    if (e.detail.keyboardEvent.shiftKey &&
        e.detail.keyboardEvent.keyCode === 75) { // 'K'
      this._moveToPreviousFileWithComment();
      return;
    }
    if (this.modifierPressed(e)) { return; }

    e.preventDefault();
    this.$.diffHost.displayLine = true;
    this.$.cursor.moveUp();
  }

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

    e.preventDefault();
    this.$.cursor.moveToVisibleArea();
  }

  _onOpenFixPreview(e) {
    this.$.applyFixDialog.open(e);
  }

  _handleNextLineOrFileWithComments(e) {
    if (this.shouldSuppressKeyboardShortcut(e)) { return; }
    if (e.detail.keyboardEvent.shiftKey &&
        e.detail.keyboardEvent.keyCode === 74) { // 'J'
      this._moveToNextFileWithComment();
      return;
    }
    if (this.modifierPressed(e)) { return; }

    e.preventDefault();
    this.$.diffHost.displayLine = true;
    this.$.cursor.moveDown();
  }

  _moveToPreviousFileWithComment() {
    if (!this._commentSkips) { return; }

    // If there is no previous diff with comments, then return to the change
    // view.
    if (!this._commentSkips.previous) {
      this._navToChangeView();
      return;
    }

    GerritNav.navigateToDiff(this._change, this._commentSkips.previous,
        this._patchRange.patchNum, this._patchRange.basePatchNum);
  }

  _moveToNextFileWithComment() {
    if (!this._commentSkips) { return; }

    // If there is no next diff with comments, then return to the change view.
    if (!this._commentSkips.next) {
      this._navToChangeView();
      return;
    }

    GerritNav.navigateToDiff(this._change, this._commentSkips.next,
        this._patchRange.patchNum, this._patchRange.basePatchNum);
  }

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

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

    e.preventDefault();
    this._navToFile(this._path, this._fileList, -1);
  }

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

    e.preventDefault();
    this._navToFile(this._path, this._fileList, 1);
  }

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

    e.preventDefault();
    if (e.detail.keyboardEvent.shiftKey) {
      this.$.cursor.moveToNextCommentThread();
    } else {
      if (this.modifierPressed(e)) { return; }
      this.$.cursor.moveToNextChunk(/* opt_clipToTop = */false,
          /* opt_navigateToNextFile = */true);
    }
  }

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

    e.preventDefault();
    if (e.detail.keyboardEvent.shiftKey) {
      this.$.cursor.moveToPreviousCommentThread();
    } else {
      if (this.modifierPressed(e)) { return; }
      this.$.cursor.moveToPreviousChunk();
    }
  }

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

    if (e.detail.keyboardEvent.shiftKey) { // Hide left diff.
      e.preventDefault();
      this.$.diffHost.toggleLeftDiff();
      return;
    }

    if (this.modifierPressed(e)) { return; }

    if (!this._loggedIn) { return; }

    this.set('changeViewState.showReplyDialog', true);
    e.preventDefault();
    this._navToChangeView();
  }

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

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

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

    e.preventDefault();
    this.$.diffPreferencesDialog.open();
  }

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

    e.preventDefault();
    if (this._getDiffViewMode() === DiffViewMode.SIDE_BY_SIDE) {
      this.$.modeSelect.setMode(DiffViewMode.UNIFIED);
    } else {
      this.$.modeSelect.setMode(DiffViewMode.SIDE_BY_SIDE);
    }
  }

  _navToChangeView() {
    if (!this._changeNum || !this._patchRange.patchNum) { return; }
    this._navigateToChange(
        this._change,
        this._patchRange,
        this._change && this._change.revisions);
  }

  _navToFile(path, fileList, direction) {
    const newPath = this._getNavLinkPath(path, fileList, direction);
    if (!newPath) { return; }

    if (newPath.up) {
      this._navigateToChange(
          this._change,
          this._patchRange,
          this._change && this._change.revisions);
      return;
    }

    GerritNav.navigateToDiff(this._change, newPath.path,
        this._patchRange.patchNum, this._patchRange.basePatchNum);
  }

  /**
   * @param {?string} path The path of the current file being shown.
   * @param {!Array<string>} fileList The list of files in this change and
   *     patch range.
   * @param {number} direction Either 1 (next file) or -1 (prev file).
   * @param {(number|boolean)} opt_noUp Whether to return to the change view
   *     when advancing the file goes outside the bounds of fileList.
   *
   * @return {?string} The next URL when proceeding in the specified
   *     direction.
   */
  _computeNavLinkURL(change, path, fileList, direction, opt_noUp) {
    const newPath = this._getNavLinkPath(path, fileList, direction, opt_noUp);
    if (!newPath) { return null; }

    if (newPath.up) {
      return this._getChangePath(
          this._change,
          this._patchRange,
          this._change && this._change.revisions);
    }
    return this._getDiffUrl(this._change, this._patchRange, newPath.path);
  }

  _goToEditFile() {
    // TODO(taoalpha): add a shortcut for editing
    const editUrl = GerritNav.getEditUrlForDiff(
        this._change,
        this._path,
        this._patchRange.patchNum
    );
    return GerritNav.navigateToRelativeUrl(editUrl);
  }

  /**
   * Gives an object representing the target of navigating either left or
   * right through the change. The resulting object will have one of the
   * following forms:
   *   * {path: "<target file path>"} - When another file path should be the
   *     result of the navigation.
   *   * {up: true} - When the result of navigating should go back to the
   *     change view.
   *   * null - When no navigation is possible for the given direction.
   *
   * @param {?string} path The path of the current file being shown.
   * @param {!Array<string>} fileList The list of files in this change and
   *     patch range.
   * @param {number} direction Either 1 (next file) or -1 (prev file).
   * @param {?number|boolean=} opt_noUp Whether to return to the change view
   *     when advancing the file goes outside the bounds of fileList.
   * @return {?Object}
   */
  _getNavLinkPath(path, fileList, direction, opt_noUp) {
    if (!path || !fileList || fileList.length === 0) { return null; }

    let idx = fileList.indexOf(path);
    if (idx === -1) {
      const file = direction > 0 ?
        fileList[0] :
        fileList[fileList.length - 1];
      return {path: file};
    }

    idx += direction;
    // Redirect to the change view if opt_noUp isn’t truthy and idx falls
    // outside the bounds of [0, fileList.length).
    if (idx < 0 || idx > fileList.length - 1) {
      if (opt_noUp) { return null; }
      return {up: true};
    }

    return {path: fileList[idx]};
  }

  _getReviewedFiles(changeNum, patchNum) {
    return this.$.restAPI.getReviewedFiles(changeNum, patchNum)
        .then(files => {
          this._reviewedFiles = new Set(files);
          return this._reviewedFiles;
        });
  }

  _getReviewedStatus(editMode, changeNum, patchNum, path) {
    if (editMode) { return Promise.resolve(false); }
    return this._getReviewedFiles(changeNum, patchNum)
        .then(files => files.has(path));
  }

  _paramsChanged(value) {
    if (value.view !== GerritNav.View.DIFF) { return; }

    if (value.changeNum && value.project) {
      this.$.restAPI.setInProjectLookup(value.changeNum, value.project);
    }

    this.$.diffHost.lineOfInterest = this._getLineOfInterest(this.params);
    this._initCursor(this.params);

    this._changeNum = value.changeNum;
    this.classList.remove('hideComments');
    this._path = value.path;
    this._patchRange = {
      patchNum: value.patchNum,
      basePatchNum: value.basePatchNum || PARENT,
    };

    // NOTE: This may be called before attachment (e.g. while parentElement is
    // null). Fire title-change in an async so that, if attachment to the DOM
    // has been queued, the event can bubble up to the handler in gr-app.
    this.async(() => {
      this.dispatchEvent(new CustomEvent('title-change', {
        detail: {title: this.computeTruncatedPath(this._path)},
        composed: true, bubbles: true,
      }));
    });

    // When navigating away from the page, there is a possibility that the
    // patch number is no longer a part of the URL (say when navigating to
    // the top-level change info view) and therefore undefined in `params`.
    if (!this._patchRange.patchNum) {
      return;
    }

    const promises = [];

    promises.push(this._getDiffPreferences());

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

    promises.push(this._getChangeDetail(this._changeNum).then(change => {
      let commit;
      let baseCommit;
      if (change) {
        for (const commitSha in change.revisions) {
          if (!change.revisions.hasOwnProperty(commitSha)) continue;
          const revision = change.revisions[commitSha];
          const patchNum = revision._number.toString();
          if (patchNum === this._patchRange.patchNum) {
            commit = commitSha;
            const commitObj = revision.commit || {};
            const parents = commitObj.parents || [];
            if (this._patchRange.basePatchNum === PARENT && parents.length) {
              baseCommit = parents[parents.length - 1].commit;
            }
          } else if (patchNum === this._patchRange.basePatchNum) {
            baseCommit = commitSha;
          }
        }
        this._commitRange = {commit, baseCommit};
      }
    }));

    promises.push(this._loadComments());

    promises.push(this._getChangeEdit(this._changeNum));

    this.$.diffHost.cancel();
    this.$.diffHost.clearDiffContent();
    this._loading = true;
    return Promise.all(promises)
        .then(r => {
          const edit = r[4];
          if (edit) {
            this.set('_change.revisions.' + edit.commit.commit, {
              _number: this.EDIT_NAME,
              basePatchNum: edit.base_patch_set_number,
              commit: edit.commit,
            });
          }
          this._loading = false;
          this.$.diffHost.comments = this._commentsForDiff;
          return this.$.diffHost.reload(true);
        })
        .then(() => {
          this.reporting.diffViewFullyLoaded();
          // If diff view displayed has not ended yet, it ends here.
          this.reporting.diffViewDisplayed();
        })
        .then(() => {
          // If the blame was loaded for a previous file and user navigates to
          // another file, then we load the blame for this file too
          if (this._isBlameLoaded) this._loadBlame();
        });
  }

  _changeViewStateChanged(changeViewState) {
    if (changeViewState.diffMode === null) {
      // If screen size is small, always default to unified view.
      this.$.restAPI.getPreferences().then(prefs => {
        this.set('changeViewState.diffMode', prefs.default_diff_view);
      });
    }
  }

  _setReviewedObserver(_loggedIn, paramsRecord, _prefs) {
    // Polymer 2: check for undefined
    if ([_loggedIn, paramsRecord, _prefs].includes(undefined)) {
      return;
    }

    const params = paramsRecord.base || {};
    if (!_loggedIn) { return; }

    if (_prefs.manual_review) {
      // Checkbox state needs to be set explicitly only when manual_review
      // is specified.
      this._getReviewedStatus(this.editMode, this._changeNum,
          this._patchRange.patchNum, this._path).then(status => {
        this.$.reviewed.checked = status;
      });
      return;
    }

    if (params.view === GerritNav.View.DIFF) {
      this._setReviewed(true);
    }
  }

  /**
   * If the params specify a diff address then configure the diff cursor.
   */
  _initCursor(params) {
    if (params.lineNum === undefined) { return; }
    if (params.leftSide) {
      this.$.cursor.side = DiffSides.LEFT;
    } else {
      this.$.cursor.side = DiffSides.RIGHT;
    }
    this.$.cursor.initialLineNumber = params.lineNum;
  }

  _getLineOfInterest(params) {
    // If there is a line number specified, pass it along to the diff so that
    // it will not get collapsed.
    if (!params.lineNum) { return null; }
    return {number: params.lineNum, leftSide: params.leftSide};
  }

  _pathChanged(path) {
    if (path) {
      this.dispatchEvent(new CustomEvent('title-change', {
        detail: {title: this.computeTruncatedPath(path)},
        composed: true, bubbles: true,
      }));
    }

    if (this._fileList.length == 0) { return; }

    this.set('changeViewState.selectedFileIndex',
        this._fileList.indexOf(path));
  }

  _getDiffUrl(change, patchRange, path) {
    if ([change, patchRange, path].includes(undefined)) {
      return '';
    }
    return GerritNav.getUrlForDiff(change, path, patchRange.patchNum,
        patchRange.basePatchNum);
  }

  _patchRangeStr(patchRange) {
    let patchStr = patchRange.patchNum;
    if (patchRange.basePatchNum != null &&
        patchRange.basePatchNum != PARENT) {
      patchStr = patchRange.basePatchNum + '..' + patchRange.patchNum;
    }
    return patchStr;
  }

  /**
   * When the latest patch of the change is selected (and there is no base
   * patch) then the patch range need not appear in the URL. Return a patch
   * range object with undefined values when a range is not needed.
   *
   * @param {!Object} patchRange
   * @param {!Object} revisions
   * @return {!Object}
   */
  _getChangeUrlRange(patchRange, revisions) {
    let patchNum = undefined;
    let basePatchNum = undefined;
    let latestPatchNum = -1;
    for (const rev of Object.values(revisions || {})) {
      latestPatchNum = Math.max(latestPatchNum, rev._number);
    }
    if (patchRange.basePatchNum !== PARENT ||
        parseInt(patchRange.patchNum, 10) !== latestPatchNum) {
      patchNum = patchRange.patchNum;
      basePatchNum = patchRange.basePatchNum;
    }
    return {patchNum, basePatchNum};
  }

  _getChangePath(change, patchRange, revisions) {
    if ([change, patchRange].includes(undefined)) {
      return '';
    }
    const range = this._getChangeUrlRange(patchRange, revisions);
    return GerritNav.getUrlForChange(change, range.patchNum,
        range.basePatchNum);
  }

  _navigateToChange(change, patchRange, revisions) {
    const range = this._getChangeUrlRange(patchRange, revisions);
    GerritNav.navigateToChange(change, range.patchNum, range.basePatchNum);
  }

  _computeChangePath(change, patchRangeRecord, revisions) {
    return this._getChangePath(change, patchRangeRecord.base, revisions);
  }

  _formatFilesForDropdown(files, patchNum, changeComments) {
    // Polymer 2: check for undefined
    if ([
      files,
      patchNum,
      changeComments,
    ].includes(undefined)) {
      return;
    }

    if (!files) { return; }
    const dropdownContent = [];
    for (const path of files.sortedFileList) {
      dropdownContent.push({
        text: this.computeDisplayPath(path),
        mobileText: this.computeTruncatedPath(path),
        value: path,
        bottomText: this._computeCommentString(changeComments, patchNum,
            path, files.changeFilesByPath[path]),
      });
    }
    return dropdownContent;
  }

  _computeCommentString(changeComments, patchNum, path, changeFileInfo) {
    const unresolvedCount = changeComments.computeUnresolvedNum({patchNum,
      path});
    const commentCount = changeComments.computeCommentCount({patchNum, path});
    const commentString = GrCountStringFormatter.computePluralString(
        commentCount, 'comment');
    const unresolvedString = GrCountStringFormatter.computeString(
        unresolvedCount, 'unresolved');

    const unmodifiedString = changeFileInfo.status === 'U' ? 'no changes': '';

    return [
      unmodifiedString,
      commentString,
      unresolvedString]
        .filter(v => v && v.length > 0).join(', ');
  }

  _computePrefsButtonHidden(prefs, prefsDisabled) {
    return prefsDisabled || !prefs;
  }

  _handleFileChange(e) {
    // This is when it gets set initially.
    const path = e.detail.value;
    if (path === this._path) {
      return;
    }

    GerritNav.navigateToDiff(this._change, path, this._patchRange.patchNum,
        this._patchRange.basePatchNum);
  }

  _handleFileTap(e) {
    // async is needed so that that the click event is fired before the
    // dropdown closes (This was a bug for touch devices).
    this.async(() => {
      this.$.dropdown.close();
    }, 1);
  }

  _handlePatchChange(e) {
    const {basePatchNum, patchNum} = e.detail;
    if (this.patchNumEquals(basePatchNum, this._patchRange.basePatchNum) &&
        this.patchNumEquals(patchNum, this._patchRange.patchNum)) { return; }
    GerritNav.navigateToDiff(
        this._change, this._path, patchNum, basePatchNum);
  }

  _handlePrefsTap(e) {
    e.preventDefault();
    this.$.diffPreferencesDialog.open();
  }

  /**
   * _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 or they
   * are on a mobile device. If the user navigates up to the change view, it
   * should clear this choice and revert to the preference the next time a
   * diff is viewed.
   *
   * Use side-by-side if the user is not logged in.
   *
   * @return {string}
   */
  _getDiffViewMode() {
    if (this.changeViewState.diffMode) {
      return this.changeViewState.diffMode;
    } else if (this._userPrefs) {
      this.set('changeViewState.diffMode', this._userPrefs.default_diff_view);
      return this._userPrefs.default_diff_view;
    } else {
      return 'SIDE_BY_SIDE';
    }
  }

  _computeModeSelectHideClass(_diff) {
    return _diff.binary ? 'hide' : '';
  }

  _onLineSelected(e, detail) {
    if (!this._change) { return; }
    const cursorAddress = this.$.cursor.getAddress();
    const number = cursorAddress ? cursorAddress.number : undefined;
    const leftSide = cursorAddress ? cursorAddress.leftSide : undefined;
    const url = GerritNav.getUrlForDiffById(this._changeNum,
        this._change.project, this._path, this._patchRange.patchNum,
        this._patchRange.basePatchNum, number, leftSide);
    history.replaceState(null, '', url);
  }

  _computeDownloadDropdownLinks(
      project, changeNum, patchRange, path, diff) {
    if (!patchRange || !patchRange.patchNum) { return []; }

    const links = [
      {
        url: this._computeDownloadPatchLink(
            project, changeNum, patchRange, path),
        name: 'Patch',
      },
    ];

    if (diff && diff.meta_a) {
      let leftPath = path;
      if (diff.change_type === 'RENAMED') {
        leftPath = diff.meta_a.name;
      }
      links.push(
          {
            url: this._computeDownloadFileLink(
                project, changeNum, patchRange, leftPath, true),
            name: 'Left Content',
          }
      );
    }

    if (diff && diff.meta_b) {
      links.push(
          {
            url: this._computeDownloadFileLink(
                project, changeNum, patchRange, path, false),
            name: 'Right Content',
          }
      );
    }

    return links;
  }

  _computeDownloadFileLink(
      project, changeNum, patchRange, path, isBase) {
    let patchNum = patchRange.patchNum;

    const comparedAgainsParent = patchRange.basePatchNum === 'PARENT';

    if (isBase && !comparedAgainsParent) {
      patchNum = patchRange.basePatchNum;
    }

    let url = this.changeBaseURL(project, changeNum, patchNum) +
        `/files/${encodeURIComponent(path)}/download`;

    if (isBase && comparedAgainsParent) {
      url += '?parent=1';
    }

    return url;
  }

  _computeDownloadPatchLink(project, changeNum, patchRange, path) {
    let url = this.changeBaseURL(project, changeNum, patchRange.patchNum);
    url += '/patch?zip&path=' + encodeURIComponent(path);
    return url;
  }

  _loadComments() {
    return this.$.commentAPI.loadAll(this._changeNum).then(comments => {
      this._changeComments = comments;
      this._commentMap = this._getPaths(this._patchRange);

      this._commentsForDiff = this._getCommentsForPath(this._path,
          this._patchRange, this._projectConfig);
    });
  }

  _recomputeComments(files, path, patchRange, projectConfig) {
    // Polymer 2: check for undefined
    if ([
      files,
      path,
      patchRange,
      projectConfig,
    ].includes(undefined)) {
      return undefined;
    }

    const file = files[path];
    if (file && file.old_path) {
      this._commentsForDiff = this._changeComments.getCommentsBySideForFile(
          {path, basePath: file.old_path},
          patchRange,
          projectConfig);

      this.$.diffHost.comments = this._commentsForDiff;
    }
  }

  _getPaths(patchRange) {
    return this._changeComments.getPaths(patchRange);
  }

  _getCommentsForPath(path, patchRange, projectConfig) {
    return this._changeComments.getCommentsBySideForPath(path, patchRange,
        projectConfig);
  }

  _getDiffDrafts() {
    return this.$.restAPI.getDiffDrafts(this._changeNum);
  }

  _computeCommentSkips(commentMap, fileList, path) {
    // Polymer 2: check for undefined
    if ([
      commentMap,
      fileList,
      path,
    ].includes(undefined)) {
      return undefined;
    }

    const skips = {previous: null, next: null};
    if (!fileList.length) { return skips; }
    const pathIndex = fileList.indexOf(path);

    // Scan backward for the previous file.
    for (let i = pathIndex - 1; i >= 0; i--) {
      if (commentMap[fileList[i]]) {
        skips.previous = fileList[i];
        break;
      }
    }

    // Scan forward for the next file.
    for (let i = pathIndex + 1; i < fileList.length; i++) {
      if (commentMap[fileList[i]]) {
        skips.next = fileList[i];
        break;
      }
    }

    return skips;
  }

  _computeDiffClass(panelFloatingDisabled) {
    if (panelFloatingDisabled) {
      return 'noOverflow';
    }
  }

  /**
   * @param {!Object} patchRangeRecord
   */
  _computeEditMode(patchRangeRecord) {
    const patchRange = patchRangeRecord.base || {};
    return this.patchNumEquals(patchRange.patchNum, this.EDIT_NAME);
  }

  /**
   * @param {boolean} editMode
   */
  _computeContainerClass(editMode) {
    return editMode ? 'editMode' : '';
  }

  _computeBlameToggleLabel(loaded, loading) {
    if (loaded) { return 'Hide blame'; }
    return 'Show blame';
  }

  _loadBlame() {
    this._isBlameLoading = true;
    this.dispatchEvent(new CustomEvent('show-alert', {
      detail: {message: MSG_LOADING_BLAME},
      composed: true, bubbles: true,
    }));
    this.$.diffHost.loadBlame()
        .then(() => {
          this._isBlameLoading = false;
          this.dispatchEvent(new CustomEvent('show-alert', {
            detail: {message: MSG_LOADED_BLAME},
            composed: true, bubbles: true,
          }));
        })
        .catch(() => {
          this._isBlameLoading = false;
        });
  }

  /**
   * Load and display blame information if it has not already been loaded.
   * Otherwise hide it.
   */
  _toggleBlame() {
    if (this._isBlameLoaded) {
      this.$.diffHost.clearBlame();
      return;
    }
    this._loadBlame();
  }

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

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

  _handleDiffAgainstBase(e) {
    if (this.shouldSuppressKeyboardShortcut(e)) { return; }
    if (this.patchNumEquals(this._patchRange.basePatchNum, 'PARENT')) {
      this.dispatchEvent(new CustomEvent('show-alert', {
        detail: {
          message: 'Base is already selected.',
        },
        composed: true, bubbles: true,
      }));
      return;
    }
    GerritNav.navigateToDiff(
        this._change, this._path, this._patchRange.patchNum);
  }

  _handleDiffBaseAgainstLeft(e) {
    if (this.shouldSuppressKeyboardShortcut(e)) { return; }
    if (this.patchNumEquals(this._patchRange.basePatchNum, 'PARENT')) {
      this.dispatchEvent(new CustomEvent('show-alert', {
        detail: {
          message: 'Left is already base.',
        },
        composed: true, bubbles: true,
      }));
      return;
    }
    GerritNav.navigateToDiff(this._change, this._path,
        this._patchRange.basePatchNum);
  }

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

    const latestPatchNum = this.computeLatestPatchNum(this._allPatchSets);
    if (this.patchNumEquals(this._patchRange.patchNum, latestPatchNum)) {
      this.dispatchEvent(new CustomEvent('show-alert', {
        detail: {
          message: 'Latest is already selected.',
        },
        composed: true, bubbles: true,
      }));
      return;
    }

    GerritNav.navigateToDiff(
        this._change, this._path, latestPatchNum,
        this._patchRange.basePatchNum);
  }

  _handleDiffRightAgainstLatest(e) {
    if (this.shouldSuppressKeyboardShortcut(e)) { return; }
    const latestPatchNum = this.computeLatestPatchNum(this._allPatchSets);
    if (this.patchNumEquals(this._patchRange.patchNum, latestPatchNum)) {
      this.dispatchEvent(new CustomEvent('show-alert', {
        detail: {
          message: 'Right is already latest.',
        },
        composed: true, bubbles: true,
      }));
      return;
    }
    GerritNav.navigateToDiff(this._change, this._path, latestPatchNum,
        this._patchRange.patchNum);
  }

  _handleDiffBaseAgainstLatest(e) {
    if (this.shouldSuppressKeyboardShortcut(e)) { return; }
    const latestPatchNum = this.computeLatestPatchNum(this._allPatchSets);
    if (this.patchNumEquals(this._patchRange.patchNum, latestPatchNum) &&
      this.patchNumEquals(this._patchRange.basePatchNum, 'PARENT')) {
      this.dispatchEvent(new CustomEvent('show-alert', {
        detail: {
          message: 'Already diffing base against latest.',
        },
        composed: true, bubbles: true,
      }));
      return;
    }
    GerritNav.navigateToDiff(this._change, this._path, latestPatchNum);
  }

  _computeBlameLoaderClass(isImageDiff, path) {
    return !this.isMagicPath(path) && !isImageDiff ? 'show' : '';
  }

  _getRevisionInfo(change) {
    return new RevisionInfo(change);
  }

  _computeFileNum(file, files) {
    // Polymer 2: check for undefined
    if ([file, files].includes(undefined)) {
      return undefined;
    }

    return files.findIndex(({value}) => value === file) + 1;
  }

  /**
   * @param {number} fileNum
   * @param {!Array<string>} files
   * @return {string}
   */
  _computeFileNumClass(fileNum, files) {
    if (files && fileNum > 0) {
      return 'show';
    }
    return '';
  }

  _handleExpandAllDiffContext(e) {
    if (this.shouldSuppressKeyboardShortcut(e)) { return; }
    this.$.diffHost.expandAllContext();
  }

  _computeDiffPrefsDisabled(disableDiffPrefs, loggedIn) {
    return disableDiffPrefs || !loggedIn;
  }

  _handleNextUnreviewedFile(e) {
    if (this.shouldSuppressKeyboardShortcut(e)) { return; }
    this._setReviewed(true);
    // Ensure that the currently viewed file always appears in unreviewedFiles
    // so we resolve the right "next" file.
    const unreviewedFiles = this._fileList
        .filter(file =>
          (file === this._path || !this._reviewedFiles.has(file)));
    this._navToFile(this._path, unreviewedFiles, 1);
  }

  _handleReloadingDiffPreference() {
    this._getDiffPreferences();
  }

  _onChangeHeaderPanelHeightChanged(e) {
    this._scrollTopMargin = e.detail.value;
  }

  _computeCanEdit(loggedIn, changeChangeRecord) {
    if ([changeChangeRecord, changeChangeRecord.base]
        .some(arg => arg === undefined)) {
      return false;
    }
    return loggedIn && this.changeIsOpen(changeChangeRecord.base);
  }
}

customElements.define(GrDiffView.is, GrDiffView);
