// 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 HOVER_PATH_PATTERN = /^comments\.(left|right)\.\#(\d+)\.__hovering$/;
  const SPLICE_PATH_PATTERN = /^comments\.(left|right)\.splices$/;

  const RANGE_HIGHLIGHT = 'range';
  const HOVER_HIGHLIGHT = 'rangeHighlight';

  const NORMALIZE_RANGE_EVENT = 'normalize-range';

  Polymer({
    is: 'gr-ranged-comment-layer',

    properties: {
      comments: Object,
      _listeners: {
        type: Array,
        value() { return []; },
      },
      _commentMap: {
        type: Object,
        value() { return {left: [], right: []}; },
      },
    },

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

    /**
     * Layer method to add annotations to a line.
     * @param {HTMLElement} el The DIV.contentText element to apply the
     *     annotation to.
     * @param {GrDiffLine} line The line object.
     */
    annotate(el, line) {
      let ranges = [];
      if (line.type === GrDiffLine.Type.REMOVE || (
          line.type === GrDiffLine.Type.BOTH &&
          el.getAttribute('data-side') !== 'right')) {
        ranges = ranges.concat(this._getRangesForLine(line, 'left'));
      }
      if (line.type === GrDiffLine.Type.ADD || (
          line.type === GrDiffLine.Type.BOTH &&
          el.getAttribute('data-side') !== 'left')) {
        ranges = ranges.concat(this._getRangesForLine(line, 'right'));
      }

      for (const range of ranges) {
        GrAnnotation.annotateElement(el, range.start,
            range.end - range.start,
            range.hovering ? HOVER_HIGHLIGHT : RANGE_HIGHLIGHT);
      }
    },

    /**
     * Register a listener for layer updates.
     * @param {Function<Number, Number, String>} fn The update handler function.
     *     Should accept as arguments the line numbers for the start and end of
     *     the update and the side as a string.
     */
    addListener(fn) {
      this._listeners.push(fn);
    },

    /**
     * Notify Layer listeners of changes to annotations.
     * @param {Number} start The line where the update starts.
     * @param {Number} end The line where the update ends.
     * @param {String} side The side of the update. ('left' or 'right')
     */
    _notifyUpdateRange(start, end, side) {
      for (const listener of this._listeners) {
        listener(start, end, side);
      }
    },

    /**
     * Handle change in the comments by updating the comment maps and by
     * emitting appropriate update notifications.
     * @param {Object} record The change record.
     */
    _handleCommentChange(record) {
      if (!record.path) { return; }

      // If the entire set of comments was changed.
      if (record.path === 'comments') {
        this._commentMap.left = this._computeCommentMap(this.comments.left);
        this._commentMap.right = this._computeCommentMap(this.comments.right);
        return;
      }

      // If the change only changed the `hovering` property of a comment.
      let match = record.path.match(HOVER_PATH_PATTERN);
      let side;

      if (match) {
        side = match[1];
        const index = match[2];
        const comment = this.comments[side][index];
        if (comment && comment.range) {
          this._commentMap[side] = this._computeCommentMap(this.comments[side]);
          this._notifyUpdateRange(
              comment.range.start_line, comment.range.end_line, side);
        }
        return;
      }

      // If comments were spliced in or out.
      match = record.path.match(SPLICE_PATH_PATTERN);
      if (match) {
        side = match[1];
        this._commentMap[side] = this._computeCommentMap(this.comments[side]);
        this._handleCommentSplice(record.value, side);
      }
    },

    /**
     * Take a list of comments and return a sparse list mapping line numbers to
     * partial ranges. Uses an end-character-index of -1 to indicate the end of
     * the line.
     * @param {Array<Object>} commentList The list of comments.
     * @return {Object} The sparse list.
     */
    _computeCommentMap(commentList) {
      const result = {};
      for (const comment of commentList) {
        if (!comment.range) { continue; }
        const range = comment.range;
        for (let line = range.start_line; line <= range.end_line; line++) {
          if (!result[line]) { result[line] = []; }
          result[line].push({
            comment,
            start: line === range.start_line ? range.start_character : 0,
            end: line === range.end_line ? range.end_character : -1,
          });
        }
      }
      return result;
    },

    /**
     * Translate a splice record into range update notifications.
     */
    _handleCommentSplice(record, side) {
      if (!record || !record.indexSplices) { return; }

      for (const splice of record.indexSplices) {
        const ranges = splice.removed.length ?
            splice.removed.map(c => { return c.range; }) :
            [splice.object[splice.index].range];
        for (const range of ranges) {
          if (!range) { continue; }
          this._notifyUpdateRange(range.start_line, range.end_line, side);
        }
      }
    },

    _getRangesForLine(line, side) {
      const lineNum = side === 'left' ? line.beforeNumber : line.afterNumber;
      const ranges = this.get(['_commentMap', side, lineNum]) || [];
      return ranges
          .map(range => {
            range = {
              start: range.start,
              end: range.end === -1 ? line.text.length : range.end,
              hovering: !!range.comment.__hovering,
            };

            // Normalize invalid ranges where the start is after the end but the
            // start still makes sense. Set the end to the end of the line.
            // @see Issue 5744
            if (range.start >= range.end && range.start < line.text.length) {
              range.end = line.text.length;
              this.$.reporting.reportInteraction(NORMALIZE_RANGE_EVENT,
                  'Modified invalid comment range on l.' + lineNum +
                  ' of the ' + side + ' side');
            }

            return range;
          })
          // Sort the ranges so that hovering highlights are on top.
          .sort((a, b) => a.hovering && !b.hovering ? 1 : 0);
    },
  });
})();
