/**
 * @license
 * Copyright 2016 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import {getSanitizeDOMValue} from '@polymer/polymer/lib/utils/settings';

// TODO(wyatta): refactor this to be <MARK> rather than <HL>.
const ANNOTATION_TAG = 'HL';

// Astral code point as per https://mathiasbynens.be/notes/javascript-unicode
const REGEX_ASTRAL_SYMBOL = /[\uD800-\uDBFF][\uDC00-\uDFFF]/;

export const GrAnnotation = {
  /**
   * The DOM API textContent.length calculation is broken when the text
   * contains Unicode. See https://mathiasbynens.be/notes/javascript-unicode .
   *
   */
  getLength(node: Node) {
    if (node instanceof Comment) return 0;
    return this.getStringLength(node.textContent || '');
  },

  getStringLength(str: string) {
    return str.replace(REGEX_ASTRAL_SYMBOL, '_').length;
  },

  /**
   * Annotates the [offset, offset+length) text segment in the parent with the
   * element definition provided as arguments.
   *
   * @param parent the node whose contents will be annotated.
   * If parent is Text then parent.parentNode must not be null
   * @param offset the 0-based offset from which the annotation will
   * start.
   * @param length of the annotated text.
   * @param elementSpec the spec to create the
   * annotating element.
   */
  annotateWithElement(
    parent: Node,
    offset: number,
    length: number,
    elSpec: ElementSpec
  ) {
    const tagName = elSpec.tagName;
    const attributes = elSpec.attributes || {};
    let childNodes: Node[];

    if (parent instanceof Element) {
      childNodes = Array.from(parent.childNodes);
    } else if (parent instanceof Text) {
      childNodes = [parent];
      parent = parent.parentNode!;
    } else {
      return;
    }

    const nestedNodes: Node[] = [];
    for (let node of childNodes) {
      const initialNodeLength = this.getLength(node);
      // If the current node is completely before the offset.
      if (offset > 0 && initialNodeLength <= offset) {
        offset -= initialNodeLength;
        continue;
      }

      if (offset > 0) {
        node = this.splitNode(node, offset);
        offset = 0;
      }
      if (this.getLength(node) > length) {
        this.splitNode(node, length);
      }
      nestedNodes.push(node);

      length -= this.getLength(node);
      if (!length) break;
    }

    const wrapper = document.createElement(tagName);
    const sanitizer = getSanitizeDOMValue();
    for (let [name, value] of Object.entries(attributes)) {
      if (!value) continue;
      if (sanitizer) {
        value = sanitizer(value, name, 'attribute', wrapper) as string;
      }
      wrapper.setAttribute(name, value);
    }
    for (const inner of nestedNodes) {
      parent.replaceChild(wrapper, inner);
      wrapper.appendChild(inner);
    }
  },

  /**
   * Surrounds the element's text at specified range in an ANNOTATION_TAG
   * element. If the element has child elements, the range is split and
   * applied as deeply as possible.
   */
  annotateElement(
    parent: HTMLElement,
    offset: number,
    length: number,
    cssClass: string
  ) {
    const nodes: Array<HTMLElement | Text> = [].slice.apply(parent.childNodes);
    let nodeLength;
    let subLength;

    for (const node of nodes) {
      nodeLength = this.getLength(node);

      // If the current node is completely before the offset.
      if (nodeLength <= offset) {
        offset -= nodeLength;
        continue;
      }

      // Sublength is the annotation length for the current node.
      subLength = Math.min(length, nodeLength - offset);

      if (node instanceof Text) {
        this._annotateText(node, offset, subLength, cssClass);
      } else if (node instanceof Element) {
        this.annotateElement(node, offset, subLength, cssClass);
      }

      // If there is still more to annotate, then shift the indices, otherwise
      // work is done, so break the loop.
      if (subLength < length) {
        length -= subLength;
        offset = 0;
      } else {
        break;
      }
    }
  },

  /**
   * Wraps node in annotation tag with cssClass, replacing the node in DOM.
   */
  wrapInHighlight(node: Element | Text, cssClass: string) {
    let hl;
    if (!(node instanceof Text) && node.tagName === ANNOTATION_TAG) {
      hl = node;
      hl.classList.add(cssClass);
    } else {
      hl = document.createElement(ANNOTATION_TAG);
      hl.className = cssClass;
      if (node.parentElement) node.parentElement.replaceChild(hl, node);
      hl.appendChild(node);
    }
    return hl;
  },

  /**
   * Splits Text Node and wraps it in hl with cssClass.
   * Wraps trailing part after split, tailing one if firstPart is true.
   */
  splitAndWrapInHighlight(
    node: Text,
    offset: number,
    cssClass: string,
    firstPart?: boolean
  ) {
    if (this.getLength(node) === offset || offset === 0) {
      return this.wrapInHighlight(node, cssClass);
    } else {
      if (firstPart) {
        this.splitNode(node, offset);
        // Node points to first part of the Text, second one is sibling.
      } else {
        // if node is Text then splitNode will return a Text
        node = this.splitNode(node, offset) as Text;
      }
      return this.wrapInHighlight(node, cssClass);
    }
  },

  /**
   * Splits Node at offset.
   * If Node is Element, it's cloned and the node at offset is split too.
   */
  splitNode(element: Node, offset: number) {
    if (element instanceof Text) {
      return this.splitTextNode(element, offset);
    }
    const tail = element.cloneNode(false);

    if (element.parentElement)
      element.parentElement.insertBefore(tail, element.nextSibling);
    // Skip nodes before offset.
    let node = element.firstChild;
    while (
      node &&
      (this.getLength(node) <= offset || this.getLength(node) === 0)
    ) {
      offset -= this.getLength(node);
      node = node.nextSibling;
    }
    if (node && this.getLength(node) > offset) {
      tail.appendChild(this.splitNode(node, offset));
    }
    while (node && node.nextSibling) {
      tail.appendChild(node.nextSibling);
    }
    return tail;
  },

  /**
   * Node.prototype.splitText Unicode-valid alternative.
   *
   * DOM Api for splitText() is broken for Unicode:
   * https://mathiasbynens.be/notes/javascript-unicode
   *
   * @return Trailing Text Node.
   */
  splitTextNode(node: Text, offset: number) {
    if (node.textContent?.match(REGEX_ASTRAL_SYMBOL)) {
      // TODO (viktard): Polyfill Array.from for IE10.
      const head = Array.from(node.textContent);
      const tail = head.splice(offset);
      const parent = node.parentNode;

      // Split the content of the original node.
      node.textContent = head.join('');

      const tailNode = document.createTextNode(tail.join(''));
      if (parent) {
        parent.insertBefore(tailNode, node.nextSibling);
      }
      return tailNode;
    } else {
      return node.splitText(offset);
    }
  },

  _annotateText(node: Text, offset: number, length: number, cssClass: string) {
    const nodeLength = this.getLength(node);

    // There are four cases:
    //  1) Entire node is highlighted.
    //  2) Highlight is at the start.
    //  3) Highlight is at the end.
    //  4) Highlight is in the middle.

    if (offset === 0 && nodeLength === length) {
      // Case 1.
      this.wrapInHighlight(node, cssClass);
    } else if (offset === 0) {
      // Case 2.
      this.splitAndWrapInHighlight(node, length, cssClass, true);
    } else if (offset + length === nodeLength) {
      // Case 3
      this.splitAndWrapInHighlight(node, offset, cssClass, false);
    } else {
      // Case 4
      this.splitAndWrapInHighlight(
        this.splitTextNode(node, offset),
        length,
        cssClass,
        true
      );
    }
  },
};

/**
 * Data used to construct an element.
 *
 */
export interface ElementSpec {
  tagName: string;
  attributes?: {[attributeName: string]: string | undefined};
}
