/**
 * @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 '../../../styles/shared-styles';
import '../gr-selection-action-box/gr-selection-action-box';
import {dom, EventApi} from '@polymer/polymer/lib/legacy/polymer.dom';
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-diff-highlight_html';
import {GrAnnotation} from './gr-annotation';
import {normalize} from './gr-range-normalizer';
import {strToClassName} from '../../../utils/dom-util';
import {customElement, property} from '@polymer/decorators';
import {Side} from '../../../constants/constants';
import {CommentRange} from '../../../types/common';
import {GrSelectionActionBox} from '../gr-selection-action-box/gr-selection-action-box';
import {GrDiffBuilderElement} from '../gr-diff-builder/gr-diff-builder-element';
import {FILE} from '../gr-diff/gr-diff-line';

interface SidedRange {
  side: Side;
  range: CommentRange;
}

interface NormalizedPosition {
  node: Node | null;
  side: Side;
  line: number;
  column: number;
}

interface NormalizedRange {
  start: NormalizedPosition | null;
  end: NormalizedPosition | null;
}

// TODO(TS): Replace by GrCommentThread once that is converted.
interface CommentThreadElement extends HTMLElement {
  rootId: string;
}

@customElement('gr-diff-highlight')
export class GrDiffHighlight extends GestureEventListeners(
  LegacyElementMixin(PolymerElement)
) {
  static get template() {
    return htmlTemplate;
  }

  @property({type: Array, notify: true})
  commentRanges: SidedRange[] = [];

  @property({type: Boolean})
  loggedIn?: boolean;

  @property({type: Object})
  _cachedDiffBuilder?: GrDiffBuilderElement;

  @property({type: Object, notify: true})
  selectedRange?: SidedRange;

  /** @override */
  created() {
    super.created();
    this.addEventListener('comment-thread-mouseleave', e =>
      this._handleCommentThreadMouseleave(e)
    );
    this.addEventListener('comment-thread-mouseenter', e =>
      this._handleCommentThreadMouseenter(e)
    );
    this.addEventListener('create-comment-requested', e =>
      this._handleRangeCommentRequest(e)
    );
  }

  get diffBuilder() {
    if (!this._cachedDiffBuilder) {
      this._cachedDiffBuilder = this.querySelector(
        'gr-diff-builder'
      ) as GrDiffBuilderElement;
    }
    return this._cachedDiffBuilder;
  }

  /**
   * Determines side/line/range for a DOM selection and shows a tooltip.
   *
   * With native shadow DOM, gr-diff-highlight cannot access a selection that
   * references the DOM elements making up the diff because they are in the
   * shadow DOM the gr-diff element. For this reason, we listen to the
   * selectionchange event and retrieve the selection in gr-diff, and then
   * call this method to process the Selection.
   *
   * @param selection A DOM Selection living in the shadow DOM of
   * the diff element.
   * @param isMouseUp If true, this is called due to a mouseup
   * event, in which case we might want to immediately create a comment,
   * because isMouseUp === true combined with an existing selection must
   * mean that this is the end of a double-click.
   */
  handleSelectionChange(
    selection: Selection | Range | null,
    isMouseUp: boolean
  ) {
    if (selection === null) return;
    // Debounce is not just nice for waiting until the selection has settled,
    // it is also vital for being able to click on the action box before it is
    // removed.
    // If you wait longer than 50 ms, then you don't properly catch a very
    // quick 'c' press after the selection change. If you wait less than 10
    // ms, then you will have about 50 _handleSelection calls when doing a
    // simple drag for select.
    this.debounce(
      'selectionChange',
      () => this._handleSelection(selection, isMouseUp),
      10
    );
  }

  _getThreadEl(e: Event): CommentThreadElement | null {
    const path = (dom(e) as EventApi).path || [];
    for (const pathEl of path) {
      if (
        pathEl instanceof HTMLElement &&
        pathEl.classList.contains('comment-thread')
      ) {
        return pathEl as CommentThreadElement;
      }
    }
    return null;
  }

  _toggleRangeElHighlight(
    threadEl: CommentThreadElement,
    highlightRange = false
  ) {
    // We don't want to re-create the line just for highlighting the range which
    // is creating annoying bugs: @see Issue 12934
    // As gr-ranged-comment-layer now does not notify the layer re-render and
    // lack of access to the thread or the lineEl from the ranged-comment-layer,
    // need to update range class for styles here.
    let curNode: HTMLElement | null = threadEl.assignedSlot;
    while (curNode) {
      if (curNode.nodeName === 'TABLE') break;
      curNode = curNode.parentElement;
    }
    if (curNode?.querySelectorAll) {
      if (highlightRange) {
        const rangeNodes = curNode.querySelectorAll(
          `.range.${strToClassName(threadEl.rootId)}`
        );
        rangeNodes.forEach(rangeNode => {
          rangeNode.classList.add('rangeHighlight');
          rangeNode.classList.remove('range');
        });
      } else {
        const rangeNodes = curNode.querySelectorAll(
          `.rangeHighlight.${strToClassName(threadEl.rootId)}`
        );
        rangeNodes.forEach(rangeNode => {
          rangeNode.classList.remove('rangeHighlight');
          rangeNode.classList.add('range');
        });
      }
    }
  }

  _handleCommentThreadMouseenter(e: Event) {
    const threadEl = this._getThreadEl(e)!;
    const index = this._indexForThreadEl(threadEl);

    if (index !== undefined) {
      this.set(['commentRanges', index, 'hovering'], true);
    }

    this._toggleRangeElHighlight(threadEl, /* highlightRange= */ true);
  }

  _handleCommentThreadMouseleave(e: Event) {
    const threadEl = this._getThreadEl(e)!;
    const index = this._indexForThreadEl(threadEl);

    if (index !== undefined) {
      this.set(['commentRanges', index, 'hovering'], false);
    }

    this._toggleRangeElHighlight(threadEl, /* highlightRange= */ false);
  }

  _indexForThreadEl(threadEl: HTMLElement) {
    const side = threadEl.getAttribute('comment-side') as Side;
    const rangeString = threadEl.getAttribute('range');
    if (!rangeString) return undefined;
    const range = JSON.parse(rangeString) as CommentRange;

    if (!range) return undefined;

    return this._indexOfCommentRange(side, range);
  }

  _indexOfCommentRange(side: Side, range: CommentRange) {
    function rangesEqual(a: CommentRange, b: CommentRange) {
      if (!a && !b) {
        return true;
      }
      if (!a || !b) {
        return false;
      }
      return (
        a.start_line === b.start_line &&
        a.start_character === b.start_character &&
        a.end_line === b.end_line &&
        a.end_character === b.end_character
      );
    }

    return this.commentRanges.findIndex(
      commentRange =>
        commentRange.side === side && rangesEqual(commentRange.range, range)
    );
  }

  /**
   * Get current normalized selection.
   * Merges multiple ranges, accounts for triple click, accounts for
   * syntax highligh, convert native DOM Range objects to Gerrit concepts
   * (line, side, etc).
   */
  _getNormalizedRange(selection: Selection | Range) {
    /* On Safari the ShadowRoot.getSelection() isn't there and the only thing
       we can get is a single Range */
    if (selection instanceof Range) {
      return this._normalizeRange(selection);
    }
    const rangeCount = selection.rangeCount;
    if (rangeCount === 0) {
      return null;
    } else if (rangeCount === 1) {
      return this._normalizeRange(selection.getRangeAt(0));
    } else {
      const startRange = this._normalizeRange(selection.getRangeAt(0));
      const endRange = this._normalizeRange(
        selection.getRangeAt(rangeCount - 1)
      );
      return {
        start: startRange.start,
        end: endRange.end,
      };
    }
  }

  /**
   * Normalize a specific DOM Range.
   *
   * @return fixed normalized range
   */
  _normalizeRange(domRange: Range): NormalizedRange {
    const range = normalize(domRange);
    return this._fixTripleClickSelection(
      {
        start: this._normalizeSelectionSide(
          range.startContainer,
          range.startOffset
        ),
        end: this._normalizeSelectionSide(range.endContainer, range.endOffset),
      },
      domRange
    );
  }

  /**
   * Adjust triple click selection for the whole line.
   * A triple click always results in:
   * - start.column == end.column == 0
   * - end.line == start.line + 1
   *
   * @param range Normalized range, ie column/line numbers
   * @param domRange DOM Range object
   * @return fixed normalized range
   */
  _fixTripleClickSelection(range: NormalizedRange, domRange: Range) {
    if (!range.start) {
      // Selection outside of current diff.
      return range;
    }
    const start = range.start;
    const end = range.end;
    // Happens when triple click in side-by-side mode with other side empty.
    const endsAtOtherEmptySide =
      !end &&
      domRange.endOffset === 0 &&
      domRange.endContainer instanceof HTMLElement &&
      domRange.endContainer.nodeName === 'TD' &&
      (domRange.endContainer.classList.contains('left') ||
        domRange.endContainer.classList.contains('right'));
    const endsAtBeginningOfNextLine =
      end &&
      start.column === 0 &&
      end.column === 0 &&
      end.line === start.line + 1;
    const content = domRange.cloneContents().querySelector('.contentText');
    const lineLength = (content && this._getLength(content)) || 0;
    if (lineLength && (endsAtBeginningOfNextLine || endsAtOtherEmptySide)) {
      // Move the selection to the end of the previous line.
      range.end = {
        node: start.node,
        column: lineLength,
        side: start.side,
        line: start.line,
      };
    }
    return range;
  }

  /**
   * Convert DOM Range selection to concrete numbers (line, column, side).
   * Moves range end if it's not inside td.content.
   * Returns null if selection end is not valid (outside of diff).
   *
   * @param node td.content child
   * @param offset offset within node
   */
  _normalizeSelectionSide(
    node: Node | null,
    offset: number
  ): NormalizedPosition | null {
    let column;
    if (!node || !this.contains(node)) return null;
    const lineEl = this.diffBuilder.getLineElByChild(node);
    if (!lineEl) return null;
    const side = this.diffBuilder.getSideByLineEl(lineEl);
    if (!side) return null;
    const line = this.diffBuilder.getLineNumberByChild(lineEl);
    if (!line || line === FILE) return null;
    const contentTd = this.diffBuilder.getContentTdByLineEl(lineEl);
    if (!contentTd) return null;
    const contentText = contentTd.querySelector('.contentText');
    if (!contentTd.contains(node)) {
      node = contentText;
      column = 0;
    } else {
      const thread = contentTd.querySelector('.comment-thread');
      if (thread?.contains(node)) {
        column = this._getLength(contentText);
        node = contentText;
      } else {
        column = this._convertOffsetToColumn(node, offset);
      }
    }

    return {
      node,
      side,
      line,
      column,
    };
  }

  /**
   * The only line in which add a comment tooltip is cut off is the first
   * line. Even if there is a collapsed section, The first visible line is
   * in the position where the second line would have been, if not for the
   * collapsed section, so don't need to worry about this case for
   * positioning the tooltip.
   */
  _positionActionBox(
    actionBox: GrSelectionActionBox,
    startLine: number,
    range: Text | Element | Range
  ) {
    if (startLine > 1) {
      actionBox.placeAbove(range);
      return;
    }
    actionBox.positionBelow = true;
    actionBox.placeBelow(range);
  }

  _isRangeValid(range: NormalizedRange | null) {
    if (!range || !range.start || !range.start.node || !range.end) {
      return false;
    }
    const start = range.start;
    const end = range.end;
    return !(
      start.side !== end.side ||
      end.line < start.line ||
      (start.line === end.line && start.column === end.column)
    );
  }

  _handleSelection(selection: Selection | Range, isMouseUp: boolean) {
    /* On Safari, the selection events may return a null range that should
       be ignored */
    if (!selection) {
      return;
    }
    const normalizedRange = this._getNormalizedRange(selection);
    if (!this._isRangeValid(normalizedRange)) {
      this._removeActionBox();
      return;
    }
    /* On Safari the ShadowRoot.getSelection() isn't there and the only thing
       we can get is a single Range */
    const domRange =
      selection instanceof Range ? selection : selection.getRangeAt(0);
    const start = normalizedRange!.start!;
    const end = normalizedRange!.end!;

    // TODO (viktard): Drop empty first and last lines from selection.

    // If the selection is from the end of one line to the start of the next
    // line, then this must have been a double-click, or you have started
    // dragging. Showing the action box is bad in the former case and not very
    // useful in the latter, so never do that.
    // If this was a mouse-up event, we create a comment immediately if
    // the selection is from the end of a line to the start of the next line.
    // In a perfect world we would only do this for double-click, but it is
    // extremely rare that a user would drag from the end of one line to the
    // start of the next and release the mouse, so we don't bother.
    // TODO(brohlfs): This does not work, if the double-click is before a new
    // diff chunk (start will be equal to end), and neither before an "expand
    // the diff context" block (end line will match the first line of the new
    // section and thus be greater than start line + 1).
    if (start.line === end.line - 1 && end.column === 0) {
      // Rather than trying to find the line contents (for comparing
      // start.column with the content length), we just check if the selection
      // is empty to see that it's at the end of a line.
      const content = domRange.cloneContents().querySelector('.contentText');
      if (isMouseUp && this._getLength(content) === 0) {
        this._fireCreateRangeComment(start.side, {
          start_line: start.line,
          start_character: 0,
          end_line: start.line,
          end_character: start.column,
        });
      }
      return;
    }

    let actionBox = this.shadowRoot!.querySelector(
      'gr-selection-action-box'
    ) as GrSelectionActionBox | null;
    if (!actionBox) {
      actionBox = document.createElement('gr-selection-action-box');
      this.root!.insertBefore(actionBox, this.root!.firstElementChild);
    }
    this.selectedRange = {
      range: {
        start_line: start.line,
        start_character: start.column,
        end_line: end.line,
        end_character: end.column,
      },
      side: start.side,
    };
    if (start.line === end.line) {
      this._positionActionBox(actionBox, start.line, domRange);
    } else if (start.node instanceof Text) {
      if (start.column) {
        this._positionActionBox(
          actionBox,
          start.line,
          start.node.splitText(start.column)
        );
      }
      start.node.parentElement!.normalize(); // Undo splitText from above.
    } else if (
      start.node instanceof HTMLElement &&
      start.node.classList.contains('content') &&
      (start.node.firstChild instanceof Element ||
        start.node.firstChild instanceof Text)
    ) {
      this._positionActionBox(actionBox, start.line, start.node.firstChild);
    } else if (start.node instanceof Element || start.node instanceof Text) {
      this._positionActionBox(actionBox, start.line, start.node);
    } else {
      console.warn('Failed to position comment action box.');
      this._removeActionBox();
    }
  }

  _fireCreateRangeComment(side: Side, range: CommentRange) {
    this.dispatchEvent(
      new CustomEvent('create-range-comment', {
        detail: {side, range},
        composed: true,
        bubbles: true,
      })
    );
    this._removeActionBox();
  }

  _handleRangeCommentRequest(e: Event) {
    e.stopPropagation();
    if (!this.selectedRange) {
      throw Error('Selected Range is needed for new range comment!');
    }
    const {side, range} = this.selectedRange;
    this._fireCreateRangeComment(side, range);
  }

  _removeActionBox() {
    this.selectedRange = undefined;
    const actionBox = this.shadowRoot!.querySelector('gr-selection-action-box');
    if (actionBox) {
      this.root!.removeChild(actionBox);
    }
  }

  _convertOffsetToColumn(el: Node, offset: number) {
    if (el instanceof Element && el.classList.contains('content')) {
      return offset;
    }
    while (
      el.previousSibling ||
      !el.parentElement?.classList.contains('content')
    ) {
      if (el.previousSibling) {
        el = el.previousSibling;
        offset += this._getLength(el);
      } else {
        el = el.parentElement!;
      }
    }
    return offset;
  }

  /**
   * Get length of a node. If the node is a content node, then only give the
   * length of its .contentText child.
   *
   * @param node this is sometimes passed as null.
   */
  _getLength(node: Node | null): number {
    if (node === null) return 0;
    if (node instanceof Element && node.classList.contains('content')) {
      return this._getLength(node.querySelector('.contentText')!);
    } else {
      return GrAnnotation.getLength(node);
    }
  }
}

declare global {
  interface HTMLElementTagNameMap {
    'gr-diff-highlight': GrDiffHighlight;
  }
}
