/**
 * @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 '../../../scripts/bundled-polymer.js';

import '../../../behaviors/fire-behavior/fire-behavior.js';
import '../../../behaviors/gr-patch-set-behavior/gr-patch-set-behavior.js';
import '../../../behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior.js';
import '../../../behaviors/rest-client-behavior/rest-client-behavior.js';
import '@polymer/paper-tabs/paper-tabs.js';
import '../../../styles/shared-styles.js';
import '../../core/gr-navigation/gr-navigation.js';
import '../../core/gr-reporting/gr-reporting.js';
import '../../diff/gr-comment-api/gr-comment-api.js';
import '../../edit/gr-edit-constants.js';
import '../../plugins/gr-endpoint-decorator/gr-endpoint-decorator.js';
import '../../plugins/gr-endpoint-param/gr-endpoint-param.js';
import '../../shared/gr-account-link/gr-account-link.js';
import '../../shared/gr-button/gr-button.js';
import '../../shared/gr-change-star/gr-change-star.js';
import '../../shared/gr-change-status/gr-change-status.js';
import '../../shared/gr-count-string-formatter/gr-count-string-formatter.js';
import '../../shared/gr-date-formatter/gr-date-formatter.js';
import '../../shared/gr-editable-content/gr-editable-content.js';
import '../../shared/gr-js-api-interface/gr-js-api-interface.js';
import '../../shared/gr-linked-text/gr-linked-text.js';
import '../../shared/gr-overlay/gr-overlay.js';
import '../../shared/gr-rest-api-interface/gr-rest-api-interface.js';
import '../../shared/gr-tooltip-content/gr-tooltip-content.js';
import '../../shared/revision-info/revision-info.js';
import '../gr-change-actions/gr-change-actions.js';
import '../gr-change-metadata/gr-change-metadata.js';
import '../../shared/gr-icons/gr-icons.js';
import '../gr-commit-info/gr-commit-info.js';
import '../gr-download-dialog/gr-download-dialog.js';
import '../gr-file-list-header/gr-file-list-header.js';
import '../gr-file-list/gr-file-list.js';
import '../gr-included-in-dialog/gr-included-in-dialog.js';
import '../gr-messages-list/gr-messages-list.js';
import '../gr-related-changes-list/gr-related-changes-list.js';
import '../../diff/gr-apply-fix-dialog/gr-apply-fix-dialog.js';
import '../gr-reply-dialog/gr-reply-dialog.js';
import '../gr-thread-list/gr-thread-list.js';
import '../gr-upload-help-dialog/gr-upload-help-dialog.js';
import {flush} from '@polymer/polymer/lib/legacy/polymer.dom.js';
import {beforeNextRender} from '@polymer/polymer/lib/utils/render-status.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-change-view_html.js';

const CHANGE_ID_ERROR = {
  MISMATCH: 'mismatch',
  MISSING: 'missing',
};
const CHANGE_ID_REGEX_PATTERN = /^Change-Id\:\s(I[0-9a-f]{8,40})/gm;

const MIN_LINES_FOR_COMMIT_COLLAPSE = 30;
const DEFAULT_NUM_FILES_SHOWN = 200;

const REVIEWERS_REGEX = /^(R|CC)=/gm;
const MIN_CHECK_INTERVAL_SECS = 0;

// These are the same as the breakpoint set in CSS. Make sure both are changed
// together.
const BREAKPOINT_RELATED_SMALL = '50em';
const BREAKPOINT_RELATED_MED = '75em';

// In the event that the related changes medium width calculation is too close
// to zero, provide some height.
const MINIMUM_RELATED_MAX_HEIGHT = 100;

const SMALL_RELATED_HEIGHT = 400;

const REPLY_REFIT_DEBOUNCE_INTERVAL_MS = 500;

const TRAILING_WHITESPACE_REGEX = /[ \t]+$/gm;

const MSG_PREFIX = '#message-';

const ReloadToastMessage = {
  NEWER_REVISION: 'A newer patch set has been uploaded',
  RESTORED: 'This change has been restored',
  ABANDONED: 'This change has been abandoned',
  MERGED: 'This change has been merged',
  NEW_MESSAGE: 'There are new messages on this change',
};

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

const CommentTabs = {
  CHANGE_LOG: 0,
  COMMENT_THREADS: 1,
  ROBOT_COMMENTS: 2,
};

const CHANGE_DATA_TIMING_LABEL = 'ChangeDataLoaded';
const CHANGE_RELOAD_TIMING_LABEL = 'ChangeReloaded';
const SEND_REPLY_TIMING_LABEL = 'SendReply';
// Making the tab names more unique in case a plugin adds one with same name
const FILES_TAB_NAME = '__gerrit_internal_files';
const FINDINGS_TAB_NAME = '__gerrit_internal_findings';
const ROBOT_COMMENTS_LIMIT = 10;

/**
 * @appliesMixin Gerrit.FireMixin
 * @appliesMixin Gerrit.KeyboardShortcutMixin
 * @appliesMixin Gerrit.PatchSetMixin
 * @appliesMixin Gerrit.RESTClientMixin
 * @extends Polymer.Element
 */
