/**
 * @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 {GrAnnotation} 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];
      const index = match.index;
      const length = token.length;
      // Binary files encoded as text for example can have super long lines
      // with super long tokens. Let's guard against this scenario.
      if (length > TOKEN_LENGTH_LIMIT) continue;
      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.
      GrAnnotation.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 + token.length, // 1-based inclusive
    };
    this.tokenHighlightListener({token, element, side, range});
  }
}
