/**
 * @license
 * Copyright 2022 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import {
  SyntaxLayerLine,
  SyntaxLayerRange,
  UNCLOSED,
} from '../types/syntax-worker-api';

/**
 * Utilities related to working with the HighlightJS syntax highlighting lib.
 *
 * Note that this utility is mostly used by the syntax-worker, which is a Web
 * Worker and can thus not depend on document, the DOM or any related
 * functionality.
 */

/**
 * With these expressions you can match exactly what HighlightJS produces. It
 * is really that simple:
 * https://github.com/highlightjs/highlight.js/blob/main/src/lib/html_renderer.js
 */
const openingSpan = new RegExp('<span class="([^"]*?)">');
const closingSpan = new RegExp('</span>');

/**
 * Reverse what HighlightJS does in `escapeHTML()`, see:
 * https://github.com/highlightjs/highlight.js/blob/main/src/lib/utils.js
 */
function unescapeHTML(value: string) {
  return value
    .replace(/&#x27;/g, "'")
    .replace(/&quot;/g, '"')
    .replace(/&gt;/g, '>')
    .replace(/&lt;/g, '<')
    .replace(/&amp;/g, '&');
}

function equal(r: SyntaxLayerRange) {
  return (s: SyntaxLayerRange) =>
    r.start === s.start && r.length === s.length && r.className === s.className;
}

function unique(r: SyntaxLayerRange, index: number, array: SyntaxLayerRange[]) {
  return index === array.findIndex(equal(r));
}

/**
 * HighlightJS produces one long HTML string with HTML elements spanning
 * multiple lines. <gr-diff> is line based, needs all elements closed at the end
 * of the line, and is not interested in the HTML that HighlightJS produces.
 *
 * So we are splitting the HTML string up into lines and process them one by
 * one. Each <span> is detected, converted into a SyntaxLayerRange and removed.
 * Unclosed spans will be carried over to the next line.
 */
export function highlightedStringToRanges(
  highlightedCode: string
): SyntaxLayerLine[] {
  // What the function eventually returns.
  const rangesPerLine: SyntaxLayerLine[] = [];
  // The unclosed ranges that are carried over from one line to the next.
  let carryOverRanges: SyntaxLayerRange[] = [];

  for (let line of highlightedCode.split('\n')) {
    const ranges: SyntaxLayerRange[] = [...carryOverRanges];
    carryOverRanges = [];

    // Remove all span tags one after another from left to right.
    // For each opening <span ...> push a new (unclosed) range.
    // For each closing </span> close the latest unclosed range.
    let removal: SpanRemoval | undefined;
    while ((removal = removeFirstSpan(line)) !== undefined) {
      if (removal.type === SpanType.OPENING) {
        ranges.push({
          start: removal.offset,
          length: UNCLOSED,
          className: removal.class ?? '',
        });
      } else {
        const unclosed = lastUnclosed(ranges);
        unclosed.length = removal.offset - unclosed.start;
      }
      line = removal.lineAfter;
    }

    // All unclosed spans need to have the length set such that they extend to
    // the end of the line. And they have to be carried over to the next line
    // as cloned objects with start:0.
    const lineLength = line.length;
    for (const range of ranges) {
      if (isUnclosed(range)) {
        carryOverRanges.push({...range, start: 0});
        range.length = lineLength - range.start;
      }
    }
    rangesPerLine.push({
      ranges: ranges.filter(r => r.length > 0).filter(unique),
    });
  }
  if (carryOverRanges.length > 0) {
    throw new Error('unclosed <span>s in highlighted code');
  }
  return rangesPerLine;
}

function isUnclosed(range: SyntaxLayerRange) {
  return range.length === UNCLOSED;
}

function lastUnclosed(ranges: SyntaxLayerRange[]) {
  const unclosed = [...ranges].reverse().find(isUnclosed);
  if (!unclosed) throw new Error(`no unclosed range found ${ranges.length}`);
  return unclosed;
}

/** Used for `type` in SpanRemoval. */
export enum SpanType {
  OPENING,
  CLOSING,
}

/** Return type for removeFirstSpan(). */
export interface SpanRemoval {
  type: SpanType;
  /** The line string after removing the matched span tag. */
  lineAfter: string;
  /** The matched css class for OPENING spans. undefined for CLOSING. */
  class?: string;
  /** At which char in the line did the removed span tag start? */
  offset: number;
}

/**
 * Finds the first <span ...> or </span>, removes it from the line and returns
 * details about the removal. Returns `undefined`, if neither is found.
 */
export function removeFirstSpan(line: string): SpanRemoval | undefined {
  const openingMatch = openingSpan.exec(line);
  const openingIndex = openingMatch?.index ?? Number.MAX_VALUE;
  const closingMatch = closingSpan.exec(line);
  const closingIndex = closingMatch?.index ?? Number.MAX_VALUE;
  if (openingIndex === Number.MAX_VALUE && closingIndex === Number.MAX_VALUE) {
    return undefined;
  }
  const type =
    openingIndex < closingIndex ? SpanType.OPENING : SpanType.CLOSING;
  const match = type === SpanType.OPENING ? openingMatch : closingMatch;
  if (match === null) return undefined;
  const length = match[0].length;
  const offsetEscaped = type === SpanType.OPENING ? openingIndex : closingIndex;
  const lineUpToMatch = line.slice(0, offsetEscaped);
  const lineAfterMatch = line.slice(offsetEscaped + length);
  // We are parsing HTML, so escaped characters must only count as one char.
  const offsetUnescaped = unescapeHTML(lineUpToMatch).length;
  const removal: SpanRemoval = {
    type,
    lineAfter: lineUpToMatch + lineAfterMatch,
    offset: offsetUnescaped,
    class: type === SpanType.OPENING ? match[1] : undefined,
  };
  return removal;
}
