/**
 * @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 the show fix preview action is triggered.
     *
     * @event open-fix-preview
     */

    /**
     * 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',
        },
        comments: {
          type: Array,
        },
        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,
        _hasHumanReply: 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)',
        '_computeHasHumanReply(comment, comments.*)',
      ];
    }

    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();
      }
    }

    _computeHasHumanReply() {
      if (!this.comment || !this.comments) return;
      // hide please fix button for robot comment that has human reply
      this._hasHumanReply = this.comments.some(c => {
        return c.in_reply_to && c.in_reply_to === this.comment.id &&
            !c.robot_id;
      });
    }

    /**
     * @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 && 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(),
      }));
    }

    _handleShowFix() {
      this.dispatchEvent(new CustomEvent('open-fix-preview', {
        bubbles: true,
        composed: true,
        detail: this._getEventPayload(),
      }));
    }

    _hasNoFix(comment) {
      return !comment || !comment.fix_suggestions;
    }

    _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);
})();
