import type {
  RegexExecutionRequest,
  RegexExecutionResult,
  RegexReplacementRequest,
  RegexReplacementResult,
} from "../model/match";
import type {
  RegexSyntaxRequest,
  RegexSyntaxResult,
  ReplacementSyntaxResult,
} from "../model/syntax";
import type { RegexEngineInfo } from "../model/flavour";
import type { ReplacementSyntaxRequest } from "../syntax/SyntaxProvider";
import type { Pcre2TraceRequest, Pcre2TraceResult } from "../model/trace";

export const WORKER_PROTOCOL_VERSION = 2;

export type SyntaxWorkerOperation =
  | {
      readonly kind: "parse-pattern";
      readonly request: RegexSyntaxRequest;
    }
  | {
      readonly kind: "parse-replacement";
      readonly request: ReplacementSyntaxRequest;
    };

export type SyntaxWorkerResult =
  | {
      readonly kind: "parse-pattern";
      readonly result: RegexSyntaxResult;
    }
  | {
      readonly kind: "parse-replacement";
      readonly result: ReplacementSyntaxResult;
    };

export type EngineWorkerOperation =
  | {
      readonly kind: "load";
    }
  | {
      readonly kind: "execute";
      readonly request: RegexExecutionRequest;
    }
  | {
      readonly kind: "replace";
      readonly request: RegexReplacementRequest;
    };

export type EngineWorkerResult =
  | {
      readonly kind: "load";
      readonly info: RegexEngineInfo;
    }
  | {
      readonly kind: "execute";
      readonly result: RegexExecutionResult;
    }
  | {
      readonly kind: "replace";
      readonly result: RegexReplacementResult;
    };

export interface TraceWorkerOperation {
  readonly kind: "trace";
  readonly request: Pcre2TraceRequest;
}

export interface TraceWorkerResult {
  readonly kind: "trace";
  readonly result: Pcre2TraceResult;
}

export interface WorkerRequest<T> {
  readonly protocolVersion: typeof WORKER_PROTOCOL_VERSION;
  readonly requestId: number;
  readonly generation: number;
  readonly payload: T;
}

export type WorkerResponse<T> =
  | {
      readonly protocolVersion: typeof WORKER_PROTOCOL_VERSION;
      readonly requestId: number;
      readonly generation: number;
      readonly ok: true;
      readonly payload: T;
    }
  | {
      readonly protocolVersion: typeof WORKER_PROTOCOL_VERSION;
      readonly requestId: number;
      readonly generation: number;
      readonly ok: false;
      readonly error: {
        readonly name: string;
        readonly message: string;
      };
    };

export function workerError(error: unknown): {
  readonly name: string;
  readonly message: string;
} {
  return error instanceof Error
    ? { name: error.name, message: error.message }
    : { name: "Error", message: String(error) };
}
