import type {
  RegexSyntaxRequest,
  RegexSyntaxResult,
  ReplacementSyntaxResult,
} from "../model/syntax";
import type { ReplacementSyntaxRequest } from "../syntax/SyntaxProvider";
import { WorkerSupervisor } from "./WorkerSupervisor";
import type {
  SyntaxWorkerOperation,
  SyntaxWorkerResult,
} from "./worker-protocol";

export class SyntaxSupervisor {
  private readonly supervisor: WorkerSupervisor<
    SyntaxWorkerOperation,
    SyntaxWorkerResult
  >;

  constructor(label = "Syntax parser", workerName = "regex-tools-syntax") {
    this.supervisor = new WorkerSupervisor<
      SyntaxWorkerOperation,
      SyntaxWorkerResult
    >(label, () => {
      return new Worker(
        new URL("../../workers/syntax.worker.ts", import.meta.url),
        {
          type: "module",
          name: workerName,
        },
      );
    });
  }

  async parsePattern(
    request: RegexSyntaxRequest,
    timeoutMs = 1_000,
  ): Promise<RegexSyntaxResult> {
    const response = await this.supervisor.run(
      { kind: "parse-pattern", request },
      timeoutMs,
      { supersede: true },
    );
    if (response.kind !== "parse-pattern") {
      throw new Error("Syntax worker returned the wrong response kind");
    }
    return response.result;
  }

  async parseReplacement(
    request: ReplacementSyntaxRequest,
    timeoutMs = 1_000,
  ): Promise<ReplacementSyntaxResult> {
    const response = await this.supervisor.run(
      { kind: "parse-replacement", request },
      timeoutMs,
      { supersede: true },
    );
    if (response.kind !== "parse-replacement") {
      throw new Error("Syntax worker returned the wrong response kind");
    }
    return response.result;
  }

  cancel(): void {
    this.supervisor.cancel();
  }

  dispose(): void {
    this.supervisor.dispose();
  }
}
