/// <reference lib="webworker" />

import { PLANEGCS_WASM_CAPABILITIES, solvePlanegcsSubset, type PlanegcsWasmModule } from './planegcsAdapter'
import { assertSketchSolverRequest, type SketchSolverRequest, type SketchSolverResponse } from './sketchSolverProtocol'

type WorkerRequest = { type: 'initialize'; moduleUrl: string } | { type: 'solve'; request: SketchSolverRequest } | { type: 'dispose' }
type WorkerResponse = { type: 'ready'; capabilities: typeof PLANEGCS_WASM_CAPABILITIES } | { type: 'response'; response: SketchSolverResponse } | { type: 'error'; requestId?: string; error: string }

const scope = self as DedicatedWorkerGlobalScope
let module: PlanegcsWasmModule | null = null
const send = (message: WorkerResponse) => scope.postMessage(message)

const initialize = async (moduleUrl: string) => {
  const imported = await import(/* @vite-ignore */ moduleUrl) as { default?: () => Promise<PlanegcsWasmModule> }
  if (typeof imported.default !== 'function') throw new Error('FreeCAD planegcs module has no default Emscripten factory export.')
  module = await imported.default()
  send({ type: 'ready', capabilities: PLANEGCS_WASM_CAPABILITIES })
}

scope.onmessage = ({ data }: MessageEvent<WorkerRequest>) => {
  void (async () => {
    try {
      if (data.type === 'initialize') return await initialize(data.moduleUrl)
      if (data.type === 'dispose') { module = null; scope.close(); return }
      if (!module) throw new Error('FreeCAD planegcs Worker is not initialized.')
      assertSketchSolverRequest(data.request)
      const result = solvePlanegcsSubset(module, data.request.snapshot)
      send({ type: 'response', response: { protocolVersion: data.request.protocolVersion, requestId: data.request.requestId, documentId: data.request.documentId, documentVersion: data.request.documentVersion, generation: data.request.generation, provider: PLANEGCS_WASM_CAPABILITIES, result } })
    } catch (error) {
      send({ type: 'error', requestId: data.type === 'solve' ? data.request.requestId : undefined, error: error instanceof Error ? `${error.name}: ${error.message}` : String(error) })
    }
  })()
}

export {}
