/**
 * @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 UNRESOLVED_EXPAND_COUNT = 5;
  const NEWLINE_PATTERN = /\n/g;

  Polymer({
    is: 'gr-comment-thread',
    _legacyUndefinedCheck: true,

    /**
     * Fired when the thread should be discarded.
     *
     * @event thread-discard
     */

    /**
     * Fired when a comment in the thread is permanently modified.
     *
     * @event thread-changed
     */

    /**
     * gr-comment-thread exposes the following attributes that allow a
     * diff widget like gr-diff to show the thread in the right location:
     *
     * line-num:
     *     1-based line number or undefined if it refers to the entire file.
     *
     * comment-side:
     *     "left" or "right". These indicate which of the two diffed versions
     *     the comment relates to. In the case of unified diff, the left
     *     version is the one whose line number column is further to the left.
     *
     * range:
     *     The range of text that the comment refers to (start_line,
     *     start_character, end_line, end_character), serialized as JSON. If
     *     set, range's end_line will have the same value as line-num. Line
     *     numbers are 1-based, char numbers are 0-based. The start position
     *     (start_line, start_character) is inclusive, and the end position
     *     (end_line, end_character) is exclusive.
     */
    properties: {
      changeNum: String,
      comments: {
        type: Array,
        value() { return []; },
      },
      /**
       * @type {?{start_line: number, start_character: number, end_line: number,
       *          end_character: number}}
       */
      range: {
        type: Object,
        reflectToAttribute: true,
      },
      keyEventTarget: {
        type: Object,
        value() { return document.body; },
      },
      commentSide: {
        type: String,
        reflectToAttribute: true,
      },
      patchNum: String,
      path: String,
      projectName: {
        type: String,
        observer: '_projectNameChanged',
      },
      hasDraft: {
        type: Boolean,
        notify: true,
        reflectToAttribute: true,
      },
      isOnParent: {
        type: Boolean,
        value: false,
      },
      parentIndex: {
        type: Number,
        value: null,
      },
      rootId: {
        type: String,
        notify: true,
        computed: '_computeRootId(comments.*)',
      },
      /**
       * If this is true, the comment thread also needs to have the change and
       * line properties property set
       */
      showFilePath: {
        type: Boolean,
        value: false,
      },
      /** Necessary only if showFilePath is true or when used with gr-diff */
      lineNum: {
        type: Number,
        reflectToAttribute: true,
      },
      unresolved: {
        type: Boolean,
        notify: true,
        reflectToAttribute: true,
      },
      _showActions: Boolean,
      _lastComment: Object,
      _orderedComments: Array,
      _projectConfig: Object,
    },

    behaviors: [
      Gerrit.KeyboardShortcutBehavior,
      Gerrit.PathListBehavior,
    ],

    listeners: {
      'comment-update': '_handleCommentUpdate',
    },

    observers: [
      '_commentsChanged(comments.*)',
    ],

    keyBindings: {
      'e shift+e': '_handleEKey',
    },

    attached() {
      this._getLoggedIn().then(loggedIn => {
        this._showActions = loggedIn;
      });
      this._setInitialExpandedState();
    },

    addOrEditDraft(opt_lineNum, opt_range) {
      const lastComment = this.comments[this.comments.length - 1] || {};
      if (lastComment.__draft) {
        const commentEl = this._commentElWithDraftID(
            lastComment.id || lastComment.__draftID);
        commentEl.editing = true;

        // If the comment was collapsed, re-open it to make it clear which
        // actions are available.
        commentEl.collapsed = false;
      } else {
        const range = opt_range ? opt_range :
          lastComment ? lastComment.range : undefined;
        const unresolved = lastComment ? lastComment.unresolved : undefined;
        this.addDraft(opt_lineNum, range, unresolved);
      }
    },

    addDraft(opt_lineNum, opt_range, opt_unresolved) {
      const draft = this._newDraft(opt_lineNum, opt_range);
      draft.__editing = true;
      draft.unresolved = opt_unresolved === false ? opt_unresolved : true;
      this.push('comments', draft);
    },

    fireRemoveSelf() {
      this.dispatchEvent(new CustomEvent('thread-discard',
          {detail: {rootId: this.rootId}, bubbles: false}));
    },

    _getDiffUrlForComment(projectName, changeNum, path, patchNum) {
      return Gerrit.Nav.getUrlForDiffById(changeNum,
          projectName, path, patchNum,
          null, this.lineNum);
    },

    _computeDisplayPath(path) {
      const lineString = this.lineNum ? `#${this.lineNum}` : '';
      return this.computeDisplayPath(path) + lineString;
    },

    _getLoggedIn() {
      return this.$.restAPI.getLoggedIn();
    },

    _commentsChanged() {
      this._orderedComments = this._sortedComments(this.comments);
      this.updateThreadProperties();
    },

    updateThreadProperties() {
      if (this._orderedComments.length) {
        this._lastComment = this._getLastComment();
        this.unresolved = this._lastComment.unresolved;
        this.hasDraft = this._lastComment.__draft;
      }
    },

    _hideActions(_showActions, _lastComment) {
      return !_showActions || !_lastComment || !!_lastComment.__draft;
    },

    _getLastComment() {
      return this._orderedComments[this._orderedComments.length - 1] || {};
    },

    _handleEKey(e) {
      if (this.shouldSuppressKeyboardShortcut(e)) { return; }

      // Don’t preventDefault in this case because it will render the event
      // useless for other handlers (other gr-comment-thread elements).
      if (e.detail.keyboardEvent.shiftKey) {
        this._expandCollapseComments(true);
      } else {
        if (this.modifierPressed(e)) { return; }
        this._expandCollapseComments(false);
      }
    },

    _expandCollapseComments(actionIsCollapse) {
      const comments =
          Polymer.dom(this.root).querySelectorAll('gr-comment');
      for (const comment of comments) {
        comment.collapsed = actionIsCollapse;
      }
    },

    /**
     * Sets the initial state of the comment thread.
     * Expands the thread if one of the following is true:
     * - last {UNRESOLVED_EXPAND_COUNT} comments expanded by default if the
     * thread is unresolved,
     * - it's a robot comment.
     */
    _setInitialExpandedState() {
      if (this._orderedComments) {
        for (let i = 0; i < this._orderedComments.length; i++) {
          const comment = this._orderedComments[i];
          const isRobotComment = !!comment.robot_id;
          // False if it's an unresolved comment under UNRESOLVED_EXPAND_COUNT.
          const resolvedThread = !this.unresolved ||
                this._orderedComments.length - i - 1 >= UNRESOLVED_EXPAND_COUNT;
          comment.collapsed = !isRobotComment && resolvedThread;
        }
      }
    },

    _sortedComments(comments) {
      return comments.slice().sort((c1, c2) => {
        const c1Date = c1.__date || util.parseDate(c1.updated);
        const c2Date = c2.__date || util.parseDate(c2.updated);
        const dateCompare = c1Date - c2Date;
        // Ensure drafts are at the end. There should only be one but in edge
        // cases could be more. In the unlikely event two drafts are being
        // compared, use the typical date compare.
        if (c2.__draft && !c1.__draft ) { return -1; }
        if (c1.__draft && !c2.__draft ) { return 1; }
        if (dateCompare === 0 && (!c1.id || !c1.id.localeCompare)) { return 0; }
        // If same date, fall back to sorting by id.
        return dateCompare ? dateCompare : c1.id.localeCompare(c2.id);
      });
    },

    _createReplyComment(parent, content, opt_isEditing,
        opt_unresolved) {
      this.$.reporting.recordDraftInteraction();
      const reply = this._newReply(
          this._orderedComments[this._orderedComments.length - 1].id,
          parent.line,
          content,
          opt_unresolved,
          parent.range);

      // If there is currently a comment in an editing state, add an attribute
      // so that the gr-comment knows not to populate the draft text.
      for (let i = 0; i < this.comments.length; i++) {
        if (this.comments[i].__editing) {
          reply.__otherEditing = true;
          break;
        }
      }

      if (opt_isEditing) {
        reply.__editing = true;
      }

      this.push('comments', reply);

      if (!opt_isEditing) {
        // Allow the reply to render in the dom-repeat.
        this.async(() => {
          const commentEl = this._commentElWithDraftID(reply.__draftID);
          commentEl.save();
        }, 1);
      }
    },

    _isDraft(comment) {
      return !!comment.__draft;
    },

    /**
     * @param {boolean=} opt_quote
     */
    _processCommentReply(opt_quote) {
      const comment = this._lastComment;
      let quoteStr;
      if (opt_quote) {
        const msg = comment.message;
        quoteStr = '> ' + msg.replace(NEWLINE_PATTERN, '\n> ') + '\n\n';
      }
      this._createReplyComment(comment, quoteStr, true, comment.unresolved);
    },

    _handleCommentReply(e) {
      this._processCommentReply();
    },

    _handleCommentQuote(e) {
      this._processCommentReply(true);
    },

    _handleCommentAck(e) {
      const comment = this._lastComment;
      this._createReplyComment(comment, 'Ack', false, false);
    },

    _handleCommentDone(e) {
      const comment = this._lastComment;
      this._createReplyComment(comment, 'Done', false, false);
    },

    _handleCommentFix(e) {
      const comment = e.detail.comment;
      const msg = comment.message;
      const quoteStr = '> ' + msg.replace(NEWLINE_PATTERN, '\n> ') + '\n\n';
      const response = quoteStr + 'Please Fix';
      this._createReplyComment(comment, response, false, true);
    },

    _commentElWithDraftID(id) {
      const els = Polymer.dom(this.root).querySelectorAll('gr-comment');
      for (const el of els) {
        if (el.comment.id === id || el.comment.__draftID === id) {
          return el;
        }
      }
      return null;
    },

    _newReply(inReplyTo, opt_lineNum, opt_message, opt_unresolved,
        opt_range) {
      const d = this._newDraft(opt_lineNum);
      d.in_reply_to = inReplyTo;
      d.range = opt_range;
      if (opt_message != null) {
        d.message = opt_message;
      }
      if (opt_unresolved !== undefined) {
        d.unresolved = opt_unresolved;
      }
      return d;
    },

    /**
     * @param {number=} opt_lineNum
     * @param {!Object=} opt_range
     */
    _newDraft(opt_lineNum, opt_range) {
      const d = {
        __draft: true,
        __draftID: Math.random().toString(36),
        __date: new Date(),
        path: this.path,
        patchNum: this.patchNum,
        side: this._getSide(this.isOnParent),
        __commentSide: this.commentSide,
      };
      if (opt_lineNum) {
        d.line = opt_lineNum;
      }
      if (opt_range) {
        d.range = opt_range;
      }
      if (this.parentIndex) {
        d.parent = this.parentIndex;
      }
      return d;
    },

    _getSide(isOnParent) {
      if (isOnParent) { return 'PARENT'; }
      return 'REVISION';
    },

    _computeRootId(comments) {
      // Keep the root ID even if the comment was removed, so that notification
      // to sync will know which thread to remove.
      if (!comments.base.length) { return this.rootId; }
      const rootComment = comments.base[0];
      return rootComment.id || rootComment.__draftID;
    },

    _handleCommentDiscard(e) {
      const diffCommentEl = Polymer.dom(e).rootTarget;
      const comment = diffCommentEl.comment;
      const idx = this._indexOf(comment, this.comments);
      if (idx == -1) {
        throw Error('Cannot find comment ' +
            JSON.stringify(diffCommentEl.comment));
      }
      this.splice('comments', idx, 1);
      if (this.comments.length === 0) {
        this.fireRemoveSelf();
      }
      this._handleCommentSavedOrDiscarded(e);

      // Check to see if there are any other open comments getting edited and
      // set the local storage value to its message value.
      for (const changeComment of this.comments) {
        if (changeComment.__editing) {
          const commentLocation = {
            changeNum: this.changeNum,
            patchNum: this.patchNum,
            path: changeComment.path,
            line: changeComment.line,
          };
          return this.$.storage.setDraftComment(commentLocation,
              changeComment.message);
        }
      }
    },

    _handleCommentSavedOrDiscarded(e) {
      this.dispatchEvent(new CustomEvent('thread-changed',
          {detail: {rootId: this.rootId, path: this.path},
            bubbles: false}));
    },

    _handleCommentUpdate(e) {
      const comment = e.detail.comment;
      const index = this._indexOf(comment, this.comments);
      if (index === -1) {
        // This should never happen: comment belongs to another thread.
        console.warn('Comment update for another comment thread.');
        return;
      }
      this.set(['comments', index], comment);
      // Because of the way we pass these comment objects around by-ref, in
      // combination with the fact that Polymer does dirty checking in
      // observers, the this.set() call above will not cause a thread update in
      // some situations.
      this.updateThreadProperties();
    },

    _indexOf(comment, arr) {
      for (let i = 0; i < arr.length; i++) {
        const c = arr[i];
        if ((c.__draftID != null && c.__draftID == comment.__draftID) ||
            (c.id != null && c.id == comment.id)) {
          return i;
        }
      }
      return -1;
    },

    _computeHostClass(unresolved) {
      return unresolved ? 'unresolved' : '';
    },

    /**
     * Load the project config when a project name has been provided.
     *
     * @param {string} name The project name.
     */
    _projectNameChanged(name) {
      if (!name) { return; }
      this.$.restAPI.getProjectConfig(name).then(config => {
        this._projectConfig = config;
      });
    },
  });
})();