class GrChangeView extends mixinBehaviors( [
  Gerrit.FireBehavior,
  Gerrit.KeyboardShortcutBehavior,
  Gerrit.PatchSetBehavior,
  Gerrit.RESTClientBehavior,
], GestureEventListeners(
    LegacyElementMixin(
        PolymerElement))) {
  static get template() { return htmlTemplate; }

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

  /**
   * Fired if an error occurs when fetching the change data.
   *
   * @event page-error
   */

  /**
   * Fired if being logged in is required.
   *
   * @event show-auth-required
   */

  static get properties() {
    return {
    /**
     * URL params passed from the router.
     */
      params: {
        type: Object,
        observer: '_paramsChanged',
      },
      /** @type {?} */
      viewState: {
        type: Object,
        notify: true,
        value() { return {}; },
        observer: '_viewStateChanged',
      },
      backPage: String,
      hasParent: Boolean,
      keyEventTarget: {
        type: Object,
        value() { return document.body; },
      },
      disableEdit: {
        type: Boolean,
        value: false,
      },
      disableDiffPrefs: {
        type: Boolean,
        value: false,
      },
      _diffPrefsDisabled: {
        type: Boolean,
        computed: '_computeDiffPrefsDisabled(disableDiffPrefs, _loggedIn)',
      },
      _commentThreads: Array,
      // TODO(taoalpha): Consider replacing diffDrafts
      // with _draftCommentThreads everywhere, currently only
      // replaced in reply-dialoig
      _draftCommentThreads: {
        type: Array,
      },
      _robotCommentThreads: {
        type: Array,
        computed: '_computeRobotCommentThreads(_commentThreads,'
          + ' _currentRobotCommentsPatchSet, _showAllRobotComments)',
      },
      /** @type {?} */
      _serverConfig: {
        type: Object,
        observer: '_startUpdateCheckTimer',
      },
      _diffPrefs: Object,
      _numFilesShown: {
        type: Number,
        value: DEFAULT_NUM_FILES_SHOWN,
        observer: '_numFilesShownChanged',
      },
      _account: {
        type: Object,
        value: {},
      },
      _prefs: Object,
      /** @type {?} */
      _changeComments: Object,
      _canStartReview: {
        type: Boolean,
        computed: '_computeCanStartReview(_change)',
      },
      _comments: Object,
      /** @type {?} */
      _change: {
        type: Object,
        observer: '_changeChanged',
      },
      _revisionInfo: {
        type: Object,
        computed: '_getRevisionInfo(_change)',
      },
      /** @type {?} */
      _commitInfo: Object,
      _currentRevision: {
        type: Object,
        computed: '_computeCurrentRevision(_change.current_revision, ' +
          '_change.revisions)',
        observer: '_handleCurrentRevisionUpdate',
      },
      _files: Object,
      _changeNum: String,
      _diffDrafts: {
        type: Object,
        value() { return {}; },
      },
      _editingCommitMessage: {
        type: Boolean,
        value: false,
      },
      _hideEditCommitMessage: {
        type: Boolean,
        computed: '_computeHideEditCommitMessage(_loggedIn, ' +
            '_editingCommitMessage, _change, _editMode, _commitCollapsed, ' +
            '_commitCollapsible)',
      },
      _diffAgainst: String,
      /** @type {?string} */
      _latestCommitMessage: {
        type: String,
        value: '',
      },
      _commentTabs: {
        type: Object,
        value: CommentTabs,
      },
      _lineHeight: Number,
      _changeIdCommitMessageError: {
        type: String,
        computed:
        '_computeChangeIdCommitMessageError(_latestCommitMessage, _change)',
      },
      /** @type {?} */
      _patchRange: {
        type: Object,
      },
      _filesExpanded: String,
      _basePatchNum: String,
      _selectedRevision: Object,
      _currentRevisionActions: Object,
      _allPatchSets: {
        type: Array,
        computed: 'computeAllPatchSets(_change, _change.revisions.*)',
      },
      _loggedIn: {
        type: Boolean,
        value: false,
      },
      _loading: Boolean,
      /** @type {?} */
      _projectConfig: Object,
      _replyButtonLabel: {
        type: String,
        value: 'Reply',
        computed: '_computeReplyButtonLabel(_diffDrafts.*, _canStartReview)',
      },
      _selectedPatchSet: String,
      _shownFileCount: Number,
      _initialLoadComplete: {
        type: Boolean,
        value: false,
      },
      _replyDisabled: {
        type: Boolean,
        value: true,
        computed: '_computeReplyDisabled(_serverConfig)',
      },
      _changeStatus: {
        type: String,
        computed: 'changeStatusString(_change)',
      },
      _changeStatuses: {
        type: String,
        computed:
        '_computeChangeStatusChips(_change, _mergeable, _submitEnabled)',
      },
      /** If false, then the "Show more" button was used to expand. */
      _commitCollapsed: {
        type: Boolean,
        value: true,
      },
      /** Is the "Show more/less" button visible? */
      _commitCollapsible: {
        type: Boolean,
        computed: '_computeCommitCollapsible(_latestCommitMessage)',
      },
      _relatedChangesCollapsed: {
        type: Boolean,
        value: true,
      },
      /** @type {?number} */
      _updateCheckTimerHandle: Number,
      _editMode: {
        type: Boolean,
        computed: '_computeEditMode(_patchRange.*, params.*)',
      },
      _showRelatedToggle: {
        type: Boolean,
        value: false,
        observer: '_updateToggleContainerClass',
      },
      _parentIsCurrent: {
        type: Boolean,
        computed: '_isParentCurrent(_currentRevisionActions)',
      },
      _submitEnabled: {
        type: Boolean,
        computed: '_isSubmitEnabled(_currentRevisionActions)',
      },

      /** @type {?} */
      _mergeable: {
        type: Boolean,
        value: undefined,
      },
      _currentView: {
        type: Number,
        value: CommentTabs.CHANGE_LOG,
      },
      _showFileTabContent: {
        type: Boolean,
        value: true,
      },
      /** @type {Array<string>} */
      _dynamicTabHeaderEndpoints: {
        type: Array,
      },
      /** @type {Array<string>} */
      _dynamicTabContentEndpoints: {
        type: Array,
      },
      // The dynamic content of the plugin added tab
      _selectedTabPluginEndpoint: {
        type: String,
      },
      // The dynamic heading of the plugin added tab
      _selectedTabPluginHeader: {
        type: String,
      },
      _robotCommentsPatchSetDropdownItems: {
        type: Array,
        value() { return []; },
        computed: '_computeRobotCommentsPatchSetDropdownItems(_change, ' +
          '_commentThreads)',
      },
      _currentRobotCommentsPatchSet: {
        type: Number,
      },
      _files_tab_name: {
        type: String,
        value: FILES_TAB_NAME,
      },
      _findings_tab_name: {
        type: String,
        value: FINDINGS_TAB_NAME,
      },
      _currentTabName: {
        type: String,
        value: FILES_TAB_NAME,
      },
      _showAllRobotComments: {
        type: Boolean,
        value: false,
      },
      _showRobotCommentsButton: {
        type: Boolean,
        value: false,
      },
    };
  }

  static get observers() {
    return [
      '_labelsChanged(_change.labels.*)',
      '_paramsAndChangeChanged(params, _change)',
      '_patchNumChanged(_patchRange.patchNum)',
    ];
  }

  keyboardShortcuts() {
    return {
      [this.Shortcut.SEND_REPLY]: null, // DOC_ONLY binding
      [this.Shortcut.EMOJI_DROPDOWN]: null, // DOC_ONLY binding
      [this.Shortcut.REFRESH_CHANGE]: '_handleRefreshChange',
      [this.Shortcut.OPEN_REPLY_DIALOG]: '_handleOpenReplyDialog',
      [this.Shortcut.OPEN_DOWNLOAD_DIALOG]:
          '_handleOpenDownloadDialogShortcut',
      [this.Shortcut.TOGGLE_DIFF_MODE]: '_handleToggleDiffMode',
      [this.Shortcut.TOGGLE_CHANGE_STAR]: '_handleToggleChangeStar',
      [this.Shortcut.UP_TO_DASHBOARD]: '_handleUpToDashboard',
      [this.Shortcut.EXPAND_ALL_MESSAGES]: '_handleExpandAllMessages',
      [this.Shortcut.COLLAPSE_ALL_MESSAGES]: '_handleCollapseAllMessages',
      [this.Shortcut.OPEN_DIFF_PREFS]: '_handleOpenDiffPrefsShortcut',
      [this.Shortcut.EDIT_TOPIC]: '_handleEditTopic',
    };
  }

  /** @override */
  created() {
    super.created();

    this.addEventListener('topic-changed',
        () => this._handleTopicChanged());

    this.addEventListener(
        // When an overlay is opened in a mobile viewport, the overlay has a full
        // screen view. When it has a full screen view, we do not want the
        // background to be scrollable. This will eliminate background scroll by
        // hiding most of the contents on the screen upon opening, and showing
        // again upon closing.
        'fullscreen-overlay-opened',
        () => this._handleHideBackgroundContent());

    this.addEventListener('fullscreen-overlay-closed',
        () => this._handleShowBackgroundContent());

    this.addEventListener('diff-comments-modified',
        () => this._handleReloadCommentThreads());
  }

  /** @override */
  attached() {
    super.attached();
    this._getServerConfig().then(config => {
      this._serverConfig = config;
    });

    this._getLoggedIn().then(loggedIn => {
      this._loggedIn = loggedIn;
      if (loggedIn) {
        this.$.restAPI.getAccount().then(acct => {
          this._account = acct;
        });
      }
      this._setDiffViewMode();
    });

    Gerrit.awaitPluginsLoaded()
        .then(() => {
          this._dynamicTabHeaderEndpoints =
          Gerrit._endpoints.getDynamicEndpoints('change-view-tab-header');
          this._dynamicTabContentEndpoints =
          Gerrit._endpoints.getDynamicEndpoints('change-view-tab-content');
          if (this._dynamicTabContentEndpoints.length !==
          this._dynamicTabHeaderEndpoints.length) {
            console.warn('Different number of tab headers and tab content.');
          }
        })
        .then(() => this._setPrimaryTab());

    this.addEventListener('comment-save', this._handleCommentSave.bind(this));
    this.addEventListener('comment-refresh', this._reloadDrafts.bind(this));
    this.addEventListener('comment-discard',
        this._handleCommentDiscard.bind(this));
    this.addEventListener('change-message-deleted',
        () => this._reload());
    this.addEventListener('editable-content-save',
        this._handleCommitMessageSave.bind(this));
    this.addEventListener('editable-content-cancel',
        this._handleCommitMessageCancel.bind(this));
    this.addEventListener('open-fix-preview',
        this._onOpenFixPreview.bind(this));
    this.addEventListener('close-fix-preview',
        this._onCloseFixPreview.bind(this));
    this.listen(window, 'scroll', '_handleScroll');
    this.listen(document, 'visibilitychange', '_handleVisibilityChange');
  }

  /** @override */
  detached() {
    super.detached();
    this.unlisten(window, 'scroll', '_handleScroll');
    this.unlisten(document, 'visibilitychange', '_handleVisibilityChange');

    if (this._updateCheckTimerHandle) {
      this._cancelUpdateCheckTimer();
    }
  }

  get messagesList() {
    return this.shadowRoot.querySelector('gr-messages-list');
  }

  get threadList() {
    return this.shadowRoot.querySelector('gr-thread-list');
  }

  /**
   * @param {boolean=} opt_reset
   */
  _setDiffViewMode(opt_reset) {
    if (!opt_reset && this.viewState.diffViewMode) { return; }

    return this._getPreferences()
        .then( prefs => {
          if (!this.viewState.diffMode) {
            this.set('viewState.diffMode', prefs.default_diff_view);
          }
        })
        .then(() => {
          if (!this.viewState.diffMode) {
            this.set('viewState.diffMode', 'SIDE_BY_SIDE');
          }
        });
  }

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

  _onCloseFixPreview(e) {
    this._reload();
  }

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

    e.preventDefault();
    if (this.viewState.diffMode === DiffViewMode.SIDE_BY_SIDE) {
      this.$.fileListHeader.setDiffViewMode(DiffViewMode.UNIFIED);
    } else {
      this.$.fileListHeader.setDiffViewMode(DiffViewMode.SIDE_BY_SIDE);
    }
  }

  _handleCommentTabChange() {
    this._currentView = this.$.commentTabs.selected;
    const type = Object.keys(CommentTabs).find(key => CommentTabs[key] ===
        this._currentView);
    this.$.reporting.reportInteraction('comment-tab-changed', {tabName:
        type});
  }

  _isSelectedView(currentView, view) {
    return currentView === view;
  }

  _findIfTabMatches(currentTab, tab) {
    return currentTab === tab;
  }

  _handleFileTabChange(e) {
    const selectedIndex = e.target.selected;
    const tabs = e.target.querySelectorAll('paper-tab');
    this._currentTabName = tabs[selectedIndex] &&
      tabs[selectedIndex].dataset.name;
    const source = e && e.type ? e.type : '';
    const pluginIndex = (this._dynamicTabHeaderEndpoints || []).indexOf(
        this._currentTabName);
    if (pluginIndex !== -1) {
      this._selectedTabPluginEndpoint = this._dynamicTabContentEndpoints[
          pluginIndex];
      this._selectedTabPluginHeader = this._dynamicTabHeaderEndpoints[
          pluginIndex];
    } else {
      this._selectedTabPluginEndpoint = '';
      this._selectedTabPluginHeader = '';
    }
    this.$.reporting.reportInteraction('tab-changed',
        {tabName: this._currentTabName, source});
  }

  _handleShowTab(e) {
    const primaryTabs = this.shadowRoot.querySelector('#primaryTabs');
    const tabs = primaryTabs.querySelectorAll('paper-tab');
    let idx = -1;
    tabs.forEach((tab, index) => {
      if (tab.dataset.name === e.detail.tab) idx = index;
    });
    if (idx === -1) {
      console.error(e.detail.tab + ' tab not found');
      return;
    }
    primaryTabs.selected = idx;
    primaryTabs.scrollIntoView();
    this.$.reporting.reportInteraction('show-tab', {tabName: e.detail.tab});
  }

  _handleEditCommitMessage(e) {
    this._editingCommitMessage = true;
    this.$.commitMessageEditor.focusTextarea();
  }

  _handleCommitMessageSave(e) {
    // Trim trailing whitespace from each line.
    const message = e.detail.content.replace(TRAILING_WHITESPACE_REGEX, '');

    this.$.jsAPI.handleCommitMessage(this._change, message);

    this.$.commitMessageEditor.disabled = true;
    this.$.restAPI.putChangeCommitMessage(
        this._changeNum, message).then(resp => {
      this.$.commitMessageEditor.disabled = false;
      if (!resp.ok) { return; }

      this._latestCommitMessage = this._prepareCommitMsgForLinkify(
          message);
      this._editingCommitMessage = false;
      this._reloadWindow();
    })
        .catch(err => {
          this.$.commitMessageEditor.disabled = false;
        });
  }

  _reloadWindow() {
    window.location.reload();
  }

  _handleCommitMessageCancel(e) {
    this._editingCommitMessage = false;
  }

  _computeChangeStatusChips(change, mergeable, submitEnabled) {
    // Polymer 2: check for undefined
    if ([
      change,
      mergeable,
    ].some(arg => arg === undefined)) {
      // To keep consistent with Polymer 1, we are returning undefined
      // if not all dependencies are defined
      return undefined;
    }

    // Show no chips until mergeability is loaded.
    if (mergeable === null) {
      return [];
    }

    const options = {
      includeDerived: true,
      mergeable: !!mergeable,
      submitEnabled: !!submitEnabled,
    };
    return this.changeStatuses(change, options);
  }

  _computeHideEditCommitMessage(
      loggedIn, editing, change, editMode, collapsed, collapsible) {
    if (!loggedIn || editing ||
        (change && change.status === this.ChangeStatus.MERGED) ||
        editMode ||
        (collapsed && collapsible)) {
      return true;
    }

    return false;
  }

  _robotCommentCountPerPatchSet(threads) {
    return threads.reduce((robotCommentCountMap, thread) => {
      const comments = thread.comments;
      const robotCommentsCount = comments.reduce((acc, comment) =>
        (comment.robot_id ? acc + 1 : acc), 0);
      robotCommentCountMap[comments[0].patch_set] =
          (robotCommentCountMap[comments[0].patch_set] || 0) +
        robotCommentsCount;
      return robotCommentCountMap;
    }, {});
  }

  _computeText(patch, commentThreads) {
    const commentCount = this._robotCommentCountPerPatchSet(commentThreads);
    const commentCnt = commentCount[patch._number] || 0;
    if (commentCnt === 0) return `Patchset ${patch._number}`;
    const findingsText = commentCnt === 1 ? 'finding' : 'findings';
    return `Patchset ${patch._number}`
            + ` (${commentCnt} ${findingsText})`;
  }

  _computeRobotCommentsPatchSetDropdownItems(change, commentThreads) {
    if (!change || !commentThreads || !change.revisions) return [];

    return Object.values(change.revisions)
        .filter(patch => patch._number !== 'edit')
        .map(patch => {
          return {
            text: this._computeText(patch, commentThreads),
            value: patch._number,
          };
        })
        .sort((a, b) => b.value - a.value);
  }

  _handleCurrentRevisionUpdate(currentRevision) {
    this._currentRobotCommentsPatchSet = currentRevision._number;
  }

  _handleRobotCommentPatchSetChanged(e) {
    const patchSet = parseInt(e.detail.value);
    if (patchSet === this._currentRobotCommentsPatchSet) return;
    this._currentRobotCommentsPatchSet = patchSet;
  }

  _computeShowText(showAllRobotComments) {
    return showAllRobotComments ? 'Show Less' : 'Show more';
  }

  _toggleShowRobotComments() {
    this._showAllRobotComments = !this._showAllRobotComments;
  }

  _computeRobotCommentThreads(commentThreads, currentRobotCommentsPatchSet,
      showAllRobotComments) {
    if (!commentThreads || !currentRobotCommentsPatchSet) return [];
    const threads = commentThreads.filter(thread => {
      const comments = thread.comments || [];
      return comments.length && comments[0].robot_id && (comments[0].patch_set
        === currentRobotCommentsPatchSet);
    });
    this._showRobotCommentsButton = threads.length > ROBOT_COMMENTS_LIMIT;
    return threads.slice(0, showAllRobotComments ? undefined :
      ROBOT_COMMENTS_LIMIT);
  }

  _handleReloadCommentThreads() {
    // Get any new drafts that have been saved in the diff view and show
    // in the comment thread view.
    this._reloadDrafts().then(() => {
      this._commentThreads = this._changeComments.getAllThreadsForChange()
          .map(c => Object.assign({}, c));
      flush();
    });
  }

  _handleReloadDiffComments(e) {
    // Keeps the file list counts updated.
    this._reloadDrafts().then(() => {
      // Get any new drafts that have been saved in the thread view and show
      // in the diff view.
      this.$.fileList.reloadCommentsForThreadWithRootId(e.detail.rootId,
          e.detail.path);
      flush();
    });
  }

  _computeTotalCommentCounts(unresolvedCount, changeComments) {
    if (!changeComments) return undefined;
    const draftCount = changeComments.computeDraftCount();
    const unresolvedString = GrCountStringFormatter.computeString(
        unresolvedCount, 'unresolved');
    const draftString = GrCountStringFormatter.computePluralString(
        draftCount, 'draft');

    return unresolvedString +
        // Add a comma and space if both unresolved and draft comments exist.
        (unresolvedString && draftString ? ', ' : '') +
        draftString;
  }

  _handleCommentSave(e) {
    const draft = e.detail.comment;
    if (!draft.__draft) { return; }

    draft.patch_set = draft.patch_set || this._patchRange.patchNum;

    // The use of path-based notification helpers (set, push) can’t be used
    // because the paths could contain dots in them. A new object must be
    // created to satisfy Polymer’s dirty checking.
    // https://github.com/Polymer/polymer/issues/3127
    const diffDrafts = Object.assign({}, this._diffDrafts);
    if (!diffDrafts[draft.path]) {
      diffDrafts[draft.path] = [draft];
      this._diffDrafts = diffDrafts;
      return;
    }
    for (let i = 0; i < this._diffDrafts[draft.path].length; i++) {
      if (this._diffDrafts[draft.path][i].id === draft.id) {
        diffDrafts[draft.path][i] = draft;
        this._diffDrafts = diffDrafts;
        return;
      }
    }
    diffDrafts[draft.path].push(draft);
    diffDrafts[draft.path].sort((c1, c2) =>
      // No line number means that it’s a file comment. Sort it above the
      // others.
      (c1.line || -1) - (c2.line || -1)
    );
    this._diffDrafts = diffDrafts;
  }

  _handleCommentDiscard(e) {
    const draft = e.detail.comment;
    if (!draft.__draft) { return; }

    if (!this._diffDrafts[draft.path]) {
      return;
    }
    let index = -1;
    for (let i = 0; i < this._diffDrafts[draft.path].length; i++) {
      if (this._diffDrafts[draft.path][i].id === draft.id) {
        index = i;
        break;
      }
    }
    if (index === -1) {
      // It may be a draft that hasn’t been added to _diffDrafts since it was
      // never saved.
      return;
    }

    draft.patch_set = draft.patch_set || this._patchRange.patchNum;

    // The use of path-based notification helpers (set, push) can’t be used
    // because the paths could contain dots in them. A new object must be
    // created to satisfy Polymer’s dirty checking.
    // https://github.com/Polymer/polymer/issues/3127
    const diffDrafts = Object.assign({}, this._diffDrafts);
    diffDrafts[draft.path].splice(index, 1);
    if (diffDrafts[draft.path].length === 0) {
      delete diffDrafts[draft.path];
    }
    this._diffDrafts = diffDrafts;
  }

  _handleReplyTap(e) {
    e.preventDefault();
    this._openReplyDialog(this.$.replyDialog.FocusTarget.ANY);
  }

  _handleOpenDiffPrefs() {
    this.$.fileList.openDiffPrefs();
  }

  _handleOpenIncludedInDialog() {
    this.$.includedInDialog.loadData().then(() => {
      flush();
      this.$.includedInOverlay.refit();
    });
    this.$.includedInOverlay.open();
  }

  _handleIncludedInDialogClose(e) {
    this.$.includedInOverlay.close();
  }

  _handleOpenDownloadDialog() {
    this.$.downloadOverlay.open().then(() => {
      this.$.downloadOverlay
          .setFocusStops(this.$.downloadDialog.getFocusStops());
      this.$.downloadDialog.focus();
    });
  }

  _handleDownloadDialogClose(e) {
    this.$.downloadOverlay.close();
  }

  _handleOpenUploadHelpDialog(e) {
    this.$.uploadHelpOverlay.open();
  }

  _handleCloseUploadHelpDialog(e) {
    this.$.uploadHelpOverlay.close();
  }

  _handleMessageReply(e) {
    const msg = e.detail.message.message;
    const quoteStr = msg.split('\n').map(
        line => '> ' + line)
        .join('\n') + '\n\n';
    this.$.replyDialog.quote = quoteStr;
    this._openReplyDialog(this.$.replyDialog.FocusTarget.BODY);
  }

  _handleHideBackgroundContent() {
    this.$.mainContent.classList.add('overlayOpen');
  }

  _handleShowBackgroundContent() {
    this.$.mainContent.classList.remove('overlayOpen');
  }

  _handleReplySent(e) {
    this.addEventListener('change-details-loaded',
        () => {
          this.$.reporting.timeEnd(SEND_REPLY_TIMING_LABEL);
        }, {once: true});
    this.$.replyOverlay.close();
    this._reload();
  }

  _handleReplyCancel(e) {
    this.$.replyOverlay.close();
  }

  _handleReplyAutogrow(e) {
    // If the textarea resizes, we need to re-fit the overlay.
    this.debounce('reply-overlay-refit', () => {
      this.$.replyOverlay.refit();
    }, REPLY_REFIT_DEBOUNCE_INTERVAL_MS);
  }

  _handleShowReplyDialog(e) {
    let target = this.$.replyDialog.FocusTarget.REVIEWERS;
    if (e.detail.value && e.detail.value.ccsOnly) {
      target = this.$.replyDialog.FocusTarget.CCS;
    }
    this._openReplyDialog(target);
  }

  _handleScroll() {
    this.debounce('scroll', () => {
      this.viewState.scrollTop = document.body.scrollTop;
    }, 150);
  }

  _setShownFiles(e) {
    this._shownFileCount = e.detail.length;
  }

  _expandAllDiffs() {
    this.$.fileList.expandAllDiffs();
  }

  _collapseAllDiffs() {
    this.$.fileList.collapseAllDiffs();
  }

  _paramsChanged(value) {
    this._currentView = CommentTabs.CHANGE_LOG;
    this._setPrimaryTab();
    if (value.view !== Gerrit.Nav.View.CHANGE) {
      this._initialLoadComplete = false;
      return;
    }

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

    const patchChanged = this._patchRange &&
        (value.patchNum !== undefined && value.basePatchNum !== undefined) &&
        (this._patchRange.patchNum !== value.patchNum ||
        this._patchRange.basePatchNum !== value.basePatchNum);

    if (this._changeNum !== value.changeNum) {
      this._initialLoadComplete = false;
    }

    const patchRange = {
      patchNum: value.patchNum,
      basePatchNum: value.basePatchNum || 'PARENT',
    };

    this.$.fileList.collapseAllDiffs();
    this._patchRange = patchRange;

    // If the change has already been loaded and the parameter change is only
    // in the patch range, then don't do a full reload.
    if (this._initialLoadComplete && patchChanged) {
      if (patchRange.patchNum == null) {
        patchRange.patchNum = this.computeLatestPatchNum(this._allPatchSets);
      }
      this._reloadPatchNumDependentResources().then(() => {
        this._sendShowChangeEvent();
      });
      return;
    }

    this._changeNum = value.changeNum;
    this.$.relatedChanges.clear();

    this._reload(true).then(() => {
      this._performPostLoadTasks();
    });
  }

  _sendShowChangeEvent() {
    this.$.jsAPI.handleEvent(this.$.jsAPI.EventType.SHOW_CHANGE, {
      change: this._change,
      patchNum: this._patchRange.patchNum,
      info: {mergeable: this._mergeable},
    });
  }

  _setPrimaryTab() {
    // Selected has to be set after the paper-tabs are visible, because
    // the selected underline depends on calculations made by the browser.
    // paper-tabs depends on iron-resizable-behavior, which only fires on
    // attached() without using RenderStatus.beforeNextRender. Not changing
    // this when migrating from Polymer 1 to 2 was probably an oversight by
    // the paper component maintainers.
    // https://polymer-library.polymer-project.org/2.0/docs/upgrade#attach-time-attached-connectedcallback
    // By calling _onTabSizingChanged() we are reaching into the private API
    // of paper-tabs, but we believe this workaround is acceptable for the
    // time being.
    beforeNextRender(this, () => {
      this.$.commentTabs.selected = 0;
      this.$.commentTabs._onTabSizingChanged();
      const primaryTabs = this.shadowRoot.querySelector('#primaryTabs');
      if (primaryTabs) {
        primaryTabs.selected = 0;
        primaryTabs._onTabSizingChanged();
      }
    });
  }

  _performPostLoadTasks() {
    this._maybeShowReplyDialog();
    this._maybeShowRevertDialog();

    this._sendShowChangeEvent();

    this.async(() => {
      if (this.viewState.scrollTop) {
        document.documentElement.scrollTop =
            document.body.scrollTop = this.viewState.scrollTop;
      } else {
        this._maybeScrollToMessage(window.location.hash);
      }
      this._initialLoadComplete = true;
    });
  }

  _paramsAndChangeChanged(value, change) {
    // Polymer 2: check for undefined
    if ([value, change].some(arg => arg === undefined)) {
      return;
    }

    // If the change number or patch range is different, then reset the
    // selected file index.
    const patchRangeState = this.viewState.patchRange;
    if (this.viewState.changeNum !== this._changeNum ||
        patchRangeState.basePatchNum !== this._patchRange.basePatchNum ||
        patchRangeState.patchNum !== this._patchRange.patchNum) {
      this._resetFileListViewState();
    }
  }

  _viewStateChanged(viewState) {
    this._numFilesShown = viewState.numFilesShown ?
      viewState.numFilesShown : DEFAULT_NUM_FILES_SHOWN;
  }

  _numFilesShownChanged(numFilesShown) {
    this.viewState.numFilesShown = numFilesShown;
  }

  _handleMessageAnchorTap(e) {
    const hash = MSG_PREFIX + e.detail.id;
    const url = Gerrit.Nav.getUrlForChange(this._change,
        this._patchRange.patchNum, this._patchRange.basePatchNum,
        this._editMode, hash);
    history.replaceState(null, '', url);
  }

  _maybeScrollToMessage(hash) {
    if (hash.startsWith(MSG_PREFIX)) {
      this.messagesList.scrollToMessage(hash.substr(MSG_PREFIX.length));
    }
  }

  _getLocationSearch() {
    // Not inlining to make it easier to test.
    return window.location.search;
  }

  _getUrlParameter(param) {
    const pageURL = this._getLocationSearch().substring(1);
    const vars = pageURL.split('&');
    for (let i = 0; i < vars.length; i++) {
      const name = vars[i].split('=');
      if (name[0] == param) {
        return name[0];
      }
    }
    return null;
  }

  _maybeShowRevertDialog() {
    Gerrit.awaitPluginsLoaded()
        .then(this._getLoggedIn.bind(this))
        .then(loggedIn => {
          if (!loggedIn || !this._change ||
              this._change.status !== this.ChangeStatus.MERGED) {
          // Do not display dialog if not logged-in or the change is not
          // merged.
            return;
          }
          if (this._getUrlParameter('revert')) {
            this.$.actions.showRevertDialog();
          }
        });
  }

  _maybeShowReplyDialog() {
    this._getLoggedIn().then(loggedIn => {
      if (!loggedIn) { return; }

      if (this.viewState.showReplyDialog) {
        this._openReplyDialog(this.$.replyDialog.FocusTarget.ANY);
        // TODO(kaspern@): Find a better signal for when to call center.
        this.async(() => { this.$.replyOverlay.center(); }, 100);
        this.async(() => { this.$.replyOverlay.center(); }, 1000);
        this.set('viewState.showReplyDialog', false);
      }
    });
  }

  _resetFileListViewState() {
    this.set('viewState.selectedFileIndex', 0);
    this.set('viewState.scrollTop', 0);
    if (!!this.viewState.changeNum &&
        this.viewState.changeNum !== this._changeNum) {
      // Reset the diff mode to null when navigating from one change to
      // another, so that the user's preference is restored.
      this._setDiffViewMode(true);
      this.set('_numFilesShown', DEFAULT_NUM_FILES_SHOWN);
    }
    this.set('viewState.changeNum', this._changeNum);
    this.set('viewState.patchRange', this._patchRange);
  }

  _changeChanged(change) {
    if (!change || !this._patchRange || !this._allPatchSets) { return; }

    // We get the parent first so we keep the original value for basePatchNum
    // and not the updated value.
    const parent = this._getBasePatchNum(change, this._patchRange);

    this.set('_patchRange.patchNum', this._patchRange.patchNum ||
            this.computeLatestPatchNum(this._allPatchSets));

    this.set('_patchRange.basePatchNum', parent);

    const title = change.subject + ' (' + change.change_id.substr(0, 9) + ')';
    this.fire('title-change', {title});
  }

  /**
   * Gets base patch number, if it is a parent try and decide from
   * preference whether to default to `auto merge`, `Parent 1` or `PARENT`.
   *
   * @param {Object} change
   * @param {Object} patchRange
   * @return {number|string}
   */
  _getBasePatchNum(change, patchRange) {
    if (patchRange.basePatchNum &&
        patchRange.basePatchNum !== 'PARENT') {
      return patchRange.basePatchNum;
    }

    const revisionInfo = this._getRevisionInfo(change);
    if (!revisionInfo) return 'PARENT';

    const parentCounts = revisionInfo.getParentCountMap();
    // check that there is at least 2 parents otherwise fall back to 1,
    // which means there is only one parent.
    const parentCount = parentCounts.hasOwnProperty(1) ?
      parentCounts[1] : 1;

    const preferFirst = this._prefs &&
        this._prefs.default_base_for_merges === 'FIRST_PARENT';

    if (parentCount > 1 && preferFirst && !patchRange.patchNum) {
      return -1;
    }

    return 'PARENT';
  }

  _computeChangeUrl(change) {
    return Gerrit.Nav.getUrlForChange(change);
  }

  _computeShowCommitInfo(changeStatus, current_revision) {
    return changeStatus === 'Merged' && current_revision;
  }

  _computeMergedCommitInfo(current_revision, revisions) {
    const rev = revisions[current_revision];
    if (!rev || !rev.commit) { return {}; }
    // CommitInfo.commit is optional. Set commit in all cases to avoid error
    // in <gr-commit-info>. @see Issue 5337
    if (!rev.commit.commit) { rev.commit.commit = current_revision; }
    return rev.commit;
  }

  _computeChangeIdClass(displayChangeId) {
    return displayChangeId === CHANGE_ID_ERROR.MISMATCH ? 'warning' : '';
  }

  _computeTitleAttributeWarning(displayChangeId) {
    if (displayChangeId === CHANGE_ID_ERROR.MISMATCH) {
      return 'Change-Id mismatch';
    } else if (displayChangeId === CHANGE_ID_ERROR.MISSING) {
      return 'No Change-Id in commit message';
    }
  }

  _computeChangeIdCommitMessageError(commitMessage, change) {
    // Polymer 2: check for undefined
    if ([commitMessage, change].some(arg => arg === undefined)) {
      return undefined;
    }

    if (!commitMessage) { return CHANGE_ID_ERROR.MISSING; }

    // Find the last match in the commit message:
    let changeId;
    let changeIdArr;

    while (changeIdArr = CHANGE_ID_REGEX_PATTERN.exec(commitMessage)) {
      changeId = changeIdArr[1];
    }

    if (changeId) {
      // A change-id is detected in the commit message.

      if (changeId === change.change_id) {
        // The change-id found matches the real change-id.
        return null;
      }
      // The change-id found does not match the change-id.
      return CHANGE_ID_ERROR.MISMATCH;
    }
    // There is no change-id in the commit message.
    return CHANGE_ID_ERROR.MISSING;
  }

  _computeLabelNames(labels) {
    return Object.keys(labels).sort();
  }

  _computeLabelValues(labelName, labels) {
    const result = [];
    const t = labels[labelName];
    if (!t) { return result; }
    const approvals = t.all || [];
    for (const label of approvals) {
      if (label.value && label.value != labels[labelName].default_value) {
        let labelClassName;
        let labelValPrefix = '';
        if (label.value > 0) {
          labelValPrefix = '+';
          labelClassName = 'approved';
        } else if (label.value < 0) {
          labelClassName = 'notApproved';
        }
        result.push({
          value: labelValPrefix + label.value,
          className: labelClassName,
          account: label,
        });
      }
    }
    return result;
  }

  _computeReplyButtonLabel(changeRecord, canStartReview) {
    // Polymer 2: check for undefined
    if ([changeRecord, canStartReview].some(arg => arg === undefined)) {
      return 'Reply';
    }

    if (canStartReview) {
      return 'Start review';
    }

    const drafts = (changeRecord && changeRecord.base) || {};
    const draftCount = Object.keys(drafts)
        .reduce((count, file) => count + drafts[file].length, 0);

    let label = 'Reply';
    if (draftCount > 0) {
      label += ' (' + draftCount + ')';
    }
    return label;
  }

  _handleOpenReplyDialog(e) {
    if (this.shouldSuppressKeyboardShortcut(e) ||
        this.modifierPressed(e)) {
      return;
    }
    this._getLoggedIn().then(isLoggedIn => {
      if (!isLoggedIn) {
        this.fire('show-auth-required');
        return;
      }

      e.preventDefault();
      this._openReplyDialog(this.$.replyDialog.FocusTarget.ANY);
    });
  }

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

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

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

    e.preventDefault();
    this.$.metadata.editTopic();
  }

  _handleRefreshChange(e) {
    if (this.shouldSuppressKeyboardShortcut(e)) { return; }
    e.preventDefault();
    Gerrit.Nav.navigateToChange(this._change);
  }

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

    e.preventDefault();
    this.$.changeStar.toggleStar();
  }

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

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

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

    e.preventDefault();
    this.messagesList.handleExpandCollapse(true);
  }

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

    e.preventDefault();
    this.messagesList.handleExpandCollapse(false);
  }

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

    if (this._diffPrefsDisabled) { return; }

    e.preventDefault();
    this.$.fileList.openDiffPrefs();
  }

  _determinePageBack() {
    // Default backPage to root if user came to change view page
    // via an email link, etc.
    Gerrit.Nav.navigateToRelativeUrl(this.backPage ||
        Gerrit.Nav.getUrlForRoot());
  }

  _handleLabelRemoved(splices, path) {
    for (const splice of splices) {
      for (const removed of splice.removed) {
        const changePath = path.split('.');
        const labelPath = changePath.splice(0, changePath.length - 2);
        const labelDict = this.get(labelPath);
        if (labelDict.approved &&
            labelDict.approved._account_id === removed._account_id) {
          this._reload();
          return;
        }
      }
    }
  }

  _labelsChanged(changeRecord) {
    if (!changeRecord) { return; }
    if (changeRecord.value && changeRecord.value.indexSplices) {
      this._handleLabelRemoved(changeRecord.value.indexSplices,
          changeRecord.path);
    }
    this.$.jsAPI.handleEvent(this.$.jsAPI.EventType.LABEL_CHANGE, {
      change: this._change,
    });
  }

  /**
   * @param {string=} opt_section
   */
  _openReplyDialog(opt_section) {
    this.$.replyOverlay.open().finally(() => {
      // the following code should be executed no matter open succeed or not
      this._resetReplyOverlayFocusStops();
      this.$.replyDialog.open(opt_section);
      flush();
      this.$.replyOverlay.center();
    });
  }

  _handleReloadChange(e) {
    return this._reload().then(() => {
      // If the change was rebased or submitted, we need to reload the page
      // with the latest patch.
      const action = e.detail.action;
      if (action === 'rebase' || action === 'submit') {
        Gerrit.Nav.navigateToChange(this._change);
      }
    });
  }

  _handleGetChangeDetailError(response) {
    this.fire('page-error', {response});
  }

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

  _getServerConfig() {
    return this.$.restAPI.getConfig();
  }

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

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

  _prepareCommitMsgForLinkify(msg) {
    // TODO(wyatta) switch linkify sequence, see issue 5526.
    // This is a zero-with space. It is added to prevent the linkify library
    // from including R= or CC= as part of the email address.
    return msg.replace(REVIEWERS_REGEX, '$1=\u200B');
  }

  /**
   * Utility function to make the necessary modifications to a change in the
   * case an edit exists.
   *
   * @param {!Object} change
   * @param {?Object} edit
   */
  _processEdit(change, edit) {
    if (!edit) { return; }
    change.revisions[edit.commit.commit] = {
      _number: this.EDIT_NAME,
      basePatchNum: edit.base_patch_set_number,
      commit: edit.commit,
      fetch: edit.fetch,
    };
    // If the edit is based on the most recent patchset, load it by
    // default, unless another patch set to load was specified in the URL.
    if (!this._patchRange.patchNum &&
        change.current_revision === edit.base_revision) {
      change.current_revision = edit.commit.commit;
      this.set('_patchRange.patchNum', this.EDIT_NAME);
      // Because edits are fibbed as revisions and added to the revisions
      // array, and revision actions are always derived from the 'latest'
      // patch set, we must copy over actions from the patch set base.
      // Context: Issue 7243
      change.revisions[edit.commit.commit].actions =
          change.revisions[edit.base_revision].actions;
    }
  }

  _getChangeDetail() {
    const detailCompletes = this.$.restAPI.getChangeDetail(
        this._changeNum, this._handleGetChangeDetailError.bind(this));
    const editCompletes = this._getEdit();
    const prefCompletes = this._getPreferences();

    return Promise.all([detailCompletes, editCompletes, prefCompletes])
        .then(([change, edit, prefs]) => {
          this._prefs = prefs;

          if (!change) {
            return '';
          }
          this._processEdit(change, edit);
          // Issue 4190: Coalesce missing topics to null.
          if (!change.topic) { change.topic = null; }
          if (!change.reviewer_updates) {
            change.reviewer_updates = null;
          }
          const latestRevisionSha = this._getLatestRevisionSHA(change);
          const currentRevision = change.revisions[latestRevisionSha];
          if (currentRevision.commit && currentRevision.commit.message) {
            this._latestCommitMessage = this._prepareCommitMsgForLinkify(
                currentRevision.commit.message);
          } else {
            this._latestCommitMessage = null;
          }

          const lineHeight = getComputedStyle(this).lineHeight;

          // Slice returns a number as a string, convert to an int.
          this._lineHeight =
              parseInt(lineHeight.slice(0, lineHeight.length - 2), 10);

          this._change = change;
          if (!this._patchRange || !this._patchRange.patchNum ||
              this.patchNumEquals(this._patchRange.patchNum,
                  currentRevision._number)) {
            // CommitInfo.commit is optional, and may need patching.
            if (!currentRevision.commit.commit) {
              currentRevision.commit.commit = latestRevisionSha;
            }
            this._commitInfo = currentRevision.commit;
            this._selectedRevision = currentRevision;
            // TODO: Fetch and process files.
          } else {
            this._selectedRevision =
              Object.values(this._change.revisions).find(
                  revision => {
                    // edit patchset is a special one
                    const thePatchNum = this._patchRange.patchNum;
                    if (thePatchNum === 'edit') {
                      return revision._number === thePatchNum;
                    }
                    return revision._number === parseInt(thePatchNum, 10);
                  });
          }
        });
  }

  _isSubmitEnabled(revisionActions) {
    return !!(revisionActions && revisionActions.submit &&
      revisionActions.submit.enabled);
  }

  _isParentCurrent(revisionActions) {
    if (revisionActions && revisionActions.rebase) {
      return !revisionActions.rebase.enabled;
    } else {
      return true;
    }
  }

  _getEdit() {
    return this.$.restAPI.getChangeEdit(this._changeNum, true);
  }

  _getLatestCommitMessage() {
    return this.$.restAPI.getChangeCommitInfo(this._changeNum,
        this.computeLatestPatchNum(this._allPatchSets)).then(commitInfo => {
      if (!commitInfo) return Promise.resolve();
      this._latestCommitMessage =
                  this._prepareCommitMsgForLinkify(commitInfo.message);
    });
  }

  _getLatestRevisionSHA(change) {
    if (change.current_revision) {
      return change.current_revision;
    }
    // current_revision may not be present in the case where the latest rev is
    // a draft and the user doesn’t have permission to view that rev.
    let latestRev = null;
    let latestPatchNum = -1;
    for (const rev in change.revisions) {
      if (!change.revisions.hasOwnProperty(rev)) { continue; }

      if (change.revisions[rev]._number > latestPatchNum) {
        latestRev = rev;
        latestPatchNum = change.revisions[rev]._number;
      }
    }
    return latestRev;
  }

  _getCommitInfo() {
    return this.$.restAPI.getChangeCommitInfo(
        this._changeNum, this._patchRange.patchNum).then(
        commitInfo => {
          this._commitInfo = commitInfo;
        });
  }

  _reloadDraftsWithCallback(e) {
    return this._reloadDrafts().then(() => e.detail.resolve());
  }

  /**
   * Fetches a new changeComment object, and data for all types of comments
   * (comments, robot comments, draft comments) is requested.
   */
  _reloadComments() {
    return this.$.commentAPI.loadAll(this._changeNum)
        .then(comments => this._recomputeComments(comments));
  }

  /**
   * Fetches a new changeComment object, but only updated data for drafts is
   * requested.
   *
   * TODO(taoalpha): clean up this and _reloadComments, as single comment
   * can be a thread so it does not make sense to only update drafts
   * without updating threads
   */
  _reloadDrafts() {
    return this.$.commentAPI.reloadDrafts(this._changeNum)
        .then(comments => this._recomputeComments(comments));
  }

  _recomputeComments(comments) {
    this._changeComments = comments;
    this._diffDrafts = Object.assign({}, this._changeComments.drafts);
    this._commentThreads = this._changeComments.getAllThreadsForChange()
        .map(c => Object.assign({}, c));
    this._draftCommentThreads = this._commentThreads
        .filter(c => c.comments[c.comments.length - 1].__draft);
  }

  /**
   * Reload the change.
   *
   * @param {boolean=} opt_isLocationChange Reloads the related changes
   *     when true and ends reporting events that started on location change.
   * @return {Promise} A promise that resolves when the core data has loaded.
   *     Some non-core data loading may still be in-flight when the core data
   *     promise resolves.
   */
  _reload(opt_isLocationChange) {
    this._loading = true;
    this._relatedChangesCollapsed = true;
    this.$.reporting.time(CHANGE_RELOAD_TIMING_LABEL);
    this.$.reporting.time(CHANGE_DATA_TIMING_LABEL);

    // Array to house all promises related to data requests.
    const allDataPromises = [];

    // Resolves when the change detail and the edit patch set (if available)
    // are loaded.
    const detailCompletes = this._getChangeDetail();
    allDataPromises.push(detailCompletes);

    // Resolves when the loading flag is set to false, meaning that some
    // change content may start appearing.
    const loadingFlagSet = detailCompletes
        .then(() => {
          this._loading = false;
          this.dispatchEvent(new CustomEvent('change-details-loaded',
              {bubbles: true, composed: true}));
        })
        .then(() => {
          this.$.reporting.timeEnd(CHANGE_RELOAD_TIMING_LABEL);
          if (opt_isLocationChange) {
            this.$.reporting.changeDisplayed();
          }
        });

    // Resolves when the project config has loaded.
    const projectConfigLoaded = detailCompletes
        .then(() => this._getProjectConfig());
    allDataPromises.push(projectConfigLoaded);

    // Resolves when change comments have loaded (comments, drafts and robot
    // comments).
    const commentsLoaded = this._reloadComments();
    allDataPromises.push(commentsLoaded);

    let coreDataPromise;

    // If the patch number is specified
    if (this._patchRange && this._patchRange.patchNum) {
      // Because a specific patchset is specified, reload the resources that
      // are keyed by patch number or patch range.
      const patchResourcesLoaded = this._reloadPatchNumDependentResources();
      allDataPromises.push(patchResourcesLoaded);

      // Promise resolves when the change detail and patch dependent resources
      // have loaded.
      const detailAndPatchResourcesLoaded =
          Promise.all([patchResourcesLoaded, loadingFlagSet]);

      // Promise resolves when mergeability information has loaded.
      const mergeabilityLoaded = detailAndPatchResourcesLoaded
          .then(() => this._getMergeability());
      allDataPromises.push(mergeabilityLoaded);

      // Promise resovles when the change actions have loaded.
      const actionsLoaded = detailAndPatchResourcesLoaded
          .then(() => this.$.actions.reload());
      allDataPromises.push(actionsLoaded);

      // The core data is loaded when both mergeability and actions are known.
      coreDataPromise = Promise.all([mergeabilityLoaded, actionsLoaded]);
    } else {
      // Resolves when the file list has loaded.
      const fileListReload = loadingFlagSet
          .then(() => this.$.fileList.reload());
      allDataPromises.push(fileListReload);

      const latestCommitMessageLoaded = loadingFlagSet.then(() => {
        // If the latest commit message is known, there is nothing to do.
        if (this._latestCommitMessage) { return Promise.resolve(); }
        return this._getLatestCommitMessage();
      });
      allDataPromises.push(latestCommitMessageLoaded);

      // Promise resolves when mergeability information has loaded.
      const mergeabilityLoaded = loadingFlagSet
          .then(() => this._getMergeability());
      allDataPromises.push(mergeabilityLoaded);

      // Core data is loaded when mergeability has been loaded.
      coreDataPromise = mergeabilityLoaded;
    }

    if (opt_isLocationChange) {
      const relatedChangesLoaded = coreDataPromise
          .then(() => this.$.relatedChanges.reload());
      allDataPromises.push(relatedChangesLoaded);
    }

    Promise.all(allDataPromises).then(() => {
      this.$.reporting.timeEnd(CHANGE_DATA_TIMING_LABEL);
      if (opt_isLocationChange) {
        this.$.reporting.changeFullyLoaded();
      }
    });

    return coreDataPromise;
  }

  /**
   * Kicks off requests for resources that rely on the patch range
   * (`this._patchRange`) being defined.
   */
  _reloadPatchNumDependentResources() {
    return Promise.all([
      this._getCommitInfo(),
      this.$.fileList.reload(),
    ]);
  }

  _getMergeability() {
    if (!this._change) {
      this._mergeable = null;
      return Promise.resolve();
    }
    // If the change is closed, it is not mergeable. Note: already merged
    // changes are obviously not mergeable, but the mergeability API will not
    // answer for abandoned changes.
    if (this._change.status === this.ChangeStatus.MERGED ||
        this._change.status === this.ChangeStatus.ABANDONED) {
      this._mergeable = false;
      return Promise.resolve();
    }

    this._mergeable = null;
    return this.$.restAPI.getMergeable(this._changeNum).then(m => {
      this._mergeable = m.mergeable;
    });
  }

  _computeCanStartReview(change) {
    return !!(change.actions && change.actions.ready &&
        change.actions.ready.enabled);
  }

  _computeReplyDisabled() { return false; }

  _computeChangePermalinkAriaLabel(changeNum) {
    return 'Change ' + changeNum;
  }

  _computeCommitMessageCollapsed(collapsed, collapsible) {
    return collapsible && collapsed;
  }

  _computeRelatedChangesClass(collapsed) {
    return collapsed ? 'collapsed' : '';
  }

  _computeCollapseText(collapsed) {
    // Symbols are up and down triangles.
    return collapsed ? '\u25bc Show more' : '\u25b2 Show less';
  }

  /**
   * Returns the text to be copied when
   * click the copy icon next to change subject
   *
   * @param {!Object} change
   */
  _computeCopyTextForTitle(change) {
    return `${change._number}: ${change.subject} | ` +
     `${location.protocol}//${location.host}` +
       `${this._computeChangeUrl(change)}`;
  }

  _toggleCommitCollapsed() {
    this._commitCollapsed = !this._commitCollapsed;
    if (this._commitCollapsed) {
      window.scrollTo(0, 0);
    }
  }

  _toggleRelatedChangesCollapsed() {
    this._relatedChangesCollapsed = !this._relatedChangesCollapsed;
    if (this._relatedChangesCollapsed) {
      window.scrollTo(0, 0);
    }
  }

  _computeCommitCollapsible(commitMessage) {
    if (!commitMessage) { return false; }
    return commitMessage.split('\n').length >= MIN_LINES_FOR_COMMIT_COLLAPSE;
  }

  _getOffsetHeight(element) {
    return element.offsetHeight;
  }

  _getScrollHeight(element) {
    return element.scrollHeight;
  }

  /**
   * Get the line height of an element to the nearest integer.
   */
  _getLineHeight(element) {
    const lineHeightStr = getComputedStyle(element).lineHeight;
    return Math.round(lineHeightStr.slice(0, lineHeightStr.length - 2));
  }

  /**
   * New max height for the related changes section, shorter than the existing
   * change info height.
   */
  _updateRelatedChangeMaxHeight() {
    // Takes into account approximate height for the expand button and
    // bottom margin.
    const EXTRA_HEIGHT = 30;
    let newHeight;

    if (window.matchMedia(`(max-width: ${BREAKPOINT_RELATED_SMALL})`)
        .matches) {
      // In a small (mobile) view, give the relation chain some space.
      newHeight = SMALL_RELATED_HEIGHT;
    } else if (window.matchMedia(`(max-width: ${BREAKPOINT_RELATED_MED})`)
        .matches) {
      // Since related changes are below the commit message, but still next to
      // metadata, the height should be the height of the metadata minus the
      // height of the commit message to reduce jank. However, if that doesn't
      // result in enough space, instead use the MINIMUM_RELATED_MAX_HEIGHT.
      // Note: extraHeight is to take into account margin/padding.
      const medRelatedHeight = Math.max(
          this._getOffsetHeight(this.$.mainChangeInfo) -
          this._getOffsetHeight(this.$.commitMessage) - 2 * EXTRA_HEIGHT,
          MINIMUM_RELATED_MAX_HEIGHT);
      newHeight = medRelatedHeight;
    } else {
      if (this._commitCollapsible) {
        // Make sure the content is lined up if both areas have buttons. If
        // the commit message is not collapsed, instead use the change info
        // height.
        newHeight = this._getOffsetHeight(this.$.commitMessage);
      } else {
        newHeight = this._getOffsetHeight(this.$.commitAndRelated) -
            EXTRA_HEIGHT;
      }
    }
    const stylesToUpdate = {};

    // Get the line height of related changes, and convert it to the nearest
    // integer.
    const lineHeight = this._getLineHeight(this.$.relatedChanges);

    // Figure out a new height that is divisible by the rounded line height.
    const remainder = newHeight % lineHeight;
    newHeight = newHeight - remainder;

    stylesToUpdate['--relation-chain-max-height'] = newHeight + 'px';

    // Update the max-height of the relation chain to this new height.
    if (this._commitCollapsible) {
      stylesToUpdate['--related-change-btn-top-padding'] = remainder + 'px';
    }

    this.updateStyles(stylesToUpdate);
  }

  _computeShowRelatedToggle() {
    // Make sure the max height has been applied, since there is now content
    // to populate.
    if (!util.getComputedStyleValue('--relation-chain-max-height', this)) {
      this._updateRelatedChangeMaxHeight();
    }
    // Prevents showMore from showing when click on related change, since the
    // line height would be positive, but related changes height is 0.
    if (!this._getScrollHeight(this.$.relatedChanges)) {
      return this._showRelatedToggle = false;
    }

    if (this._getScrollHeight(this.$.relatedChanges) >
        (this._getOffsetHeight(this.$.relatedChanges) +
        this._getLineHeight(this.$.relatedChanges))) {
      return this._showRelatedToggle = true;
    }
    this._showRelatedToggle = false;
  }

  _updateToggleContainerClass(showRelatedToggle) {
    if (showRelatedToggle) {
      this.$.relatedChangesToggle.classList.add('showToggle');
    } else {
      this.$.relatedChangesToggle.classList.remove('showToggle');
    }
  }

  _startUpdateCheckTimer() {
    if (!this._serverConfig ||
        !this._serverConfig.change ||
        this._serverConfig.change.update_delay === undefined ||
        this._serverConfig.change.update_delay <= MIN_CHECK_INTERVAL_SECS) {
      return;
    }

    this._updateCheckTimerHandle = this.async(() => {
      this.fetchChangeUpdates(this._change, this.$.restAPI).then(result => {
        let toastMessage = null;
        if (!result.isLatest) {
          toastMessage = ReloadToastMessage.NEWER_REVISION;
        } else if (result.newStatus === this.ChangeStatus.MERGED) {
          toastMessage = ReloadToastMessage.MERGED;
        } else if (result.newStatus === this.ChangeStatus.ABANDONED) {
          toastMessage = ReloadToastMessage.ABANDONED;
        } else if (result.newStatus === this.ChangeStatus.NEW) {
          toastMessage = ReloadToastMessage.RESTORED;
        } else if (result.newMessages) {
          toastMessage = ReloadToastMessage.NEW_MESSAGE;
        }

        if (!toastMessage) {
          this._startUpdateCheckTimer();
          return;
        }

        this._cancelUpdateCheckTimer();
        this.fire('show-alert', {
          message: toastMessage,
          // Persist this alert.
          dismissOnNavigation: true,
          action: 'Reload',
          callback: function() {
            // Load the current change without any patch range.
            Gerrit.Nav.navigateToChange(this._change);
          }.bind(this),
        });
      });
    }, this._serverConfig.change.update_delay * 1000);
  }

  _cancelUpdateCheckTimer() {
    if (this._updateCheckTimerHandle) {
      this.cancelAsync(this._updateCheckTimerHandle);
    }
    this._updateCheckTimerHandle = null;
  }

  _handleVisibilityChange() {
    if (document.hidden && this._updateCheckTimerHandle) {
      this._cancelUpdateCheckTimer();
    } else if (!this._updateCheckTimerHandle) {
      this._startUpdateCheckTimer();
    }
  }

  _handleTopicChanged() {
    this.$.relatedChanges.reload();
  }

  _computeHeaderClass(editMode) {
    const classes = ['header'];
    if (editMode) { classes.push('editMode'); }
    return classes.join(' ');
  }

  _computeEditMode(patchRangeRecord, paramsRecord) {
    if ([patchRangeRecord, paramsRecord].some(arg => arg === undefined)) {
      return undefined;
    }

    if (paramsRecord.base && paramsRecord.base.edit) { return true; }

    const patchRange = patchRangeRecord.base || {};
    return this.patchNumEquals(patchRange.patchNum, this.EDIT_NAME);
  }

  _handleFileActionTap(e) {
    e.preventDefault();
    const controls = this.$.fileListHeader.$.editControls;
    const path = e.detail.path;
    switch (e.detail.action) {
      case GrEditConstants.Actions.DELETE.id:
        controls.openDeleteDialog(path);
        break;
      case GrEditConstants.Actions.OPEN.id:
        Gerrit.Nav.navigateToRelativeUrl(
            Gerrit.Nav.getEditUrlForDiff(this._change, path,
                this._patchRange.patchNum));
        break;
      case GrEditConstants.Actions.RENAME.id:
        controls.openRenameDialog(path);
        break;
      case GrEditConstants.Actions.RESTORE.id:
        controls.openRestoreDialog(path);
        break;
    }
  }

  _computeCommitMessageKey(number, revision) {
    return `c${number}_rev${revision}`;
  }

  _patchNumChanged(patchNumStr) {
    if (!this._selectedRevision) {
      return;
    }

    let patchNum = parseInt(patchNumStr, 10);
    if (patchNumStr === 'edit') {
      patchNum = patchNumStr;
    }

    if (patchNum === this._selectedRevision._number) {
      return;
    }
    this._selectedRevision = Object.values(this._change.revisions).find(
        revision => revision._number === patchNum);
  }

  /**
   * If an edit exists already, load it. Otherwise, toggle edit mode via the
   * navigation API.
   */
  _handleEditTap() {
    const editInfo = Object.values(this._change.revisions).find(info =>
      info._number === this.EDIT_NAME);

    if (editInfo) {
      Gerrit.Nav.navigateToChange(this._change, this.EDIT_NAME);
      return;
    }

    // Avoid putting patch set in the URL unless a non-latest patch set is
    // selected.
    let patchNum;
    if (!this.patchNumEquals(this._patchRange.patchNum,
        this.computeLatestPatchNum(this._allPatchSets))) {
      patchNum = this._patchRange.patchNum;
    }
    Gerrit.Nav.navigateToChange(this._change, patchNum, null, true);
  }

  _handleStopEditTap() {
    Gerrit.Nav.navigateToChange(this._change, this._patchRange.patchNum);
  }

  _resetReplyOverlayFocusStops() {
    this.$.replyOverlay.setFocusStops(this.$.replyDialog.getFocusStops());
  }

  _handleToggleStar(e) {
    this.$.restAPI.saveChangeStarred(e.detail.change._number,
        e.detail.starred);
  }

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

  _computeCurrentRevision(currentRevision, revisions) {
    return currentRevision && revisions && revisions[currentRevision];
  }

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

customElements.define(GrChangeView.is, GrChangeView);
