/**
 * @license
 * Copyright 2021 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import {DiffLayer} from '../../../types/types';
import {GrDiffLine, Side, TokenHighlightListener} from '../../../api/diff';
import {assertIsDefined} from '../../../utils/common-util';
import {
  GrAnnotationImpl,
  getStringLength,
} from '../gr-diff-highlight/gr-annotation';
import {debounce, DelayedTask} from '../../../utils/async-util';

import {getLineElByChild, getSideByLineEl} from '../gr-diff/gr-diff-utils';

import {
  getLineNumberByChild,
  lineNumberToNumber,
} from '../gr-diff/gr-diff-utils';
import {GrDiff} from '../gr-diff/gr-diff';

const tokenMatcher = new RegExp(/[\w]+/g);

/** CSS class for all tokens. */
const CSS_TOKEN = 'token';

/** CSS class for the currently hovered token. */
const CSS_HIGHLIGHT = 'token-highlight';

/** CSS class marking which text value each token corresponds */
const TOKEN_TEXT_PREFIX = 'tk-text-';

/**
 * CSS class marking which index (column) where token starts within a line of code.
 * The assumption is that we can only have a single token per column start per line.
 */
const TOKEN_INDEX_PREFIX = 'tk-index-';

export const HOVER_DELAY_MS = 200;

const LINE_LENGTH_LIMIT = 500;

const TOKEN_LENGTH_LIMIT = 100;

const TOKEN_COUNT_LIMIT = 10000;

const TOKEN_OCCURRENCES_LIMIT = 1000;

/**
 * When a user hovers over a token in the diff, then this layer makes sure that
 * all occurrences of this token are annotated with the 'token-highlight' css
 * class. And removes that class when the user moves the mouse away from the
 * token.
 *
 * The layer does not react to mouse events directly by adding a css class to
 * the appropriate elements, but instead it just sets the currently highlighted
 * token and notifies the diff renderer that certain lines must be re-rendered.
 * And when that re-rendering happens the appropriate css class is added.
 */
export class TokenHighlightLayer implements DiffLayer {
  /** The currently highlighted token. */
  private currentHighlight?: string;

  /** Trigger when a new token starts or stoped being highlighted.*/
  private readonly tokenHighlightListener?: TokenHighlightListener;

  /**
   * The line of the currently highlighted token. We store this in order to
   * re-render only relevant lines of the diff. Only lines visible on the screen
   * need a highlight. For example in a file with 10,000 lines it is sufficient
   * to just re-render the ~100 lines that are visible to the user.
   *
   * It is a known issue that we are only storing the line number on the side of
   * where the user is hovering and we use that also to determine which line
   * numbers to re-render on the other side, but it is non-trivial to look up or
   * store a reliable mapping of line numbers, so we just accept this
   * shortcoming with the reasoning that the user is mostly interested in the
   * tokens on the side where they are hovering anyway.
   *
   * Another known issue is that we are not able to see past collapsed lines
   * with the current implementation.
   */
  private currentHighlightLineNumber = 0;

  /**
   * Keeps track of where tokens occur in a file during rendering, so that it is
   * easy to look up when processing mouse events.
   */
  private tokenToElements = new Map<string, Set<HTMLElement>>();

  private hoveredElement?: Element;

  private updateTokenTask?: DelayedTask;

  /**
   * Container that contains all annotated tokens and contains no shadow root
   * elements that would prevent tokens to be queryable by querySelectorAll.
   */
  private getTokenQueryContainer?: () => HTMLElement;

  /**
   * @param container for registering "deselect" click
   * @param tokenHighlightListener method that is called,
   *   when token is highlighted.
   * @param getTokenQueryContainer if specified, list of tokens to be
   *   highlighted are recalculated every time using querySelectorAll inside
   *   this element. Otherwise, the pointers calculated once at annotate() time
   *   and are reused.
   */
  constructor(
    container: HTMLElement,
    tokenHighlightListener?: TokenHighlightListener,
    getTokenQueryContainer?: () => HTMLElement
  ) {
    this.tokenHighlightListener = tokenHighlightListener;
    container.addEventListener('click', e => {
      this.handleContainerClick(e);
    });
    this.getTokenQueryContainer = getTokenQueryContainer;
  }

