/**
 * @license
 * Copyright (C) 2017 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.
 */
import '../../shared/gr-rest-api-interface/gr-rest-api-interface.js';
import {mixinBehaviors} from '@polymer/polymer/lib/legacy/class.js';
import {GestureEventListeners} from '@polymer/polymer/lib/mixins/gesture-event-listeners.js';
import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin.js';
import {PolymerElement} from '@polymer/polymer/polymer-element.js';
import {htmlTemplate} from './gr-comment-api_html.js';
import {PatchSetBehavior} from '../../../behaviors/gr-patch-set-behavior/gr-patch-set-behavior.js';
import {parseDate} from '../../../utils/date-util.js';

const PARENT = 'PARENT';

/**
 * Construct a change comments object, which can be data-bound to child
 * elements of that which uses the gr-comment-api.
 *
 * @constructor
 * @param {!Object} comments
 * @param {!Object} robotComments
 * @param {!Object} drafts
 * @param {number} changeNum
 */
class ChangeComments {
  constructor(comments, robotComments, drafts, changeNum) {
    // TODO(taoalpha): replace these with exported methods from patchset behavior
    this._patchNumEquals =
      PatchSetBehavior.patchNumEquals;
    this._isMergeParent =
      PatchSetBehavior.isMergeParent;
    this._getParentIndex =
      PatchSetBehavior.getParentIndex;

    this._comments = this._addPath(comments);
    this._robotComments = this._addPath(robotComments);
    this._drafts = this._addPath(drafts);
    this._changeNum = changeNum;
  }

  /**
   * Add path info to every comment as CommentInfo returned
   * from server does not have that.
   *
   * TODO(taoalpha): should consider changing BE to send path
   * back within CommentInfo
   *
   * @param {Object} - map between file path and comments
   */
  _addPath(comments = {}) {
    const updatedComments = {};
    for (const filePath of Object.keys(comments)) {
      const allCommentsForPath = comments[filePath] || [];
      if (allCommentsForPath.length) {
        updatedComments[filePath] = allCommentsForPath
            .map(comment => { return {...comment, path: filePath}; });
      }
    }
    return updatedComments;
  }

  get comments() {
    return this._comments;
  }

  get drafts() {
    return this._drafts;
  }

  get robotComments() {
    return this._robotComments;
  }

  /**
   * Get an object mapping file paths to a boolean representing whether that
   * path contains diff comments in the given patch set (including drafts and
   * robot comments).
   *
   * Paths with comments are mapped to true, whereas paths without comments
   * are not mapped.
   *
   * @param {Gerrit.PatchRange=} opt_patchRange The patch-range object containing
   *     patchNum and basePatchNum properties to represent the range.
   * @return {!Object}
   */
  getPaths(opt_patchRange) {
    const responses = [this.comments, this.drafts, this.robotComments];
    const commentMap = {};
    for (const response of responses) {
      for (const path in response) {
        if (response.hasOwnProperty(path) &&
          response[path].some(c => {
            // If don't care about patch range, we know that the path exists.
            if (!opt_patchRange) { return true; }
            return this._isInPatchRange(c, opt_patchRange);
          })) {
          commentMap[path] = true;
        }
      }
    }
    return commentMap;
  }

  /**
   * Gets all the comments and robot comments for the given change.
   *
   * @param {number=} opt_patchNum
   * @return {!Object}
   */
  getAllPublishedComments(opt_patchNum) {
    return this.getAllComments(false, opt_patchNum);
  }

  /**
   * Gets all the comments for a particular thread group. Used for refreshing
   * comments after the thread group has already been built.
   *
   * @param {string} rootId
   * @return {!Array} an array of comments
   */
  getCommentsForThread(rootId) {
    const allThreads = this.getAllThreadsForChange();
    const threadMatch = allThreads.find(t => t.rootId === rootId);

    // In the event that a single draft comment was removed by the thread-list
    // and the diff view is updating comments, there will no longer be a thread
    // found.  In this case, return null.
    return threadMatch ? threadMatch.comments : null;
  }

  /**
   * Filters an array of comments by line and side
   *
   * @param {!Array} comments
   * @param {boolean} parentOnly whether the only comments returned should have
   *   the side attribute set to PARENT
   * @param {string} commentSide whether the comment was left on the left or the
   *   right side regardless or unified or side-by-side
   * @param {number=} opt_line line number, can be undefined if file comment
   * @return {!Array} an array of comments
   */
  _filterCommentsBySideAndLine(comments,
      parentOnly, commentSide, opt_line) {
    return comments.filter(c => {
    // if parentOnly, only match comments with PARENT for the side.
      let sideMatch = parentOnly ? c.side === PARENT : c.side !== PARENT;
      if (parentOnly) {
        sideMatch = sideMatch && c.side === PARENT;
      }
      return sideMatch && c.line === opt_line;
    }).map(c => {
      c.__commentSide = commentSide;
      return c;
    });
  }

