/**
 * @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';

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

    /**
     * @event comment-mouse-over
     */

    /**
     * @event comment-mouse-out
     */

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

    properties: {
      changeNum: String,
      /** @type {?} */
      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,

      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: () => ({}),
      },
    },

    observers: [
      '_commentMessageChanged(comment.message)',
      '_loadLocalDraft(changeNum, patchNum, comment)',
      '_isRobotComment(comment)',
      '_calculateActionstoShow(showActions, isRobotComment)',
    ],

    behaviors: [
      Gerrit.KeyboardShortcutBehavior,
    ],

    keyBindings: {
      'ctrl+enter meta+enter ctrl+s meta+s': '_handleSaveKey',
      'esc': '_handleEsc',
    },

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

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

    get textarea() {
      return this.$$('#editTextarea');
    },

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

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

    _computeShowHideText(collapsed) {
      return collapsed ? '◀' : '▼';
    },

    _calculateActionstoShow(showActions, isRobotComment) {
      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) {
      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.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);
    },

    _handleAnchorTap(e) {
      e.preventDefault();
      if (!this.comment.line) { return; }
      this.dispatchEvent(new CustomEvent('comment-anchor-tap', {
        bubbles: 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,
        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}));
      }, 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) {
      // 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);
      }
    },

    _handleMouseEnter(e) {
      this.fire('comment-mouse-over', this._getEventPayload());
    },

    _handleMouseLeave(e) {
      this.fire('comment-mouse-out', this._getEventPayload());
    },

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

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