/**
 * @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.
 */
import {GrAnnotation} from '../gr-diff-highlight/gr-annotation';
import {GestureEventListeners} from '@polymer/polymer/lib/mixins/gesture-event-listeners';
import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin';
import {PolymerElement} from '@polymer/polymer/polymer-element';
import {htmlTemplate} from './gr-ranged-comment-layer_html';
import {GrDiffLine, GrDiffLineType} from '../gr-diff/gr-diff-line';
import {strToClassName} from '../../../utils/dom-util';
import {customElement, property, observe} from '@polymer/decorators';
import {Side} from '../../../constants/constants';
import {
  PolymerDeepPropertyChange,
  PolymerSpliceChange,
} from '@polymer/polymer/interfaces';
import {CommentRange} from '../../../types/common';
import {DiffLayer, DiffLayerListener} from '../../../types/types';

/**
 * Enhanced CommentRange by UI state. Interface for incoming ranges set from the
 * outside.
 *
 * TODO(TS): Unify with what is used in gr-diff when these objects are created.
 */
export interface CommentRangeLayer {
  side: Side;
  range: CommentRange;
  hovering: boolean;
  rootId: string;
}

/**
 * This class breaks down all comment ranges into individual line segment
 * highlights.
 */
interface CommentRangeLineLayer {
  hovering: boolean;
  rootId: string;
  start: number;
  end: number;
}

type LinesMap = {
  [line in number]: CommentRangeLineLayer[];
};

type RangesMap = {
  [side in Side]: LinesMap;
};

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

@customElement('gr-ranged-comment-layer')
export class GrRangedCommentLayer
  extends GestureEventListeners(LegacyElementMixin(PolymerElement))
  implements DiffLayer {
  static get template() {
    return htmlTemplate;
  }

  /**
   * 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
   */

  @property({type: Array})
  commentRanges: CommentRangeLayer[] = [];

  @property({type: Array})
  _listeners: DiffLayerListener[] = [];

  @property({type: Object})
  _rangesMap: RangesMap = {left: {}, right: {}};

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

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

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

  /**
   * Register a listener for layer updates.
   */
  addListener(listener: DiffLayerListener) {
    this._listeners.push(listener);
  }

  removeListener(listener: DiffLayerListener) {
    this._listeners = this._listeners.filter(f => f !== listener);
  }

  /**
   * Notify Layer listeners of changes to annotations.
   */
  _notifyUpdateRange(start: number, end: number, side: 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.
   */
  @observe('commentRanges.*')
  _handleCommentRangesChange(
    record: PolymerDeepPropertyChange<
      CommentRangeLayer[],
      PolymerSpliceChange<CommentRangeLayer[]>
    >
  ) {
    if (!record) return;

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

    // 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, rootId} = this.get(match[1]);

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

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

  _updateRangesMap(options: {
    side: Side;
    range: CommentRange;
    hovering: boolean;
    operation: (
      forLine: CommentRangeLineLayer[],
      start: number,
      end: number,
      hovering: boolean
    ) => void;
    skipLayerUpdate?: boolean;
  }) {
    const {side, range, hovering, operation, skipLayerUpdate} = options;
    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);
    }
    if (!skipLayerUpdate) {
      this._notifyUpdateRange(range.start_line, range.end_line, side);
    }
  }

  _getRangesForLine(line: GrDiffLine, side: Side) {
    const lineNum = side === Side.LEFT ? line.beforeNumber : line.afterNumber;
    const ranges: CommentRangeLineLayer[] =
      this.get(['_rangesMap', side, lineNum]) || [];
    return (
      ranges
        .map(range => {
          // Make a copy, so that the normalization below does not mess with
          // our map.
          range = {...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))
    );
  }
}

declare global {
  interface HTMLElementTagNameMap {
    'gr-ranged-comment-layer': GrRangedCommentLayer;
  }
}