  /**
   * Gets all the comments and robot comments for the given change.
   *
   * @param {boolean=} opt_includeDrafts
   * @param {number=} opt_patchNum
   * @return {!Object}
   */
  getAllComments(opt_includeDrafts,
      opt_patchNum) {
    const paths = this.getPaths();
    const publishedComments = {};
    for (const path of Object.keys(paths)) {
      publishedComments[path] = this.getAllCommentsForPath(
          path,
          opt_patchNum,
          opt_includeDrafts
      );
    }
    return publishedComments;
  }

  /**
   * Gets all the drafts for the given change.
   *
   * @param {number=} opt_patchNum
   * @return {!Object}
   */
  getAllDrafts(opt_patchNum) {
    const paths = this.getPaths();
    const drafts = {};
    for (const path of Object.keys(paths)) {
      drafts[path] = this.getAllDraftsForPath(path, opt_patchNum);
    }
    return drafts;
  }

  /**
   * Get the comments (robot comments) for a path and optional patch num.
   *
   * This method will always return a new shallow copy of all comments,
   * so manipulation on one copy won't affect other copies.
   *
   * @param {!string} path
   * @param {number=} opt_patchNum
   * @param {boolean=} opt_includeDrafts
   * @return {!Array}
   */
  getAllCommentsForPath(path,
      opt_patchNum, opt_includeDrafts) {
    const comments = this._comments[path] || [];
    const robotComments = this._robotComments[path] || [];
    let allComments = comments.concat(robotComments);
    if (opt_includeDrafts) {
      const drafts = this.getAllDraftsForPath(path);
      allComments = allComments.concat(drafts);
    }
    if (opt_patchNum) {
      allComments = allComments.filter(c =>
        this._patchNumEquals(c.patch_set, opt_patchNum)
      );
    }
    return allComments.map(c => { return {...c}; });
  }

  /**
   * Get the comments (robot comments) for a file.
   *
   * // TODO(taoalpha): maybe merge in *ForPath
   *
   * @param {!{path: string, basePath?: string, patchNum?: number}} file
   * @param {boolean=} opt_includeDrafts
   * @return {!Array}
   */
  getAllCommentsForFile(file, opt_includeDrafts) {
    let allComments = this.getAllCommentsForPath(
        file.path, file.patchNum, opt_includeDrafts
    );

    if (file.basePath) {
      allComments = allComments.concat(
          this.getAllCommentsForPath(
              file.basePath, file.patchNum, opt_includeDrafts
          )
      );
    }

    return allComments;
  }

  /**
   * Get the drafts for a path and optional patch num.
   *
   * This will return a shallow copy of all drafts every time,
   * so changes on any copy will not affect other copies.
   *
   * @param {!string} path
   * @param {number=} opt_patchNum
   * @return {!Array}
   */
  getAllDraftsForPath(path,
      opt_patchNum) {
    let comments = this._drafts[path] || [];
    if (opt_patchNum) {
      comments = comments.filter(c =>
        this._patchNumEquals(c.patch_set, opt_patchNum)
      );
    }
    return comments.map(c => { return {...c, __draft: true}; });
  }

  /**
   * Get the drafts for a file.
   *
   * // TODO(taoalpha): maybe merge in *ForPath
   *
   * @param {!{path: string, basePath?: string, patchNum?: number}} file
   * @return {!Array}
   */
  getAllDraftsForFile(file) {
    let allDrafts = this.getAllDraftsForPath(file.path, file.patchNum);
    if (file.basePath) {
      allDrafts = allDrafts.concat(
          this.getAllDraftsForPath(file.basePath, file.patchNum)
      );
    }
    return allDrafts;
  }

  /**
   * Get the comments (with drafts and robot comments) for a path and
   * patch-range. Returns an object with left and right properties mapping to
   * arrays of comments in on either side of the patch range for that path.
   *
   * @param {!string} path
   * @param {!Gerrit.PatchRange} patchRange The patch-range object containing patchNum
   *     and basePatchNum properties to represent the range.
   * @param {Object=} opt_projectConfig Optional project config object to
   *     include in the meta sub-object.
   * @return {!Gerrit.CommentsBySide}
   */
  getCommentsBySideForPath(path,
      patchRange, opt_projectConfig) {
    let comments = [];
    let drafts = [];
    let robotComments = [];
    if (this.comments && this.comments[path]) {
      comments = this.comments[path];
    }
    if (this.drafts && this.drafts[path]) {
      drafts = this.drafts[path];
    }
    if (this.robotComments && this.robotComments[path]) {
      robotComments = this.robotComments[path];
    }

    drafts.forEach(d => { d.__draft = true; });

    const all = comments.concat(drafts).concat(robotComments)
        .map(c => { return {...c}; });

    const baseComments = all.filter(c =>
      this._isInBaseOfPatchRange(c, patchRange));
    const revisionComments = all.filter(c =>
      this._isInRevisionOfPatchRange(c, patchRange));

    return {
      meta: {
        changeNum: this._changeNum,
        path,
        patchRange,
        projectConfig: opt_projectConfig,
      },
      left: baseComments,
      right: revisionComments,
    };
  }

