import hljs from "deps/hljs.ts";

export class ChatResponse {
  element = (<article className="assistant" />);

  currentLine: Text | undefined;

  codeBlockContext: Element | undefined;
  thinkingContext: HTMLDetailsElement | undefined;

  currentContext(): Element {
    if (this.codeBlockContext) return this.codeBlockContext;
    if (this.thinkingContext) return this.thinkingContext;
    return this.element;
  }

  finalizeLine() {
    if (!this.currentLine?.textContent) return;
    const line = this.currentLine.textContent;

    if (!this.thinkingContext && line === "<think>") {
      this.thinkingContext = (
        <details open>
          <summary>{`<think />`}</summary>
        </details>
      ) as HTMLDetailsElement;
      this.thinkingContext.dataset.inProgress = "";
      this.element.append(this.thinkingContext);
      this.currentLine.remove();
    } else if (this.thinkingContext && line === "</think>") {
      this.currentLine.remove();
      this.thinkingContext.open = false;
      delete this.thinkingContext.dataset.inProgress;
      this.thinkingContext = undefined;
    }

    if (line.startsWith("```")) {
      const remainder = line.substring(3).trimStart();
      this.currentLine.remove();

      if (!this.codeBlockContext) {
        const pre = (
          <pre>
            <code className={`language-${remainder}`} />
          </pre>
        );
        this.currentContext().append(pre);
        this.codeBlockContext = pre.querySelector("code")!;
      } else {
        hljs.highlightElement(this.codeBlockContext as HTMLElement);

        this.codeBlockContext = undefined;
        this.currentContext().append(remainder);
      }
    }
  }

  append(text: string) {
    const tokens = text
      .split(/(\s+)/)
      .flatMap(s => s.split(/(\n)/))
      .filter(s => s);
    for (const token of tokens) {
      if (token === "\n") {
        if (!this.currentLine) continue;

        this.finalizeLine();
        this.currentLine.appendData(token);
        this.currentLine = undefined;
        continue;
      }

      if (this.currentLine === undefined) {
        this.currentLine = document.createTextNode(token);
        this.currentContext().append(this.currentLine);
      } else {
        this.currentLine.appendData(token);
      }
    }
  }

  finalize() {
    this.finalizeLine();

    // TODO: check if we have a dangling think section or code block and lift it back out
  }
}
