// This Source Code Form is subject to the terms of the Mozilla Public
// License, v2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/
//import init, { decode_i420_simd } from "./pkg/viewer_rust_decoder.js";
/**
 * Provides a worker that can process RawImages on a background thread.
 *
 * The input image data must be **copied** to the worker, because image messages may be used
 * concurrently by other panels and features of the app. However, the resulting decoded data is
 * [transferred](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Transferable_objects)
 * back to the main thread.
 */
export class WorkerImageDecoder {
    //#wasmInitialized = false;
    #worker; // have more workers
    //#reusableBuffer: SharedArrayBuffer | null = null;
    #pendingDecodes = new Map();
    #nextMessageId = 0;
    #isTerminated = false;
    constructor() {
        this.#worker = new Worker(
        // foxglove-depcheck-used: babel-plugin-transform-import-meta
        new URL("./WorkerImageDecoder.worker", import.meta.url), { type: "module" });
        // Set up a single persistent message handler
        this.#worker.onmessage = (event) => {
            const { id, error, result } = event.data;
            const handlers = this.#pendingDecodes.get(id);
            if (!handlers) {
                // Message for an already-resolved or terminated decode, ignore it
                return;
            }
            this.#pendingDecodes.delete(id);
            if (error) {
                handlers.reject(new Error(error));
            }
            else {
                handlers.resolve(new ImageData(result, handlers.width, handlers.height));
            }
        };
        // Handle worker errors (e.g., uncaught exceptions in worker)
        this.#worker.onerror = (event) => {
            const errorMessage = `Worker error: ${event.message}`;
            // Reject all pending decodes
            for (const handlers of this.#pendingDecodes.values()) {
                handlers.reject(new Error(errorMessage));
            }
            this.#pendingDecodes.clear();
        };
    }
    /**
     * Copies `image` to the worker, and transfers the decoded result back to the main thread.
     */
    decode(image, options) {
        if (this.#isTerminated) {
            return Promise.reject(new Error("Worker has been terminated"));
        }
        return new Promise((resolve, reject) => {
            const messageId = this.#nextMessageId++;
            this.#pendingDecodes.set(messageId, {
                resolve,
                reject,
                width: image.width,
                height: image.height,
            });
            // TODO: Try using shared buffer for input data as well
            this.#worker.postMessage({ id: messageId, image, options }, [
                image.data.buffer,
            ]);
        });
    }
    //public async decodeOnMain(image: RosImage | RawImage, options: Partial<RawImageOptions>): Promise<ImageData | ImageBitmap> {
    //    const requiredSize = image.width * image.height * 4;
    //
    //    // Create or resize buffer if needed
    //    if (!this.#reusableBuffer || this.#reusableBuffer.length < requiredSize) {
    //      console.log('Resizing buffer', this.#reusableBuffer?.length);
    //      this.#reusableBuffer = new Uint8ClampedArray(requiredSize);
    //    }
    //
    //    return decodeRawImage(image, options, this.#reusableBuffer).then(() => {
    //      return new ImageData(this.#reusableBuffer!, image.width, image.height);
    //    });
    //}
    //public async decodeRust(
    //  image: RosImage | RawImage,
    //  options: Partial<RawImageOptions>,
    //): Promise<ImageData> {
    //  if (!this.#wasmInitialized) {
    //    console.log("Initializing wasm decoder");
    //    await init();
    //    this.#wasmInitialized = true;
    //  }
    //
    //  // TODO: Potentially use async rs function to improve performance
    //  const decodedBuffer: Uint8Array = decode_i420_simd(
    //    image.data as Uint8Array,
    //    image.width,
    //    image.height,
    //    0,
    //  );
    //
    //  return new ImageData(new Uint8ClampedArray(decodedBuffer), image.width, image.height);
    //}
    terminate() {
        if (this.#isTerminated) {
            return;
        }
        this.#isTerminated = true;
        // Reject all pending decode operations to prevent memory leaks
        const terminationError = new Error("Worker terminated");
        for (const handlers of this.#pendingDecodes.values()) {
            handlers.reject(terminationError);
        }
        this.#pendingDecodes.clear();
        this.#worker.terminate();
    }
}
//# sourceMappingURL=WorkerImageDecoder.js.map