/**
 * @license
 * Copyright 2016 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import '../../../styles/shared-styles';
import '../gr-selection-action-box/gr-selection-action-box';
import {getLength} from './gr-annotation';
import {normalize} from './gr-range-normalizer';
import {strToClassName} from '../../../utils/dom-util';
import {Side} from '../../../constants/constants';
import {CommentRange} from '../../../types/common';
import {GrSelectionActionBox} from '../gr-selection-action-box/gr-selection-action-box';
import {
  getLineElByChild,
  getLineNumberByChild,
  getSideByLineEl,
  GrDiffCommentThread,
} from '../gr-diff/gr-diff-utils';
import {debounce, DelayedTask} from '../../../utils/async-util';
import {assertIsDefined, queryAndAssert} from '../../../utils/common-util';
import {DiffModel} from '../gr-diff-model/gr-diff-model';

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

/**
 * The methods that we actually want to call on the builder. We don't want a
 * fully blown dependency on GrDiffBuilderElement.
 */
export interface DiffBuilderInterface {
  getContentTdByLineEl(lineEl?: Element): Element | undefined;
  diffModel: DiffModel;
}

/**
 * Handles showing, positioning and interacting with <gr-selection-action-box>.
 *
 * Toggles a css class for highlighting comment ranges when the mouse leaves or
 * enters a comment thread element.
 */
export class GrDiffHighlight {
  selectedRange?: SidedRange;

  private diffBuilder?: DiffBuilderInterface;

  private diffTable?: HTMLElement;

  private selectionChangeTask?: DelayedTask;

  init(diffTable: HTMLElement, diffBuilder: DiffBuilderInterface) {
    this.cleanup();

    this.diffTable = diffTable;
    this.diffBuilder = diffBuilder;

    diffTable.addEventListener(
      'comment-thread-mouseleave',
      this.handleCommentThreadMouseleave
    );
    diffTable.addEventListener(
      'comment-thread-mouseenter',
      this.handleCommentThreadMouseenter
    );
    diffTable.addEventListener(
      'create-comment-requested',
      this.handleRangeCommentRequest
    );
  }

  cleanup() {
    this.selectionChangeTask?.cancel();
    if (this.diffTable) {
      this.diffTable.removeEventListener(
        'comment-thread-mouseleave',
        this.handleCommentThreadMouseleave
      );
      this.diffTable.removeEventListener(
        'comment-thread-mouseenter',
        this.handleCommentThreadMouseenter
      );
      this.diffTable.removeEventListener(
        'create-comment-requested',
        this.handleRangeCommentRequest
      );
    }
  }

  /**
   * 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.selectionChangeTask = debounce(
      this.selectionChangeTask,
      () => this.handleSelection(selection, isMouseUp),
      10
    );
  }

  private toggleRangeElHighlight(
    thread: GrDiffCommentThread,
    highlightRange = false
  ) {
    const rootId = thread?.rootId;
    if (!rootId) return;
    if (!this.diffTable) return;
    const highlightClass = highlightRange ? 'range' : 'rangeHoverHighlight';
    const selector = `.${highlightClass}.${strToClassName(rootId)}`;
    const rangeNodes = this.diffTable.querySelectorAll(selector);
    for (const rangeNode of rangeNodes) {
      rangeNode.classList.toggle('rangeHoverHighlight', highlightRange);
    }
  }

  private handleCommentThreadMouseenter = (
    e: CustomEvent<GrDiffCommentThread>
  ) => {
    this.toggleRangeElHighlight(e.detail, /* highlightRange= */ true);
  };

  private handleCommentThreadMouseleave = (
    e: CustomEvent<GrDiffCommentThread>
  ) => {
    this.toggleRangeElHighlight(e.detail, /* highlightRange= */ false);
  };

  /**
   * 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).
   */
  private 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
   */
  private 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
   */
  private 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
   */
  private normalizeSelectionSide(
    node: Node | null,
    offset: number
  ): NormalizedPosition | null {
    let column;
    if (!this.diffTable) return null;
    if (!this.diffBuilder) return null;
    if (!node || !this.diffTable.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 (typeof line !== 'number') 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.
   */
  // visible for testing
  positionActionBox(
    actionBox: GrSelectionActionBox,
    startLine: number,
    range: Text | Element | Range
  ) {
    if (startLine > 1) {
      actionBox.positionBelow = false;
      actionBox.placeAbove(range);
      return;
    }
    actionBox.positionBelow = true;
    actionBox.placeBelow(range);
  }

  private 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)
    );
  }

  // visible for testing
  handleSelection(selection: Selection | Range, isMouseUp: boolean) {
    /* On Safari, the selection events may return a null range that should
       be ignored */
    if (!selection) return;
    if (!this.diffTable) 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.createRangeComment(start.side, {
          start_line: start.line,
          start_character: 0,
          end_line: start.line,
          end_character: start.column,
        });
      }
      return;
    }

    let actionBox = this.diffTable.querySelector('gr-selection-action-box');
    if (!actionBox) {
      actionBox = document.createElement('gr-selection-action-box');
      this.diffTable.appendChild(actionBox);
    }
    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();
    }
  }

  private createRangeComment(side: Side, range: CommentRange) {
    assertIsDefined(this.diffBuilder, 'diffBuilder');
    this.diffBuilder?.diffModel.createCommentOnRange(range, side);
    this.removeActionBox();
  }

  private handleRangeCommentRequest = (e: Event) => {
    e.stopPropagation();
    assertIsDefined(this.selectedRange, 'selectedRange');
    const {side, range} = this.selectedRange;
    this.createRangeComment(side, range);
  };

  // visible for testing
  removeActionBox() {
    this.selectedRange = undefined;
    const actionBox = this.diffTable?.querySelector('gr-selection-action-box');
    if (actionBox) actionBox.remove();
  }

  private 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.
   */
  // visible for testing
  getLength(node: Node | null): number {
    if (node === null) return 0;
    if (node instanceof Element && node.classList.contains('content')) {
      return this.getLength(queryAndAssert(node, '.contentText'));
    } else {
      return getLength(node);
    }
  }
}