  /**
   * Get the comments (with drafts and robot comments) for a file and
   * patch-range. Returns an object with left and right properties mapping to
   * arrays of comments in on either side of the patch range for that path.
   *
   * // TODO(taoalpha): maybe merge *ForPath so find all comments in one pass
   *
   * @param {!{path: string, basePath?: string, patchNum?: number}} file
   * @param {!Gerrit.PatchRange} patchRange The patch-range object containing patchNum
   *     and basePatchNum properties to represent the range.
   * @param {Object=} opt_projectConfig Optional project config object to
   *     include in the meta sub-object.
   * @return {!Gerrit.CommentsBySide}
   */
  getCommentsBySideForFile(file, patchRange, opt_projectConfig) {
    const comments = this.getCommentsBySideForPath(
        file.path, patchRange, opt_projectConfig
    );
    if (file.basePath) {
      const commentsForBasePath = this.getCommentsBySideForPath(
          file.basePath, patchRange, opt_projectConfig
      );
      // merge in the left and right
      comments.left = comments.left.concat(commentsForBasePath.left);
      comments.right = comments.right.concat(commentsForBasePath.right);
    }
    return comments;
  }

  /**
   * @param {!Object} comments Object keyed by file, with a value of an array
   *   of comments left on that file.
   * @return {!Array} A flattened list of all comments, where each comment
   *   also includes the file that it was left on, which was the key of the
   *   originall object.
   */
  _commentObjToArrayWithFile(comments) {
    let commentArr = [];
    for (const file of Object.keys(comments)) {
      const commentsForFile = [];
      for (const comment of comments[file]) {
        commentsForFile.push(Object.assign({__path: file}, comment));
      }
      commentArr = commentArr.concat(commentsForFile);
    }
    return commentArr;
  }

  _commentObjToArray(comments) {
    let commentArr = [];
    for (const file of Object.keys(comments)) {
      commentArr = commentArr.concat(comments[file]);
    }
    return commentArr;
  }

  /**
   * Computes a string counting the number of commens in a given file.
   *
   * @param {{path: string, basePath?: string, patchNum?: number}} file
   * @return {number}
   */
  computeCommentCount(file) {
    if (file.path) {
      return this.getAllCommentsForFile(file).length;
    }
    const allComments = this.getAllPublishedComments(file.patchNum);
    return this._commentObjToArray(allComments).length;
  }

  /**
   * Computes a string counting the number of draft comments in the entire
   * change, optionally filtered by path and/or patchNum.
   *
   * @param {?{path: string, basePath?: string, patchNum?: number}} file
   * @return {number}
   */
  computeDraftCount(file) {
    if (file && file.path) {
      return this.getAllDraftsForFile(file).length;
    }
    const allDrafts = this.getAllDrafts(file && file.patchNum);
    return this._commentObjToArray(allDrafts).length;
  }

  /**
   * Computes a number of unresolved comment threads in a given file and path.
   *
   * @param {{path: string, basePath?: string, patchNum?: number}} file
   * @return {number}
   */
  computeUnresolvedNum(file) {
    let comments = [];
    let drafts = [];

    if (file.path) {
      comments = this.getAllCommentsForFile(file);
      drafts = this.getAllDraftsForFile(file);
    } else {
      comments = this._commentObjToArray(
          this.getAllPublishedComments(file.patchNum));
    }

    comments = comments.concat(drafts);

    const threads = this.getCommentThreads(this._sortComments(comments));

    const unresolvedThreads = threads
        .filter(thread =>
          thread.comments.length &&
        thread.comments[thread.comments.length - 1].unresolved);

    return unresolvedThreads.length;
  }

  getAllThreadsForChange() {
    const comments = this._commentObjToArrayWithFile(this.getAllComments(true));
    const sortedComments = this._sortComments(comments);
    return this.getCommentThreads(sortedComments);
  }

  _sortComments(comments) {
    return comments.slice(0)
        .sort(
            (c1, c2) => {
              const dateDiff =
                  parseDate(c1.updated) - parseDate(c2.updated);
              if (dateDiff) {
                return dateDiff;
              }
              return c1.id - c2.id;
            }
        );
  }

