/// <reference lib="webworker" />
/**
 * Imported FIRST by mupdf.worker.ts. ES modules run each import (and its
 * top-level await) fully before the importing module's body, so everything here
 * executes before mupdf's ~10MB wasm instantiates.
 *
 * Two problems this solves, both of which otherwise make callers hang forever:
 *
 * 1) LOST MESSAGES. A dedicated worker's message port is enabled immediately, so
 *    any message posted while the worker is still loading (mupdf's wasm load is a
 *    top-level await that delays installing the real `onmessage`) is dispatched
 *    to no handler and dropped. We register a bufferer synchronously here — before
 *    the wasm fetch below — and replay the queue via installHandler() once the
 *    real handler is ready.
 *
 * 2) WASM LOAD PATH. mupdf's bootstrap chooses between instantiateStreaming and a
 *    Node branch guarded by `typeof process`; under Vite's dev worker neither
 *    completes and the load stalls (the production bundle is fine). Handing
 *    Emscripten the bytes via `Module.wasmBinary` skips streaming, fetch-by-URL
 *    and the Node branch entirely. We read them from a Vite `?url` asset (correct
 *    MIME in dev, hashed asset in the build).
 */
import wasmUrl from '../../node_modules/mupdf/dist/mupdf-wasm.wasm?url';

self.addEventListener('error', (e) => {
  (self as unknown as Worker).postMessage({ id: -1, ok: false, error: `worker error: ${e.message || e.filename || 'unknown'}` });
});
self.addEventListener('unhandledrejection', (e) => {
  (self as unknown as Worker).postMessage({ id: -1, ok: false, error: `worker load failed: ${String((e as PromiseRejectionEvent).reason)}` });
});

// (1) buffer any messages that arrive before the real handler is installed
const buffered: MessageEvent[] = [];
const bufferer = (e: MessageEvent) => { buffered.push(e); };
self.addEventListener('message', bufferer);

/** Install the real message handler and replay anything received while loading. */
export function installHandler(handler: (e: MessageEvent) => void) {
  self.removeEventListener('message', bufferer);
  self.onmessage = handler as (this: unknown, ev: MessageEvent) => void;
  for (const e of buffered.splice(0)) handler(e);
}

// (2) fetch the wasm bytes (AFTER the bufferer is registered) and hand them to mupdf
const wasmBinary = await (await fetch(wasmUrl)).arrayBuffer();
(globalThis as unknown as { $libmupdf_wasm_Module?: unknown }).$libmupdf_wasm_Module = { wasmBinary };
