/**
 * @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 = 400;
  const TOAST_DEBOUNCE_INTERVAL = 200;

  const SAVING_MESSAGE = 'Saving';
  const DRAFT_SINGULAR = 'draft...';
  const DRAFT_PLURAL = 'drafts...';
  const SAVED_MESSAGE = 'All changes saved';

  const REPORT_CREATE_DRAFT = 'CreateDraftComment';
  const REPORT_UPDATE_DRAFT = 'UpdateDraftComment';
  const REPORT_DISCARD_DRAFT = 'DiscardDraftComment';

  const FILE = 'FILE';

  /**
    * @appliesMixin Gerrit.FireMixin
    * @appliesMixin Gerrit.KeyboardShortcutMixin
    */
  class GrComment extends Polymer.mixinBehaviors( [
    Gerrit.FireBehavior,
    Gerrit.KeyboardShortcutBehavior,
  ], Polymer.GestureEventListeners(
      Polymer.LegacyElementMixin(
          Polymer.Element))) {
    static get is() { return 'gr-comment'; }
    /**
     * Fired when the create fix comment action is triggered.
     *
     * @event create-fix-comment
     */

    /**
     * Fired when this comment is discarded.
     *
     * @event comment-discard
     */

    /**
     * Fired when this comment is saved.
     *
     * @event comment-save
     */

    /**
     * Fired when this comment is updated.
     *
     * @event comment-update
     */

    /**
     * Fired when the comment's timestamp is tapped.
     *
     * @event comment-anchor-tap
     */

    static get properties() {
      return {
        changeNum: String,
        /** @type {!Gerrit.Comment} */
        comment: {
          type: Object,
          notify: true,
          observer: '_commentChanged',
        },
        isRobotComment: {
          type: Boolean,
          value: false,
          reflectToAttribute: true,
        },
        disabled: {
          type: Boolean,
          value: false,
          reflectToAttribute: true,
        },
        draft: {
          type: Boolean,
          value: false,
          observer: '_draftChanged',
        },
        editing: {
          type: Boolean,
          value: false,
          observer: '_editingChanged',
        },
        discarding: {
          type: Boolean,
          value: false,
          reflectToAttribute: true,
        },
        hasChildren: Boolean,
        patchNum: String,
        showActions: Boolean,
        _showHumanActions: Boolean,
        _showRobotActions: Boolean,
        collapsed: {
          type: Boolean,
          value: true,
          observer: '_toggleCollapseClass',
        },
        /** @type {?} */
        projectConfig: Object,
        robotButtonDisabled: Boolean,
        _isAdmin: {
          type: Boolean,
          value: false,
        },

        _xhrPromise: Object, // Used for testing.
        _messageText: {
          type: String,
          value: '',
          observer: '_messageTextChanged',
        },
        commentSide: String,
        side: String,

        resolved: Boolean,

        _numPendingDraftRequests: {
          type: Object,
          value:
            {number: 0}, // Intentional to share the object across instances.
        },

        _enableOverlay: {
          type: Boolean,
          value: false,
        },

        /**
       * Property for storing references to overlay elements. When the overlays
       * are moved to Gerrit.getRootElement() to be shown they are no-longer
       * children, so they can't be queried along the tree, so they are stored
       * here.
       */
        _overlays: {
          type: Object,
          value: () => ({}),
        },
      };
    }

    static get observers() {
      return [
        '_commentMessageChanged(comment.message)',
        '_loadLocalDraft(changeNum, patchNum, comment)',
        '_isRobotComment(comment)',
        '_calculateActionstoShow(showActions, isRobotComment)',
      ];
    }

    get keyBindings() {
      return {
        'ctrl+enter meta+enter ctrl+s meta+s': '_handleSaveKey',
        'esc': '_handleEsc',
      };
    }

    attached() {
      super.attached();
      if (this.editing) {
        this.collapsed = false;
      } else if (this.comment) {
        this.collapsed = this.comment.collapsed;
      }
      this._getIsAdmin().then(isAdmin => {
        this._isAdmin = isAdmin;
      });
    }

    detached() {
      super.detached();
      this.cancelDebouncer('fire-update');
      if (this.textarea) {
        this.textarea.closeDropdown();
      }
    }

    get textarea() {
      return this.shadowRoot.querySelector('#editTextarea');
    }

    get confirmDeleteOverlay() {
      if (!this._overlays.confirmDelete) {
        this._enableOverlay = true;
        Polymer.dom.flush();
        this._overlays.confirmDelete = this.shadowRoot
            .querySelector('#confirmDeleteOverlay');
      }
      return this._overlays.confirmDelete;
    }

    get confirmDiscardOverlay() {
      if (!this._overlays.confirmDiscard) {
        this._enableOverlay = true;
        Polymer.dom.flush();
        this._overlays.confirmDiscard = this.shadowRoot
            .querySelector('#confirmDiscardOverlay');
      }
      return this._overlays.confirmDiscard;
    }

    _computeShowHideIcon(collapsed) {
      return collapsed ? 'gr-icons:expand-more' : 'gr-icons:expand-less';
    }

    _calculateActionstoShow(showActions, isRobotComment) {
      // Polymer 2: check for undefined
      if ([showActions, isRobotComment].some(arg => arg === undefined)) {
        return;
      }

      this._showHumanActions = showActions && !isRobotComment;
      this._showRobotActions = showActions && isRobotComment;
    }

    _isRobotComment(comment) {
      this.isRobotComment = !!comment.robot_id;
    }

    isOnParent() {
      return this.side === 'PARENT';
    }

    _getIsAdmin() {
      return this.$.restAPI.getIsAdmin();
    }

    /**
     * @param {*=} opt_comment
     */
    save(opt_comment) {
      let comment = opt_comment;
      if (!comment) {
        comment = this.comment;
      }

      this.set('comment.message', this._messageText);
      this.editing = false;
      this.disabled = true;

      if (!this._messageText) {
        return this._discardDraft();
      }

      this._xhrPromise = this._saveDraft(comment).then(response => {
        this.disabled = false;
        if (!response.ok) { return response; }

        this._eraseDraftComment();
        return this.$.restAPI.getResponseObject(response).then(obj => {
          const resComment = obj;
          resComment.__draft = true;
          // Maintain the ephemeral draft ID for identification by other
          // elements.
          if (this.comment.__draftID) {
            resComment.__draftID = this.comment.__draftID;
          }
          resComment.__commentSide = this.commentSide;
          this.comment = resComment;
          this._fireSave();
          return obj;
        });
      }).catch(err => {
        this.disabled = false;
        throw err;
      });

      return this._xhrPromise;
    }

    _eraseDraftComment() {
      // Prevents a race condition in which removing the draft comment occurs
      // prior to it being saved.
      this.cancelDebouncer('store');

      this.$.storage.eraseDraftComment({
        changeNum: this.changeNum,
        patchNum: this._getPatchNum(),
        path: this.comment.path,
        line: this.comment.line,
        range: this.comment.range,
      });
    }

    _commentChanged(comment) {
      this.editing = !!comment.__editing;
      this.resolved = !comment.unresolved;
      if (this.editing) { // It's a new draft/reply, notify.
        this._fireUpdate();
      }
    }

    /**
     * @param {!Object=} opt_mixin
     *
     * @return {!Object}
     */
    _getEventPayload(opt_mixin) {
      return Object.assign({}, opt_mixin, {
        comment: this.comment,
        patchNum: this.patchNum,
      });
    }

    _fireSave() {
      this.fire('comment-save', this._getEventPayload());
    }

    _fireUpdate() {
      this.debounce('fire-update', () => {
        this.fire('comment-update', this._getEventPayload());
      });
    }

    _draftChanged(draft) {
      this.$.container.classList.toggle('draft', draft);
    }

    _editingChanged(editing, previousValue) {
      // Polymer 2: observer fires when at least one property is defined.
      // Do nothing to prevent comment.__editing being overwritten
      // if previousValue is undefined
      if (previousValue === undefined) return;

      this.$.container.classList.toggle('editing', editing);
      if (this.comment && this.comment.id) {
        this.$$('.cancel').hidden = !editing;
      }
      if (this.comment) {
        this.comment.__editing = this.editing;
      }
      if (editing != !!previousValue) {
        // To prevent event firing on comment creation.
        this._fireUpdate();
      }
      if (editing) {
        this.async(() => {
          Polymer.dom.flush();
          this.textarea.putCursorAtEnd();
        }, 1);
      }
    }

    _computeDeleteButtonClass(isAdmin, draft) {
      return isAdmin && !draft ? 'showDeleteButtons' : '';
    }

    _computeSaveDisabled(draft, comment, resolved) {
      // If resolved state has changed and a msg exists, save should be enabled.
      if (!comment || comment.unresolved === resolved && draft) {
        return false;
      }
      return !draft || draft.trim() === '';
    }

    _handleSaveKey(e) {
      if (!this._computeSaveDisabled(this._messageText, this.comment,
          this.resolved)) {
        e.preventDefault();
        this._handleSave(e);
      }
    }

    _handleEsc(e) {
      if (!this._messageText.length) {
        e.preventDefault();
        this._handleCancel(e);
      }
    }

    _handleToggleCollapsed() {
      this.collapsed = !this.collapsed;
    }

    _toggleCollapseClass(collapsed) {
      if (collapsed) {
        this.$.container.classList.add('collapsed');
      } else {
        this.$.container.classList.remove('collapsed');
      }
    }

    _commentMessageChanged(message) {
      this._messageText = message || '';
    }

    _messageTextChanged(newValue, oldValue) {
      if (!this.comment || (this.comment && this.comment.id)) {
        return;
      }

      this.debounce('store', () => {
        const message = this._messageText;
        const commentLocation = {
          changeNum: this.changeNum,
          patchNum: this._getPatchNum(),
          path: this.comment.path,
          line: this.comment.line,
          range: this.comment.range,
        };

        if ((!this._messageText || !this._messageText.length) && oldValue) {
          // If the draft has been modified to be empty, then erase the storage
          // entry.
          this.$.storage.eraseDraftComment(commentLocation);
        } else {
          this.$.storage.setDraftComment(commentLocation, message);
        }
      }, STORAGE_DEBOUNCE_INTERVAL);
    }

    _handleAnchorClick(e) {
      e.preventDefault();
      if (!this.comment.line) {
        return;
      }
      this.dispatchEvent(new CustomEvent('comment-anchor-tap', {
        bubbles: true,
        composed: true,
        detail: {
          number: this.comment.line || FILE,
          side: this.side,
        },
      }));
    }

    _handleEdit(e) {
      e.preventDefault();
      this._messageText = this.comment.message;
      this.editing = true;
      this.$.reporting.recordDraftInteraction();
    }

    _handleSave(e) {
      e.preventDefault();

      // Ignore saves started while already saving.
      if (this.disabled) {
        return;
      }
      const timingLabel = this.comment.id ?
        REPORT_UPDATE_DRAFT : REPORT_CREATE_DRAFT;
      const timer = this.$.reporting.getTimer(timingLabel);
      this.set('comment.__editing', false);
      return this.save().then(() => { timer.end(); });
    }

    _handleCancel(e) {
      e.preventDefault();

      if (!this.comment.message ||
          this.comment.message.trim().length === 0 ||
          !this.comment.id) {
        this._fireDiscard();
        return;
      }
      this._messageText = this.comment.message;
      this.editing = false;
    }

    _fireDiscard() {
      this.cancelDebouncer('fire-update');
      this.fire('comment-discard', this._getEventPayload());
    }

    _handleFix() {
      this.dispatchEvent(new CustomEvent('create-fix-comment', {
        bubbles: true,
        composed: true,
        detail: this._getEventPayload(),
      }));
    }

    _handleDiscard(e) {
      e.preventDefault();
      this.$.reporting.recordDraftInteraction();

      if (!this._messageText) {
        this._discardDraft();
        return;
      }

      this._openOverlay(this.confirmDiscardOverlay).then(() => {
        this.confirmDiscardOverlay.querySelector('#confirmDiscardDialog')
            .resetFocus();
      });
    }

    _handleConfirmDiscard(e) {
      e.preventDefault();
      const timer = this.$.reporting.getTimer(REPORT_DISCARD_DRAFT);
      this._closeConfirmDiscardOverlay();
      return this._discardDraft().then(() => { timer.end(); });
    }

    _discardDraft() {
      if (!this.comment.__draft) {
        throw Error('Cannot discard a non-draft comment.');
      }
      this.discarding = true;
      this.editing = false;
      this.disabled = true;
      this._eraseDraftComment();

      if (!this.comment.id) {
        this.disabled = false;
        this._fireDiscard();
        return;
      }

      this._xhrPromise = this._deleteDraft(this.comment).then(response => {
        this.disabled = false;
        if (!response.ok) {
          this.discarding = false;
          return response;
        }

        this._fireDiscard();
      }).catch(err => {
        this.disabled = false;
        throw err;
      });

      return this._xhrPromise;
    }

    _closeConfirmDiscardOverlay() {
      this._closeOverlay(this.confirmDiscardOverlay);
    }

    _getSavingMessage(numPending) {
      if (numPending === 0) {
        return SAVED_MESSAGE;
      }
      return [
        SAVING_MESSAGE,
        numPending,
        numPending === 1 ? DRAFT_SINGULAR : DRAFT_PLURAL,
      ].join(' ');
    }

    _showStartRequest() {
      const numPending = ++this._numPendingDraftRequests.number;
      this._updateRequestToast(numPending);
    }

    _showEndRequest() {
      const numPending = --this._numPendingDraftRequests.number;
      this._updateRequestToast(numPending);
    }

    _handleFailedDraftRequest() {
      this._numPendingDraftRequests.number--;

      // Cancel the debouncer so that error toasts from the error-manager will
      // not be overridden.
      this.cancelDebouncer('draft-toast');
    }

    _updateRequestToast(numPending) {
      const message = this._getSavingMessage(numPending);
      this.debounce('draft-toast', () => {
        // Note: the event is fired on the body rather than this element because
        // this element may not be attached by the time this executes, in which
        // case the event would not bubble.
        document.body.dispatchEvent(new CustomEvent(
            'show-alert', {detail: {message}, bubbles: true, composed: true}));
      }, TOAST_DEBOUNCE_INTERVAL);
    }

    _saveDraft(draft) {
      this._showStartRequest();
      return this.$.restAPI.saveDiffDraft(this.changeNum, this.patchNum, draft)
          .then(result => {
            if (result.ok) {
              this._showEndRequest();
            } else {
              this._handleFailedDraftRequest();
            }
            return result;
          });
    }

    _deleteDraft(draft) {
      this._showStartRequest();
      return this.$.restAPI.deleteDiffDraft(this.changeNum, this.patchNum,
          draft).then(result => {
        if (result.ok) {
          this._showEndRequest();
        } else {
          this._handleFailedDraftRequest();
        }
        return result;
      });
    }

    _getPatchNum() {
      return this.isOnParent() ? 'PARENT' : this.patchNum;
    }

    _loadLocalDraft(changeNum, patchNum, comment) {
      // Polymer 2: check for undefined
      if ([changeNum, patchNum, comment].some(arg => arg === undefined)) {
        return;
      }

      // Only apply local drafts to comments that haven't been saved
      // remotely, and haven't been given a default message already.
      //
      // Don't get local draft if there is another comment that is currently
      // in an editing state.
      if (!comment || comment.id || comment.message || comment.__otherEditing) {
        delete comment.__otherEditing;
        return;
      }

      const draft = this.$.storage.getDraftComment({
        changeNum,
        patchNum: this._getPatchNum(),
        path: comment.path,
        line: comment.line,
        range: comment.range,
      });

      if (draft) {
        this.set('comment.message', draft.message);
      }
    }

    _handleToggleResolved() {
      this.$.reporting.recordDraftInteraction();
      this.resolved = !this.resolved;
      // Modify payload instead of this.comment, as this.comment is passed from
      // the parent by ref.
      const payload = this._getEventPayload();
      payload.comment.unresolved = !this.$.resolvedCheckbox.checked;
      this.fire('comment-update', payload);
      if (!this.editing) {
        // Save the resolved state immediately.
        this.save(payload.comment);
      }
    }

    _handleCommentDelete() {
      this._openOverlay(this.confirmDeleteOverlay);
    }

    _handleCancelDeleteComment() {
      this._closeOverlay(this.confirmDeleteOverlay);
    }

    _openOverlay(overlay) {
      Polymer.dom(Gerrit.getRootElement()).appendChild(overlay);
      return overlay.open();
    }

    _computeAuthorName(comment) {
      if (!comment) return '';
      if (comment.robot_id) {
        return comment.robot_id;
      }
      return comment.author && comment.author.name;
    }

    _computeHideRunDetails(comment, collapsed) {
      if (!comment) return true;
      return !(comment.robot_id && comment.url && !collapsed);
    }

    _closeOverlay(overlay) {
      Polymer.dom(Gerrit.getRootElement()).removeChild(overlay);
      overlay.close();
    }

    _handleConfirmDeleteComment() {
      const dialog =
          this.confirmDeleteOverlay.querySelector('#confirmDeleteComment');
      this.$.restAPI.deleteComment(
          this.changeNum, this.patchNum, this.comment.id, dialog.message)
          .then(newComment => {
            this._handleCancelDeleteComment();
            this.comment = newComment;
          });
    }
  }

  customElements.define(GrComment.is, GrComment);
})();