  /**
   * Computes all of the comments in thread format.
   *
   * @param {!Array} comments sorted by updated timestamp.
   * @return {!Array}
   */
  getCommentThreads(comments) {
    const threads = [];
    const idThreadMap = {};
    for (const comment of comments) {
    // If the comment is in reply to another comment, find that comment's
    // thread and append to it.
      if (comment.in_reply_to) {
        const thread = idThreadMap[comment.in_reply_to];
        if (thread) {
          thread.comments.push(comment);
          idThreadMap[comment.id] = thread;
          continue;
        }
      }

      // Otherwise, this comment starts its own thread.
      const newThread = {
        comments: [comment],
        patchNum: comment.patch_set,
        path: comment.__path,
        line: comment.line,
        rootId: comment.id,
      };
      if (comment.side) {
        newThread.commentSide = comment.side;
      }
      threads.push(newThread);
      idThreadMap[comment.id] = newThread;
    }
    return threads;
  }

  /**
   * Whether the given comment should be included in the base side of the
   * given patch range.
   *
   * @param {!Object} comment
   * @param {!Gerrit.PatchRange} range
   * @return {boolean}
   */
  _isInBaseOfPatchRange(comment, range) {
  // If the base of the patch range is a parent of a merge, and the comment
  // appears on a specific parent then only show the comment if the parent
  // index of the comment matches that of the range.
    if (comment.parent && comment.side === PARENT) {
      return this._isMergeParent(range.basePatchNum) &&
        comment.parent === this._getParentIndex(range.basePatchNum);
    }

    // If the base of the range is the parent of the patch:
    if (range.basePatchNum === PARENT &&
      comment.side === PARENT &&
      this._patchNumEquals(comment.patch_set, range.patchNum)) {
      return true;
    }
    // If the base of the range is not the parent of the patch:
    return range.basePatchNum !== PARENT &&
        comment.side !== PARENT &&
        this._patchNumEquals(comment.patch_set, range.basePatchNum);
  }

  /**
   * Whether the given comment should be included in the revision side of the
   * given patch range.
   *
   * @param {!Object} comment
   * @param {!Gerrit.PatchRange} range
   * @return {boolean}
   */
  _isInRevisionOfPatchRange(comment,
      range) {
    return comment.side !== PARENT &&
      this._patchNumEquals(comment.patch_set, range.patchNum);
  }

  /**
   * Whether the given comment should be included in the given patch range.
   *
   * @param {!Object} comment
   * @param {!Gerrit.PatchRange} range
   * @return {boolean|undefined}
   */
  _isInPatchRange(comment, range) {
    return this._isInBaseOfPatchRange(comment, range) ||
      this._isInRevisionOfPatchRange(comment, range);
  }
}

/**
 * @extends PolymerElement
 */
class GrCommentApi extends mixinBehaviors( [
  PatchSetBehavior,
], GestureEventListeners(
    LegacyElementMixin(
        PolymerElement))) {
  static get template() { return htmlTemplate; }

  static get is() { return 'gr-comment-api'; }

  static get properties() {
    return {
      _changeComments: Object,
    };
  }

  /** @override */
  created() {
    super.created();
    this.addEventListener('reload-drafts',
        changeNum => this.reloadDrafts(changeNum));
  }

  /**
   * Load all comments (with drafts and robot comments) for the given change
   * number. The returned promise resolves when the comments have loaded, but
   * does not yield the comment data.
   *
   * @param {number} changeNum
   * @return {!Promise<!Object>}
   */
  loadAll(changeNum) {
    const promises = [];
    promises.push(this.$.restAPI.getDiffComments(changeNum));
    promises.push(this.$.restAPI.getDiffRobotComments(changeNum));
    promises.push(this.$.restAPI.getDiffDrafts(changeNum));

    return Promise.all(promises).then(([comments, robotComments, drafts]) => {
      this._changeComments = new ChangeComments(comments,
          robotComments, drafts, changeNum);
      return this._changeComments;
    });
  }

  /**
   * Re-initialize _changeComments with a new ChangeComments object, that
   * uses the previous values for comments and robot comments, but fetches
   * updated draft comments.
   *
   * @param {number} changeNum
   * @return {!Promise<!Object>}
   */
  reloadDrafts(changeNum) {
    if (!this._changeComments) {
      return this.loadAll(changeNum);
    }
    return this.$.restAPI.getDiffDrafts(changeNum).then(drafts => {
      this._changeComments = new ChangeComments(this._changeComments.comments,
          this._changeComments.robotComments, drafts, changeNum);
      return this._changeComments;
    });
  }
}

customElements.define(GrCommentApi.is, GrCommentApi);