  static createTokenHighlightContainer(
    container: HTMLElement,
    getGrDiff: () => GrDiff,
    tokenHighlightListener?: TokenHighlightListener
  ): TokenHighlightLayer {
    return new TokenHighlightLayer(
      container,
      tokenHighlightListener,
      () => getGrDiff().diffTable!
    );
  }

  annotate(el: HTMLElement, _1: HTMLElement, _2: GrDiffLine, _3: Side): void {
    const text = el.textContent;
    if (!text) return;
    // Binary files encoded as text for example can have super long lines
    // with super long tokens. Let's guard against against this scenario.
    if (text.length > LINE_LENGTH_LIMIT) return;
    let match;
    let atLeastOneTokenMatched = false;
    while ((match = tokenMatcher.exec(text))) {
      const token = match[0];

      // Binary files encoded as text for example can have super long lines
      // with super long tokens. Let's guard against this scenario.
      if (token.length > TOKEN_LENGTH_LIMIT) continue;

      // This is to correctly count surrogate pairs in text and token.
      // If the index calculation becomes a hotspot, we could precompute a code
      // unit to code point index map for text before iterating over the results
      const index = getStringLength(text.slice(0, match.index));
      const length = getStringLength(token);

      atLeastOneTokenMatched = true;
      const highlightTypeClass =
        token === this.currentHighlight ? CSS_HIGHLIGHT : '';
      const textClass = `${TOKEN_TEXT_PREFIX}${token}`;
      const indexClass = `${TOKEN_INDEX_PREFIX}${index}`;
      // We add the TOKEN_TEXT_PREFIX class so that we can look up the token later easily
      // even if the token element was split up into multiple smaller nodes.
      // All parts of a single token will share a common TOKEN_INDEX_PREFIX class within the line of code.
      GrAnnotationImpl.annotateElement(
        el,
        index,
        length,
        `${textClass} ${indexClass} ${CSS_TOKEN} ${highlightTypeClass}`
      );
      // We could try to detect whether we are re-rendering instead of initially
      // rendering the line. Then we would not have to call storeLineForToken()
      // again. But since the Set swallows the duplicates we don't care.
      this.storeElementsForToken(token, el, textClass);
    }
    if (atLeastOneTokenMatched) {
      // These listeners do not have to be cleaned, because listeners are
      // garbage collected along with the element itself once it is not attached
      // to the DOM anymore and no references exist anymore.
      el.addEventListener('mouseover', e => {
        this.handleTokenMouseOver(e);
      });
      el.addEventListener('mouseout', e => {
        this.handleTokenMouseOut(e);
      });
    }
  }

  private storeElementsForToken(
    token: string,
    lineEl: HTMLElement,
    cssClass: string
  ) {
    for (const el of lineEl.querySelectorAll(`.${cssClass}`)) {
      let tokenEls = this.tokenToElements.get(token);
      if (!tokenEls) {
        // Just to make sure that we don't break down on large files.
        if (this.tokenToElements.size > TOKEN_COUNT_LIMIT) return;
        tokenEls = new Set<HTMLElement>();
        this.tokenToElements.set(token, tokenEls);
      }
      // Just to make sure that we don't break down on large files.
      if (tokenEls.size > TOKEN_OCCURRENCES_LIMIT) return;
      tokenEls.add(el as HTMLElement);
    }
  }

  private handleTokenMouseOut(e: MouseEvent) {
    // If there's no ongoing hover-task, terminate early.
    if (!this.updateTokenTask?.isActive()) return;
    if (e.buttons > 0 || this.interferesWithSelection()) return;
    const {element} = this.findTokenAncestor(e?.target);
    if (!element) return;
    if (element === this.hoveredElement) {
      // If we are moving out of the currently hovered element, cancel the
      // update task.
      this.hoveredElement = undefined;
      if (this.updateTokenTask) this.updateTokenTask.cancel();
    }
  }

