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

  var HOVER_PATH_PATTERN = /^comments\.(left|right)\.\#(\d+)\.__hovering$/;
  var SPLICE_PATH_PATTERN = /^comments\.(left|right)\.splices$/;

  var RANGE_HIGHLIGHT = 'range';
  var HOVER_HIGHLIGHT = 'rangeHighlight';

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

    properties: {
      comments: Object,
      _listeners: {
        type: Array,
        value: function() { return []; },
      },
      _commentMap: {
        type: Object,
        value: function() { 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: function(el, line) {
      var 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'));
      }

      ranges.forEach(function(range) {
        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: function(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: function(start, end, side) {
      this._listeners.forEach(function(listener) {
        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: function(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.
      var match = record.path.match(HOVER_PATH_PATTERN);
      if (match) {
        var side = match[1];
        var index = match[2];
        var 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) {
        var 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: function(commentList) {
      var result = {};
      commentList.forEach(function(comment) {
        if (!comment.range) { return; }
        var range = comment.range;
        for (var line = range.start_line; line <= range.end_line; line++) {
          if (!result[line]) { result[line] = []; }
          result[line].push({
            comment: 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: function(record, side) {
      if (!record || !record.indexSplices) { return; }
      record.indexSplices.forEach(function(splice) {
        var ranges = splice.removed.length ?
          splice.removed.map(function(c) { return c.range; }) :
          [splice.object[splice.index].range];
        ranges.forEach(function(range) {
          if (!range) { return; }
          this._notifyUpdateRange(range.start_line, range.end_line, side);
        }.bind(this));
      }.bind(this));
    },

    _getRangesForLine: function(line, side) {
      var lineNum = side === 'left' ? line.beforeNumber : line.afterNumber;
      var ranges = this.get(['_commentMap', side, lineNum]) || [];
      return ranges
          .map(function(range) {
            var 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;
            }

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