/**
 * @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 '@polymer/iron-autogrow-textarea/iron-autogrow-textarea.js';
import '../../core/gr-reporting/gr-reporting.js';
import '../../plugins/gr-endpoint-decorator/gr-endpoint-decorator.js';
import '../../shared/gr-account-chip/gr-account-chip.js';
import '../../shared/gr-textarea/gr-textarea.js';
import '../../shared/gr-button/gr-button.js';
import '../../shared/gr-formatted-text/gr-formatted-text.js';
import '../../shared/gr-js-api-interface/gr-js-api-interface.js';
import '../../shared/gr-overlay/gr-overlay.js';
import '../../shared/gr-rest-api-interface/gr-rest-api-interface.js';
import '../../shared/gr-storage/gr-storage.js';
import '../../shared/gr-account-list/gr-account-list.js';
import '../gr-label-scores/gr-label-scores.js';
import '../gr-thread-list/gr-thread-list.js';
import '../../../styles/shared-styles.js';
import '../gr-comment-list/gr-comment-list.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-reply-dialog_html.js';
import {BaseUrlBehavior} from '../../../behaviors/base-url-behavior/base-url-behavior.js';
import {PatchSetBehavior} from '../../../behaviors/gr-patch-set-behavior/gr-patch-set-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 {GrReviewerSuggestionsProvider, SUGGESTIONS_PROVIDERS_USERS_TYPES} from '../../../scripts/gr-reviewer-suggestions-provider/gr-reviewer-suggestions-provider.js';
import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';

const STORAGE_DEBOUNCE_INTERVAL_MS = 400;

const FocusTarget = {
  ANY: 'any',
  BODY: 'body',
  CCS: 'cc',
  REVIEWERS: 'reviewers',
};

const ReviewerTypes = {
  REVIEWER: 'REVIEWER',
  CC: 'CC',
};

const LatestPatchState = {
  LATEST: 'latest',
  CHECKING: 'checking',
  NOT_LATEST: 'not-latest',
};

const ButtonLabels = {
  START_REVIEW: 'Start review',
  SEND: 'Send',
};

const ButtonTooltips = {
  SAVE: 'Save but do not send notification or change review state',
  START_REVIEW: 'Mark as ready for review and send reply',
  SEND: 'Send reply',
};

const EMPTY_REPLY_MESSAGE = 'Cannot send an empty reply.';

const SEND_REPLY_TIMING_LABEL = 'SendReply';

/**
 * @extends Polymer.Element
 */