  private handleTokenMouseOver(e: MouseEvent) {
    if (e.buttons > 0 || this.interferesWithSelection()) return;
    const {
      line,
      token: newHighlight,
      element,
    } = this.findTokenAncestor(e?.target);
    if (!newHighlight || newHighlight === this.currentHighlight) return;
    this.hoveredElement = element;
    this.updateTokenTask = debounce(
      this.updateTokenTask,
      () => {
        this.updateTokenHighlight(newHighlight, line, element);
      },
      HOVER_DELAY_MS
    );
  }

  private handleContainerClick(e: MouseEvent) {
    if (this.interferesWithSelection()) return;
    // Ignore the click if the click is on a token.
    // We can't use e.target becauses it gets retargetted to the container as
    // it's a shadow dom.
    const {element} = this.findTokenAncestor(e.composedPath()[0]);
    if (element) return;
    this.hoveredElement = undefined;
    this.updateTokenTask?.cancel();
    this.updateTokenHighlight(undefined, 0, undefined);
  }

  private interferesWithSelection() {
    return document.getSelection()?.type === 'Range';
  }

  findTokenAncestor(el?: EventTarget | Element | null): {
    token?: string;
    line: number;
    element?: Element;
  } {
    if (!(el instanceof Element))
      return {line: 0, token: undefined, element: undefined};
    if (el.classList.contains(CSS_TOKEN)) {
      const tkTextClass = [...el.classList].find(c =>
        c.startsWith(TOKEN_TEXT_PREFIX)
      );
      const line = lineNumberToNumber(getLineNumberByChild(el));
      if (!line || !tkTextClass)
        return {line: 0, token: undefined, element: undefined};
      return {
        line,
        token: tkTextClass.substring(TOKEN_TEXT_PREFIX.length),
        element: el,
      };
    }
    if (el.tagName === 'TD')
      return {line: 0, token: undefined, element: undefined};
    return this.findTokenAncestor(el.parentElement);
  }

  private updateTokenHighlight(
    newHighlight: string | undefined,
    newLineNumber: number,
    newHoveredElement: Element | undefined
  ) {
    if (
      this.currentHighlight === newHighlight &&
      this.currentHighlightLineNumber === newLineNumber
    )
      return;

    const oldHighlight = this.currentHighlight;
    this.currentHighlight = newHighlight;
    this.currentHighlightLineNumber = newLineNumber;
    this.triggerTokenHighlightEvent(
      newHighlight,
      newLineNumber,
      newHoveredElement
    );
    this.toggleTokenHighlight(oldHighlight, CSS_HIGHLIGHT);
    this.toggleTokenHighlight(newHighlight, CSS_HIGHLIGHT);
  }

  private toggleTokenHighlight(token: string | undefined, cssClass: string) {
    if (!token) {
      return;
    }
    let tokenEls;
    let tokenElsLength;
    if (this.getTokenQueryContainer) {
      tokenEls = this.getTokenQueryContainer().querySelectorAll(
        `.${TOKEN_TEXT_PREFIX}${token}`
      );
      tokenElsLength = tokenEls.length;
    } else {
      tokenEls = this.tokenToElements.get(token);
      tokenElsLength = tokenEls?.size;
    }
    if (!tokenEls || tokenElsLength === 0) {
      console.warn(`No tokens have been found for '${token}'`);
      return;
    }
    for (const el of tokenEls) {
      el.classList.toggle(cssClass);
    }
  }

  triggerTokenHighlightEvent(
    token: string | undefined,
    line: number,
    element: Element | undefined
  ) {
    if (!this.tokenHighlightListener) {
      return;
    }
    if (!token || !element) {
      this.tokenHighlightListener(undefined);
      return;
    }
    const lineEl = getLineElByChild(element);
    assertIsDefined(lineEl, 'Line element should be found!');
    const tokenIndexStr = [...element.classList]
      .find(c => c.startsWith(TOKEN_INDEX_PREFIX))
      ?.substring(TOKEN_INDEX_PREFIX.length);
    assertIsDefined(tokenIndexStr, 'Index class should be found!');
    const index = Number(tokenIndexStr);
    const side = getSideByLineEl(lineEl);
    const range = {
      start_line: line,
      start_column: index + 1, // 1-based inclusive
      end_line: line,
      end_column: index + getStringLength(token), // 1-based inclusive
    };
    this.tokenHighlightListener({token, element, side, range});
  }
}
