import {
  WorkerSupervisor,
  type WorkerFactory,
} from "../execution/WorkerSupervisor";
import type {
  CandidateGenerationReport,
  CandidateGenerationRequest,
  GenerationWorkerOperation,
  GenerationWorkerResult,
} from "./generation.types";

export interface GenerationWorkerClient {
  generate(
    request: CandidateGenerationRequest,
    timeoutMs: number,
  ): Promise<CandidateGenerationReport>;
  cancel(): void;
  dispose(): void;
}

const createGenerationWorker: WorkerFactory = () =>
  new Worker(new URL("../../workers/generation.worker.ts", import.meta.url), {
    type: "module",
    name: "regex-tools-case-generation",
  });

export class GenerationSupervisor implements GenerationWorkerClient {
  readonly #supervisor: WorkerSupervisor<
    GenerationWorkerOperation,
    GenerationWorkerResult
  >;

  constructor(workerFactory: WorkerFactory = createGenerationWorker) {
    this.#supervisor = new WorkerSupervisor(
      "Generated-case synthesis worker",
      workerFactory,
    );
  }

  async generate(
    request: CandidateGenerationRequest,
    timeoutMs: number,
  ): Promise<CandidateGenerationReport> {
    const response = await this.#supervisor.run(
      { kind: "generate", request },
      timeoutMs,
      { supersede: true },
    );
    if (response.kind !== "generate") {
      throw new Error(
        "Generated-case worker returned the wrong response kind.",
      );
    }
    return response.result;
  }

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

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