class GrReplyDialog extends mixinBehaviors( [
  BaseUrlBehavior,
  KeyboardShortcutBehavior,
  PatchSetBehavior,
  RESTClientBehavior,
], GestureEventListeners(
    LegacyElementMixin(
        PolymerElement))) {
  static get template() { return htmlTemplate; }

  static get is() { return 'gr-reply-dialog'; }
  /**
   * Fired when a reply is successfully sent.
   *
   * @event send
   */

  /**
   * Fired when the user presses the cancel button.
   *
   * @event cancel
   */

  /**
   * Fired when the main textarea's value changes, which may have triggered
   * a change in size for the dialog.
   *
   * @event autogrow
   */

  /**
   * Fires to show an alert when a send is attempted on the non-latest patch.
   *
   * @event show-alert
   */

  /**
   * Fires when the reply dialog believes that the server side diff drafts
   * have been updated and need to be refreshed.
   *
   * @event comment-refresh
   */

  /**
   * Fires when the state of the send button (enabled/disabled) changes.
   *
   * @event send-disabled-changed
   */

  constructor() {
    super();
    this.FocusTarget = FocusTarget;
  }

  static get properties() {
    return {
    /**
     * @type {{ _number: number, removable_reviewers: Array }}
     */
      change: Object,
      patchNum: String,
      canBeStarted: {
        type: Boolean,
        value: false,
      },
      disabled: {
        type: Boolean,
        value: false,
        reflectToAttribute: true,
      },
      draft: {
        type: String,
        value: '',
        observer: '_draftChanged',
      },
      quote: {
        type: String,
        value: '',
      },
      /** @type {!Function} */
      filterReviewerSuggestion: {
        type: Function,
        value() {
          return this._filterReviewerSuggestionGenerator(false);
        },
      },
      /** @type {!Function} */
      filterCCSuggestion: {
        type: Function,
        value() {
          return this._filterReviewerSuggestionGenerator(true);
        },
      },
      permittedLabels: Object,
      /**
       * @type {{ commentlinks: Array }}
       */
      projectConfig: Object,
      knownLatestState: String,
      underReview: {
        type: Boolean,
        value: true,
      },

      _account: Object,
      _ccs: Array,
      /** @type {?Object} */
      _ccPendingConfirmation: {
        type: Object,
        observer: '_reviewerPendingConfirmationUpdated',
      },
      _messagePlaceholder: {
        type: String,
        computed: '_computeMessagePlaceholder(canBeStarted)',
      },
      _owner: Object,
      /** @type {?} */
      _pendingConfirmationDetails: Object,
      _includeComments: {
        type: Boolean,
        value: true,
      },
      _reviewers: Array,
      /** @type {?Object} */
      _reviewerPendingConfirmation: {
        type: Object,
        observer: '_reviewerPendingConfirmationUpdated',
      },
      _previewFormatting: {
        type: Boolean,
        value: false,
        observer: '_handleHeightChanged',
      },
      _reviewersPendingRemove: {
        type: Object,
        value: {
          CC: [],
          REVIEWER: [],
        },
      },
      _sendButtonLabel: {
        type: String,
        computed: '_computeSendButtonLabel(canBeStarted)',
      },
      _savingComments: Boolean,
      _reviewersMutated: {
        type: Boolean,
        value: false,
      },
      _labelsChanged: {
        type: Boolean,
        value: false,
      },
      _saveTooltip: {
        type: String,
        value: ButtonTooltips.SAVE,
        readOnly: true,
      },
      _pluginMessage: {
        type: String,
        value: '',
      },
      _commentEditing: {
        type: Boolean,
        value: false,
      },
      _sendDisabled: {
        type: Boolean,
        computed: '_computeSendButtonDisabled(canBeStarted, ' +
          'draftCommentThreads, draft, _reviewersMutated, _labelsChanged, ' +
          '_includeComments, disabled, _commentEditing)',
        observer: '_sendDisabledChanged',
      },
      draftCommentThreads: {
        type: Array,
        observer: '_handleHeightChanged',
      },
    };
  }

  get keyBindings() {
    return {
      'esc': '_handleEscKey',
      'ctrl+enter meta+enter': '_handleEnterKey',
    };
  }

  static get observers() {
    return [
      '_changeUpdated(change.reviewers.*, change.owner)',
      '_ccsChanged(_ccs.splices)',
      '_reviewersChanged(_reviewers.splices)',
    ];
  }

  /** @override */
  attached() {
    super.attached();
    this._getAccount().then(account => {
      this._account = account || {};
    });

    this.addEventListener('comment-editing-changed', e => {
      this._commentEditing = e.detail;
    });
  }

  /** @override */
  ready() {
    super.ready();
    this.$.jsAPI.addElement(this.$.jsAPI.Element.REPLY_DIALOG, this);
  }

  open(opt_focusTarget) {
    this.knownLatestState = LatestPatchState.CHECKING;
    this.fetchChangeUpdates(this.change, this.$.restAPI)
        .then(result => {
          this.knownLatestState = result.isLatest ?
            LatestPatchState.LATEST : LatestPatchState.NOT_LATEST;
        });

    this._focusOn(opt_focusTarget);
    if (this.quote && this.quote.length) {
      // If a reply quote has been provided, use it and clear the property.
      this.draft = this.quote;
      this.quote = '';
    } else {
      // Otherwise, check for an unsaved draft in localstorage.
      this.draft = this._loadStoredDraft();
    }
    if (this.$.restAPI.hasPendingDiffDrafts()) {
      this._savingComments = true;
      this.$.restAPI.awaitPendingDiffDrafts().then(() => {
        this.dispatchEvent(new CustomEvent('comment-refresh', {
          composed: true, bubbles: true,
        }));
        this._savingComments = false;
      });
    }
  }

  focus() {
    this._focusOn(FocusTarget.ANY);
  }

  getFocusStops() {
    const end = this._sendDisabled ? this.$.cancelButton : this.$.sendButton;
    return {
      start: this.$.reviewers.focusStart,
      end,
    };
  }

  setLabelValue(label, value) {
    const selectorEl =
        this.$.labelScores.shadowRoot
            .querySelector(`gr-label-score-row[name="${label}"]`);
    if (!selectorEl) { return; }
    selectorEl.setSelectedValue(value);
  }

  getLabelValue(label) {
    const selectorEl =
        this.$.labelScores.shadowRoot
            .querySelector(`gr-label-score-row[name="${label}"]`);
    if (!selectorEl) { return null; }

    return selectorEl.selectedValue;
  }

  _handleEscKey(e) {
    this.cancel();
  }

  _handleEnterKey(e) {
    this._submit();
  }

  _ccsChanged(splices) {
    this._reviewerTypeChanged(splices, ReviewerTypes.CC);
  }

  _reviewersChanged(splices) {
    this._reviewerTypeChanged(splices, ReviewerTypes.REVIEWER);
  }

  _reviewerTypeChanged(splices, reviewerType) {
    if (splices && splices.indexSplices) {
      this._reviewersMutated = true;
      this._processReviewerChange(splices.indexSplices,
          reviewerType);
      let key;
      let index;
      let account;
      // Remove any accounts that already exist as a CC for reviewer
      // or vice versa.
      const isReviewer = ReviewerTypes.REVIEWER === reviewerType;
      for (const splice of splices.indexSplices) {
        for (let i = 0; i < splice.addedCount; i++) {
          account = splice.object[splice.index + i];
          key = this._accountOrGroupKey(account);
          const array = isReviewer ? this._ccs : this._reviewers;
          index = array.findIndex(
              account => this._accountOrGroupKey(account) === key);
          if (index >= 0) {
            this.splice(isReviewer ? '_ccs' : '_reviewers', index, 1);
            const moveFrom = isReviewer ? 'CC' : 'reviewer';
            const moveTo = isReviewer ? 'reviewer' : 'CC';
            const message = (account.name || account.email || key) +
                ` moved from ${moveFrom} to ${moveTo}.`;
            this.dispatchEvent(new CustomEvent('show-alert', {
              detail: {message},
              composed: true, bubbles: true,
            }));
          }
        }
      }
    }
  }

  _processReviewerChange(indexSplices, type) {
    for (const splice of indexSplices) {
      for (const account of splice.removed) {
        if (!this._reviewersPendingRemove[type]) {
          console.err('Invalid type ' + type + ' for reviewer.');
          return;
        }
        this._reviewersPendingRemove[type].push(account);
      }
    }
  }

  /**
   * Resets the state of the _reviewersPendingRemove object, and removes
   * accounts if necessary.
   *
   * @param {boolean} isCancel true if the action is a cancel.
   * @param {Object=} opt_accountIdsTransferred map of account IDs that must
   *     not be removed, because they have been readded in another state.
   */
  _purgeReviewersPendingRemove(isCancel, opt_accountIdsTransferred) {
    let reviewerArr;
    const keep = opt_accountIdsTransferred || {};
    for (const type in this._reviewersPendingRemove) {
      if (this._reviewersPendingRemove.hasOwnProperty(type)) {
        if (!isCancel) {
          reviewerArr = this._reviewersPendingRemove[type];
          for (let i = 0; i < reviewerArr.length; i++) {
            if (!keep[reviewerArr[i]._account_id]) {
              this._removeAccount(reviewerArr[i], type);
            }
          }
        }
        this._reviewersPendingRemove[type] = [];
      }
    }
  }

  /**
   * Removes an account from the change, both on the backend and the client.
   * Does nothing if the account is a pending addition.
   *
   * @param {!Object} account
   * @param {string} type
   */
  _removeAccount(account, type) {
    if (account._pendingAdd) { return; }

    return this.$.restAPI.removeChangeReviewer(this.change._number,
        account._account_id).then(response => {
      if (!response.ok) { return response; }

      const reviewers = this.change.reviewers[type] || [];
      for (let i = 0; i < reviewers.length; i++) {
        if (reviewers[i]._account_id == account._account_id) {
          this.splice(`change.reviewers.${type}`, i, 1);
          break;
        }
      }
    });
  }

  _mapReviewer(reviewer) {
    let reviewerId;
    let confirmed;
    if (reviewer.account) {
      reviewerId = reviewer.account._account_id || reviewer.account.email;
    } else if (reviewer.group) {
      reviewerId = decodeURIComponent(reviewer.group.id);
      confirmed = reviewer.group.confirmed;
    }
    return {reviewer: reviewerId, confirmed};
  }

  send(includeComments, startReview) {
    this.$.reporting.time(SEND_REPLY_TIMING_LABEL);
    const labels = this.$.labelScores.getLabelValues();

    const obj = {
      drafts: includeComments ? 'PUBLISH_ALL_REVISIONS' : 'KEEP',
      labels,
    };

    if (startReview) {
      obj.ready = true;
    }

    if (this.draft != null) {
      obj.message = this.draft;
    }

    const accountAdditions = {};
    obj.reviewers = this.$.reviewers.additions().map(reviewer => {
      if (reviewer.account) {
        accountAdditions[reviewer.account._account_id] = true;
      }
      return this._mapReviewer(reviewer);
    });
    const ccsEl = this.$.ccs;
    if (ccsEl) {
      for (let reviewer of ccsEl.additions()) {
        if (reviewer.account) {
          accountAdditions[reviewer.account._account_id] = true;
        }
        reviewer = this._mapReviewer(reviewer);
        reviewer.state = 'CC';
        obj.reviewers.push(reviewer);
      }
    }

    this.disabled = true;

    const errFn = this._handle400Error.bind(this);
    return this._saveReview(obj, errFn)
        .then(response => {
          if (!response) {
            // Null or undefined response indicates that an error handler
            // took responsibility, so just return.
            return {};
          }
          if (!response.ok) {
            this.dispatchEvent(new CustomEvent('server-error', {
              detail: {response},
              composed: true, bubbles: true,
            }));
            return {};
          }

          this.draft = '';
          this._includeComments = true;
          this.dispatchEvent(new CustomEvent('send', {
            composed: true, bubbles: false,
          }));
          return accountAdditions;
        })
        .then(result => {
          this.disabled = false;
          return result;
        })
        .catch(err => {
          this.disabled = false;
          throw err;
        });
  }

  _focusOn(section) {
    // Safeguard- always want to focus on something.
    if (!section || section === FocusTarget.ANY) {
      section = this._chooseFocusTarget();
    }
    if (section === FocusTarget.BODY) {
      const textarea = this.$.textarea;
      textarea.async(textarea.getNativeTextarea()
          .focus.bind(textarea.getNativeTextarea()));
    } else if (section === FocusTarget.REVIEWERS) {
      const reviewerEntry = this.$.reviewers.focusStart;
      reviewerEntry.async(reviewerEntry.focus);
    } else if (section === FocusTarget.CCS) {
      const ccEntry = this.$.ccs.focusStart;
      ccEntry.async(ccEntry.focus);
    }
  }

  _chooseFocusTarget() {
    // If we are the owner and the reviewers field is empty, focus on that.
    if (this._account && this.change && this.change.owner &&
        this._account._account_id === this.change.owner._account_id &&
        (!this._reviewers || this._reviewers.length === 0)) {
      return FocusTarget.REVIEWERS;
    }

    // Default to BODY.
    return FocusTarget.BODY;
  }

  _handle400Error(response) {
    // A call to _saveReview could fail with a server error if erroneous
    // reviewers were requested. This is signalled with a 400 Bad Request
    // status. The default gr-rest-api-interface error handling would
    // result in a large JSON response body being displayed to the user in
    // the gr-error-manager toast.
    //
    // We can modify the error handling behavior by passing this function
    // through to restAPI as a custom error handling function. Since we're
    // short-circuiting restAPI we can do our own response parsing and fire
    // the server-error ourselves.
    //
    this.disabled = false;

    // Using response.clone() here, because getResponseObject() and
    // potentially the generic error handler will want to call text() on the
    // response object, which can only be done once per object.
    const jsonPromise = this.$.restAPI.getResponseObject(response.clone());
    return jsonPromise.then(result => {
      // Only perform custom error handling for 400s and a parseable
      // ReviewResult response.
      if (response.status === 400 && result) {
        const errors = [];
        for (const state of ['reviewers', 'ccs']) {
          if (!result.hasOwnProperty(state)) { continue; }
          for (const reviewer of Object.values(result[state])) {
            if (reviewer.error) {
              errors.push(reviewer.error);
            }
          }
        }
        response = {
          ok: false,
          status: response.status,
          text() { return Promise.resolve(errors.join(', ')); },
        };
      }
      this.dispatchEvent(new CustomEvent('server-error', {
        detail: {response},
        composed: true, bubbles: true,
      }));
      return null; // Means that the error has been handled.
    });
  }

  _computeHideDraftList(draftCommentThreads) {
    return draftCommentThreads.length === 0;
  }

  _computeDraftsTitle(draftCommentThreads) {
    const total = draftCommentThreads.length;
    if (total == 0) { return ''; }
    if (total == 1) { return '1 Draft'; }
    if (total > 1) { return total + ' Drafts'; }
  }

  _computeMessagePlaceholder(canBeStarted) {
    return canBeStarted ?
      'Add a note for your reviewers...' :
      'Say something nice...';
  }

  _changeUpdated(changeRecord, owner) {
    // Polymer 2: check for undefined
    if ([changeRecord, owner].some(arg => arg === undefined)) {
      return;
    }

    this._rebuildReviewerArrays(changeRecord.base, owner);
  }

  _rebuildReviewerArrays(change, owner) {
    this._owner = owner;

    const reviewers = [];
    const ccs = [];

    for (const key in change) {
      if (change.hasOwnProperty(key)) {
        if (key !== 'REVIEWER' && key !== 'CC') {
          console.warn('unexpected reviewer state:', key);
          continue;
        }
        for (const entry of change[key]) {
          if (entry._account_id === owner._account_id) {
            continue;
          }
          switch (key) {
            case 'REVIEWER':
              reviewers.push(entry);
              break;
            case 'CC':
              ccs.push(entry);
              break;
          }
        }
      }
    }

    this._ccs = ccs;
    this._reviewers = reviewers;
  }

  _accountOrGroupKey(entry) {
    return entry.id || entry._account_id;
  }

  /**
   * Generates a function to filter out reviewer/CC entries. When isCCs is
   * truthy, the function filters out entries that already exist in this._ccs.
   * When falsy, the function filters entries that exist in this._reviewers.
   *
   * @param {boolean} isCCs
   * @return {!Function}
   */
  _filterReviewerSuggestionGenerator(isCCs) {
    return suggestion => {
      let entry;
      if (suggestion.account) {
        entry = suggestion.account;
      } else if (suggestion.group) {
        entry = suggestion.group;
      } else {
        console.warn(
            'received suggestion that was neither account nor group:',
            suggestion);
      }
      if (entry._account_id === this._owner._account_id) {
        return false;
      }

      const key = this._accountOrGroupKey(entry);
      const finder = entry => this._accountOrGroupKey(entry) === key;
      if (isCCs) {
        return this._ccs.find(finder) === undefined;
      }
      return this._reviewers.find(finder) === undefined;
    };
  }

  _getAccount() {
    return this.$.restAPI.getAccount();
  }

  _cancelTapHandler(e) {
    e.preventDefault();
    this.cancel();
  }

  cancel() {
    this.dispatchEvent(new CustomEvent('cancel', {
      composed: true, bubbles: false,
    }));
    this.$.textarea.closeDropdown();
    this._purgeReviewersPendingRemove(true);
    this._rebuildReviewerArrays(this.change.reviewers, this._owner);
  }

  _saveClickHandler(e) {
    e.preventDefault();
    if (!this.$.ccs.submitEntryText()) {
      // Do not proceed with the save if there is an invalid email entry in
      // the text field of the CC entry.
      return;
    }
    this.send(this._includeComments, false).then(keepReviewers => {
      this._purgeReviewersPendingRemove(false, keepReviewers);
    });
  }

  _sendTapHandler(e) {
    e.preventDefault();
    this._submit();
  }

  _submit() {
    if (!this.$.ccs.submitEntryText()) {
      // Do not proceed with the send if there is an invalid email entry in
      // the text field of the CC entry.
      return;
    }
    if (this._sendDisabled) {
      this.dispatchEvent(new CustomEvent('show-alert', {
        bubbles: true,
        composed: true,
        detail: {message: EMPTY_REPLY_MESSAGE},
      }));
      return;
    }
    return this.send(this._includeComments, this.canBeStarted)
        .then(keepReviewers => {
          this._purgeReviewersPendingRemove(false, keepReviewers);
        })
        .catch(err => {
          this.dispatchEvent(new CustomEvent('show-error', {
            bubbles: true,
            composed: true,
            detail: {message: `Error submitting review ${err}`},
          }));
        });
  }

  _saveReview(review, opt_errFn) {
    return this.$.restAPI.saveChangeReview(this.change._number, this.patchNum,
        review, opt_errFn);
  }

  _reviewerPendingConfirmationUpdated(reviewer) {
    if (reviewer === null) {
      this.$.reviewerConfirmationOverlay.close();
    } else {
      this._pendingConfirmationDetails =
          this._ccPendingConfirmation || this._reviewerPendingConfirmation;
      this.$.reviewerConfirmationOverlay.open();
    }
  }

  _confirmPendingReviewer() {
    if (this._ccPendingConfirmation) {
      this.$.ccs.confirmGroup(this._ccPendingConfirmation.group);
      this._focusOn(FocusTarget.CCS);
    } else {
      this.$.reviewers.confirmGroup(this._reviewerPendingConfirmation.group);
      this._focusOn(FocusTarget.REVIEWERS);
    }
  }

  _cancelPendingReviewer() {
    this._ccPendingConfirmation = null;
    this._reviewerPendingConfirmation = null;

    const target =
        this._ccPendingConfirmation ? FocusTarget.CCS : FocusTarget.REVIEWERS;
    this._focusOn(target);
  }

  _getStorageLocation() {
    // Tests trigger this method without setting change.
    if (!this.change) { return {}; }
    return {
      changeNum: this.change._number,
      patchNum: '@change',
      path: '@change',
    };
  }

  _loadStoredDraft() {
    const draft = this.$.storage.getDraftComment(this._getStorageLocation());
    return draft ? draft.message : '';
  }

  _handleAccountTextEntry() {
    // When either of the account entries has input added to the autocomplete,
    // it should trigger the save button to enable/
    //
    // Note: if the text is removed, the save button will not get disabled.
    this._reviewersMutated = true;
  }

  _draftChanged(newDraft, oldDraft) {
    this.debounce('store', () => {
      if (!newDraft.length && oldDraft) {
        // If the draft has been modified to be empty, then erase the storage
        // entry.
        this.$.storage.eraseDraftComment(this._getStorageLocation());
      } else if (newDraft.length) {
        this.$.storage.setDraftComment(this._getStorageLocation(),
            this.draft);
      }
    }, STORAGE_DEBOUNCE_INTERVAL_MS);
  }

  _handleHeightChanged(e) {
    this.dispatchEvent(new CustomEvent('autogrow', {
      composed: true, bubbles: true,
    }));
  }

  _handleLabelsChanged() {
    this._labelsChanged = Object.keys(
        this.$.labelScores.getLabelValues()).length !== 0;
  }

  _isState(knownLatestState, value) {
    return knownLatestState === value;
  }

  _reload() {
    // Load the current change without any patch range.
    GerritNav.navigateToChange(this.change);
    this.cancel();
  }

  _computeSendButtonLabel(canBeStarted) {
    return canBeStarted ? ButtonLabels.SEND + ' and ' +
        ButtonLabels.START_REVIEW : ButtonLabels.SEND;
  }

  _computeSendButtonTooltip(canBeStarted) {
    return canBeStarted ? ButtonTooltips.START_REVIEW : ButtonTooltips.SEND;
  }

  _computeSavingLabelClass(savingComments) {
    return savingComments ? 'saving' : '';
  }

  _computeSendButtonDisabled(
      canBeStarted, draftCommentThreads, text, reviewersMutated,
      labelsChanged, includeComments, disabled, commentEditing) {
    // Polymer 2: check for undefined
    if ([
      canBeStarted,
      draftCommentThreads,
      text,
      reviewersMutated,
      labelsChanged,
      includeComments,
      disabled,
      commentEditing,
    ].some(arg => arg === undefined)) {
      return undefined;
    }

    if (commentEditing || disabled) { return true; }
    if (canBeStarted === true) { return false; }
    const hasDrafts = includeComments && draftCommentThreads.length;
    return !hasDrafts && !text.length && !reviewersMutated && !labelsChanged;
  }

  _computePatchSetWarning(patchNum, labelsChanged) {
    let str = `Patch ${patchNum} is not latest.`;
    if (labelsChanged) {
      str += ' Voting on a non-latest patch will have no effect.';
    }
    return str;
  }

  setPluginMessage(message) {
    this._pluginMessage = message;
  }

  _sendDisabledChanged(sendDisabled) {
    this.dispatchEvent(new CustomEvent('send-disabled-changed'));
  }

  _getReviewerSuggestionsProvider(change) {
    const provider = GrReviewerSuggestionsProvider.create(this.$.restAPI,
        change._number, SUGGESTIONS_PROVIDERS_USERS_TYPES.REVIEWER);
    provider.init();
    return provider;
  }

  _getCcSuggestionsProvider(change) {
    const provider = GrReviewerSuggestionsProvider.create(this.$.restAPI,
        change._number, SUGGESTIONS_PROVIDERS_USERS_TYPES.CC);
    provider.init();
    return provider;
  }

  _onThreadListModified() {
    // TODO(taoalpha): this won't propogate the changes to the files
    // should consider replacing this with either top level events
    // or gerrit level events

    // emit the event so change-view can also get updated with latest changes
    this.dispatchEvent(new CustomEvent('comment-refresh', {
      composed: true, bubbles: true,
    }));
  }
}

customElements.define(GrReplyDialog.is, GrReplyDialog);
