/**
 * Code Highlight runtime: highlights the server-printed lines with the in-house tokenizer (the text stays
 * identical, only token spans are added) and wires the copy button (clipboard + "Copied" feedback for 2s).
 */
import { highlightLines } from './tokenize';
import { copyText } from './clipboard';

export const COPIED_MS = 2000;

/** The code as written: the text of every line joined with \n. */
export function codeOf(root: HTMLElement): string {
  return Array.from(root.querySelectorAll<HTMLElement>('.zx-code-highlight__line'), (l) => l.textContent ?? '').join('\n');
}

export default function init(root: HTMLElement): void | (() => void) {
  if (root.dataset.zxInit) return;
  root.dataset.zxInit = '1';

  const lines = Array.from(root.querySelectorAll<HTMLElement>('.zx-code-highlight__line'));
  const code = codeOf(root);
  const lang = root.dataset.zxLang ?? 'text';
  if (lang !== 'text' && !root.dataset.zxHighlighted) {
    const html = highlightLines(code, lang);
    if (html.length === lines.length) {
      lines.forEach((line, i) => {
        line.innerHTML = html[i];
      });
      root.dataset.zxHighlighted = '1';
    }
  }

  const button = root.querySelector<HTMLButtonElement>('.zx-code-highlight__copy');
  const label = root.querySelector<HTMLElement>('.zx-code-highlight__copy-label');
  const status = root.querySelector<HTMLElement>('.zx-code-highlight__status');
  if (!button) {
    return () => {
      delete root.dataset.zxInit;
    };
  }
  const original = label?.textContent ?? '';
  let timer: ReturnType<typeof setTimeout> | undefined;

  const reset = (): void => {
    if (label) label.textContent = original;
    if (status) status.textContent = '';
    root.classList.remove('is-copied');
  };
  const onClick = async (): Promise<void> => {
    const ok = await copyText(codeOf(root), root.ownerDocument);
    if (!ok) return;
    const copied = button.dataset.zxCopied || original;
    if (label) label.textContent = copied;
    if (status) status.textContent = copied;
    root.classList.add('is-copied');
    if (timer) clearTimeout(timer);
    timer = setTimeout(reset, COPIED_MS);
  };
  const handler = (): void => {
    void onClick();
  };
  button.addEventListener('click', handler);
  return () => {
    button.removeEventListener('click', handler);
    if (timer) clearTimeout(timer);
    reset();
    delete root.dataset.zxInit;
  };
}
