/**
 * @license
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
(function() {
  'use strict';

  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 reply but do not send notification',
    START_REVIEW: 'Mark as ready for review and send reply',
    SEND: 'Send reply',
  };

  // TODO(logan): Remove once the fix for issue 6841 is stable on
  // googlesource.com.
  const START_REVIEW_MESSAGE = 'This change is ready for review.';

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

  const SEND_REPLY_TIMING_LABEL = 'SendReply';

  Polymer({
    is: '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
     */

    properties: {
      /**
       * @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: '',
      },
      diffDrafts: {
        type: Object,
        observer: '_handleHeightChanged',
      },
      /** @type {!Function} */
      filterReviewerSuggestion: {
        type: Function,
        value() {
          return this._filterReviewerSuggestionGenerator(false);
        },
      },
      /** @type {!Function} */
      filterCCSuggestion: {
        type: Function,
        value() {
          return this._filterReviewerSuggestionGenerator(true);
        },
      },
      permittedLabels: Object,
      /**
       * @type {{ note_db_enabled: boolean }}
       */
      serverConfig: 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)',
      },
      _ccsEnabled: {
        type: Boolean,
        computed: '_computeCCsEnabled(serverConfig)',
      },
      _savingComments: Boolean,
      _reviewersMutated: {
        type: Boolean,
        value: false,
      },
      _labelsChanged: {
        type: Boolean,
        value: false,
      },
      _saveTooltip: {
        type: String,
        value: ButtonTooltips.SAVE,
        readOnly: true,
      },
      _pluginMessage: {
        type: String,
        value: '',
      },
      _sendDisabled: {
        type: Boolean,
        computed: '_computeSendButtonDisabled(_sendButtonLabel, diffDrafts, ' +
            'draft, _reviewersMutated, _labelsChanged, _includeComments, ' +
            'disabled)',
        observer: '_sendDisabledChanged',
      },
    },

    FocusTarget,

    // TODO(logan): Remove once the fix for issue 6841 is stable on
    // googlesource.com.
    START_REVIEW_MESSAGE,

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

    keyBindings: {
      'esc': '_handleEscKey',
      'ctrl+enter meta+enter': '_handleEnterKey',
    },

    observers: [
      '_changeUpdated(change.reviewers.*, change.owner, serverConfig)',
      '_ccsChanged(_ccs.splices)',
      '_reviewersChanged(_reviewers.splices)',
    ],

    attached() {
      this._getAccount().then(account => {
        this._account = account || {};
      });
    },

    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.fire('comment-refresh');
          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.$$(`gr-label-score-row[name="${label}"]`);
      if (!selectorEl) { return; }
      selectorEl.setSelectedValue(value);
    },

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

      return selectorEl.selectedValue;
    },

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

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

    _ccsChanged(splices) {
      if (splices && splices.indexSplices) {
        this._reviewersMutated = true;
        this._processReviewerChange(splices.indexSplices, ReviewerTypes.CC);
      }
    },

    _reviewersChanged(splices) {
      if (splices && splices.indexSplices) {
        this._reviewersMutated = true;
        this._processReviewerChange(splices.indexSplices,
            ReviewerTypes.REVIEWER);
        let key;
        let index;
        let account;
        // Remove any accounts that already exist as a CC.
        for (const splice of splices.indexSplices) {
          for (const addedKey of splice.addedKeys) {
            account = this.get(`_reviewers.${addedKey}`);
            key = this._accountOrGroupKey(account);
            index = this._ccs.findIndex(
                account => this._accountOrGroupKey(account) === key);
            if (index >= 0) {
              this.splice('_ccs', index, 1);
              const message = (account.name || account.email || key) +
                  ' moved from CC to reviewer.';
              this.fire('show-alert', {message});
            }
          }
        }
      }
    },

    _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
     *
     * * TODO(beckysiegel) submit Polymer PR
     * @suppress {checkTypes}
     */
    _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 = 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;

      if (obj.ready && !obj.message) {
        // TODO(logan): The server currently doesn't send email in this case.
        // Insert a dummy message to force an email to be sent. Remove this
        // once the fix for issue 6841 is stable on googlesource.com.
        obj.message = START_REVIEW_MESSAGE;
      }

      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.fire('server-error', {response});
          return {};
        }

        // TODO(logan): Remove once the required API changes are live and stable
        // on googlesource.com.
        return this._maybeSetReady(startReview, response).catch(err => {
          // We catch error here because we still want to treat this as a
          // successful review.
          console.error('error setting ready:', err);
        }).then(() => {
          this.draft = '';
          this._includeComments = true;
          this.fire('send', null, {bubbles: false});
          return accountAdditions;
        });
      }).then(result => {
        this.disabled = false;
        return result;
      }).catch(err => {
        this.disabled = false;
        throw err;
      });
    },

    /**
     * Returns a promise resolving to true if review was successfully posted,
     * false otherwise.
     *
     * TODO(logan): Remove this once the required API changes are live and
     * stable on googlesource.com.
     */
    _maybeSetReady(startReview, response) {
      return this.$.restAPI.getResponseObject(response).then(result => {
        if (!startReview || result.ready) {
          return Promise.resolve();
        }
        // We don't have confirmation that review was started, so attempt to
        // start review explicitly.
        return this.$.restAPI.startReview(
            this.change._number, null, response => {
              // If we see a 409 response code, then that means the server
              // *does* support moving from WIP->ready when posting a
              // review. Only alert user for non-409 failures.
              if (response.status !== 409) {
                this.fire('server-error', {response});
              }
            });
      });
    },

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

      if (response.status !== 400) {
        // This is all restAPI does when there is no custom error handling.
        this.fire('server-error', {response});
        return response;
      }

      // Process the response body, format a better error message, and fire
      // an event for gr-event-manager to display.
      const jsonPromise = this.$.restAPI.getResponseObject(response);
      return jsonPromise.then(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.fire('server-error', {response});
      });
    },

    _computeHideDraftList(drafts) {
      return Object.keys(drafts || {}).length == 0;
    },

    _computeDraftsTitle(drafts) {
      let total = 0;
      for (const file in drafts) {
        if (drafts.hasOwnProperty(file)) {
          total += drafts[file].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, serverConfig) {
      this._rebuildReviewerArrays(changeRecord.base, owner, serverConfig);
    },

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

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

      if (this._ccsEnabled) {
        this._ccs = ccs;
      } else {
        this._ccs = [];
        reviewers = reviewers.concat(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.fire('cancel', null, {bubbles: false});
      this.$.textarea.closeDropdown();
      this._purgeReviewersPendingRemove(true);
      this._rebuildReviewerArrays(this.change.reviewers, this._owner,
          this.serverConfig);
    },

    _saveTapHandler(e) {
      e.preventDefault();
      if (this._ccsEnabled && !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._ccsEnabled && !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,
          detail: {message: EMPTY_REPLY_MESSAGE},
        }));
        return;
      }
      return this.send(this._includeComments, this.canBeStarted)
          .then(keepReviewers => {
            this._purgeReviewersPendingRemove(false, keepReviewers);
          });
    },

    _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.fire('autogrow');
    },

    _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.
      location.href = this.getBaseUrl() + '/c/' + this.change._number;
    },

    _computeSendButtonLabel(canBeStarted) {
      return canBeStarted ? ButtonLabels.START_REVIEW : ButtonLabels.SEND;
    },

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

    _computeCCsEnabled(serverConfig) {
      return serverConfig && serverConfig.note_db_enabled;
    },

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

    _computeSendButtonDisabled(buttonLabel, drafts, text, reviewersMutated,
        labelsChanged, includeComments, disabled) {
      if (disabled) { return true; }
      if (buttonLabel === ButtonLabels.START_REVIEW) { return false; }
      const hasDrafts = includeComments && Object.keys(drafts).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'));
    },
  });
})();
