import type { RegexFlavourId } from "../model/flavour";
import type { WorkerFactory } from "./WorkerSupervisor";

export interface EngineWorkerRegistration {
  readonly flavour: RegexFlavourId;
  readonly label: string;
  readonly startupTimeoutMs: number;
  readonly createWorker: WorkerFactory;
}

export class EngineWorkerRegistry {
  readonly registrations: readonly EngineWorkerRegistration[];
  private readonly byFlavour: ReadonlyMap<
    RegexFlavourId,
    EngineWorkerRegistration
  >;

  constructor(registrations: readonly EngineWorkerRegistration[]) {
    const byFlavour = new Map<RegexFlavourId, EngineWorkerRegistration>();
    for (const registration of registrations) {
      if (byFlavour.has(registration.flavour)) {
        throw new Error(
          `Execution worker for ${registration.flavour} is registered more than once.`,
        );
      }
      byFlavour.set(registration.flavour, registration);
    }
    this.registrations = [...registrations];
    this.byFlavour = byFlavour;
  }

  get(flavour: RegexFlavourId): EngineWorkerRegistration | undefined {
    return this.byFlavour.get(flavour);
  }

  require(flavour: RegexFlavourId): EngineWorkerRegistration {
    const registration = this.get(flavour);
    if (registration) return registration;
    throw new Error(
      `No execution worker is registered for regex flavour ${JSON.stringify(flavour)}.`,
    );
  }
}

export const ENGINE_WORKER_REGISTRY = new EngineWorkerRegistry([
  {
    flavour: "ecmascript",
    label: "ECMAScript engine",
    startupTimeoutMs: 1_000,
    createWorker: () =>
      new Worker(
        new URL("../../workers/ecmascript.worker.ts", import.meta.url),
        {
          type: "module",
          name: "regex-tools-ecmascript",
        },
      ),
  },
  {
    flavour: "pcre2",
    label: "PCRE2 engine",
    startupTimeoutMs: 10_000,
    createWorker: () =>
      new Worker(new URL("../../workers/pcre2.worker.ts", import.meta.url), {
        type: "module",
        name: "regex-tools-pcre2",
      }),
  },
  {
    flavour: "python",
    label: "Python re engine",
    startupTimeoutMs: 30_000,
    createWorker: () =>
      new Worker(new URL("../../workers/python.worker.ts", import.meta.url), {
        type: "module",
        name: "regex-tools-python",
      }),
  },
  {
    flavour: "java",
    label: "Java regex engine",
    startupTimeoutMs: 15_000,
    createWorker: () =>
      new Worker(new URL("../../workers/java.worker.ts", import.meta.url), {
        type: "module",
        name: "regex-tools-java",
      }),
  },
]);
