/**
 * @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 {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';
import {
  getLineElByChild,
  getLineNumberByChild,
  getRange,
  getSide,
  getSideByLineEl,
} from '../gr-diff/gr-diff-utils';
import {debounce, DelayedTask} from '../../../utils/async-util';

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

  private selectionChangeTask?: DelayedTask;

  constructor() {
    super();
    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)
    );
  }

  /** @override */
  disconnectedCallback() {
    this.selectionChangeTask?.cancel();
    super.disconnectedCallback();
  }

  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 | 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.selectionChangeTask = debounce(
      this.selectionChangeTask,
      () => 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('rangeHoverHighlight');
        });
        const hintNode = threadEl.parentElement?.querySelector(
          `gr-ranged-comment-hint[threadElRootId="${threadEl.rootId}"]`
        );
        if (hintNode) {
          hintNode.shadowRoot
            ?.querySelectorAll('.rangeHighlight')
            .forEach(highlightNode =>
              highlightNode.classList.add('rangeHoverHighlight')
            );
        }
      } else {
        const rangeNodes = curNode.querySelectorAll(
          `.rangeHoverHighlight.${strToClassName(threadEl.rootId)}`
        );
        rangeNodes.forEach(rangeNode => {
          rangeNode.classList.remove('rangeHoverHighlight');
        });
        const hintNode = threadEl.parentElement?.querySelector(
          `gr-ranged-comment-hint[threadElRootId="${threadEl.rootId}"]`
        );
        if (hintNode) {
          hintNode.shadowRoot
            ?.querySelectorAll('.rangeHoverHighlight')
            .forEach(highlightNode =>
              highlightNode.classList.remove('rangeHoverHighlight')
            );
        }
      }
    }
  }

  _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 = getSide(threadEl);
    const range = getRange(threadEl);
    if (!side || !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) {
    /* 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 = getLineElByChild(node);
    if (!lineEl) return null;
    const side = getSideByLineEl(lineEl);
    if (!side) return null;
    const line = getLineNumberByChild(lineEl);
    if (!line || line === FILE || line === 'LOST') 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, 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;
  }
}
