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

  // Polymer 1 adds # before array's key, while Polymer 2 doesn't
  const HOVER_PATH_PATTERN = /^(commentRanges\.\#?\d+)\.hovering$/;

  const RANGE_HIGHLIGHT = 'style-scope gr-diff range';
  const HOVER_HIGHLIGHT = 'style-scope gr-diff rangeHighlight';

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

    /**
     * Fired when the range in a range comment was malformed and had to be
     * normalized.
     *
     * It's `detail` has a `lineNum` and `side` parameter.
     *
     * @event normalize-range
     */

    properties: {
      /** @type {!Array<!Gerrit.HoveredRange>} */
      commentRanges: Array,
      _listeners: {
        type: Array,
        value() { return []; },
      },
      _rangesMap: {
        type: Object,
        value() { return {left: {}, right: {}}; },
      },
    },

    observers: [
      '_handleCommentRangesChange(commentRanges.*)',
    ],

    get styleModuleName() {
      return 'gr-ranged-comment-styles';
    },

    /**
     * Layer method to add annotations to a line.
     * @param {!HTMLElement} el The DIV.contentText element to apply the
     *     annotation to.
     * @param {!HTMLElement} lineNumberEl
     * @param {!Object} line The line object. (GrDiffLine)
     */
    annotate(el, lineNumberEl, 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 ranges by updating the ranges maps and by
     * emitting appropriate update notifications.
     * @param {Object} record The change record.
     */
    _handleCommentRangesChange(record) {
      if (!record) return;

      // If the entire set of comments was changed.
      if (record.path === 'commentRanges') {
        this._rangesMap = {left: {}, right: {}};
        for (const {side, range, hovering} of record.value) {
          this._updateRangesMap(
              side, range, hovering, (forLine, start, end, hovering) => {
                forLine.push({start, end, hovering});
              });
        }
      }

      // If the change only changed the `hovering` property of a comment.
      const match = record.path.match(HOVER_PATH_PATTERN);
      if (match) {
        // The #number indicates the key of that item in the array
        // not the index, especially in polymer 1.
        const {side, range, hovering} = this.get(match[1]);

        this._updateRangesMap(
            side, range, hovering, (forLine, start, end, hovering) => {
              const index = forLine.findIndex(lineRange =>
                lineRange.start === start && lineRange.end === end);
              forLine[index].hovering = hovering;
            });
      }

      // If comments were spliced in or out.
      if (record.path === 'commentRanges.splices') {
        for (const indexSplice of record.value.indexSplices) {
          const removed = indexSplice.removed;
          for (const {side, range, hovering} of removed) {
            this._updateRangesMap(
                side, range, hovering, (forLine, start, end) => {
                  const index = forLine.findIndex(lineRange =>
                    lineRange.start === start && lineRange.end === end);
                  forLine.splice(index, 1);
                });
          }
          const added = indexSplice.object.slice(
              indexSplice.index, indexSplice.index + indexSplice.addedCount);
          for (const {side, range, hovering} of added) {
            this._updateRangesMap(
                side, range, hovering, (forLine, start, end, hovering) => {
                  forLine.push({start, end, hovering});
                });
          }
        }
      }
    },

    _updateRangesMap(side, range, hovering, operation) {
      const forSide = this._rangesMap[side] || (this._rangesMap[side] = {});
      for (let line = range.start_line; line <= range.end_line; line++) {
        const forLine = forSide[line] || (forSide[line] = []);
        const start = line === range.start_line ? range.start_character : 0;
        const end = line === range.end_line ? range.end_character : -1;
        operation(forLine, start, end, hovering);
      }
      this._notifyUpdateRange(range.start_line, range.end_line, side);
    },

    _getRangesForLine(line, side) {
      const lineNum = side === 'left' ? line.beforeNumber : line.afterNumber;
      const ranges = this.get(['_rangesMap', side, lineNum]) || [];
      return ranges
          .map(range => {
            // Make a copy, so that the normalization below does not mess with
            // our map.
            range = Object.assign({}, range);
            range.end = range.end === -1 ? line.text.length : range.end;

            // 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.dispatchEvent(new CustomEvent('normalize-range', {
                bubbles: true,
                composed: true,
                detail: {lineNum, side},
              }));
            }

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