import { logger } from "../logger.js";

//#region src/preview/workers/WorkerPool.ts
const WORKER_INIT_TEST_TIMEOUT_MS = 2e3;
var WorkerPool = class {
	constructor(workerScriptUrl, poolSize = navigator.hardwareConcurrency || 4) {
		this.poolSize = poolSize;
		this.workers = [];
		this.availableWorkers = [];
		this.taskQueue = [];
		this.isTerminated = false;
		this.workerUrl = workerScriptUrl;
		if (this.hasBrowserSupport()) this.initializeWorkers();
	}
	/**
	* Check if browser supports workers (before initialization).
	*/
	hasBrowserSupport() {
		return typeof Worker !== "undefined" && typeof OffscreenCanvas !== "undefined" && typeof createImageBitmap !== "undefined";
	}
	initializeWorkers() {
		for (let i = 0; i < this.poolSize; i++) try {
			const worker = new Worker(this.workerUrl, { type: "module" });
			let testTimeout = null;
			let testHandler = null;
			const cleanupTest = () => {
				if (testTimeout !== null) {
					clearTimeout(testTimeout);
					testTimeout = null;
				}
				if (testHandler !== null) {
					worker.removeEventListener("message", testHandler);
					testHandler = null;
				}
			};
			testTimeout = window.setTimeout(() => {
				cleanupTest();
			}, WORKER_INIT_TEST_TIMEOUT_MS);
			testHandler = (event) => {
				if (event.data && typeof event.data === "string" && event.data.includes("encoderWorker")) cleanupTest();
			};
			worker.addEventListener("message", testHandler);
			worker.onerror = (error) => {
				cleanupTest();
				logger.error(`[WorkerPool] Worker ${i} error:`, {
					message: error.message,
					filename: error.filename,
					lineno: error.lineno,
					colno: error.colno
				});
			};
			worker.onmessageerror = (error) => {
				logger.error(`[WorkerPool] Worker ${i} message error:`, error);
			};
			this.workers.push(worker);
			this.availableWorkers.push(worker);
		} catch (error) {
			logger.error(`[WorkerPool] Failed to create worker ${i}:`, error instanceof Error ? error.message : String(error));
		}
		if (this.workers.length === 0) {
			logger.error(`[WorkerPool] Failed to create any workers. URL: ${this.workerUrl}`);
			logger.error(`[WorkerPool] Browser support check:`, {
				Worker: typeof Worker !== "undefined",
				OffscreenCanvas: typeof OffscreenCanvas !== "undefined",
				createImageBitmap: typeof createImageBitmap !== "undefined"
			});
		}
	}
	/**
	* Get the number of workers in the pool.
	*/
	get workerCount() {
		return this.workers.length;
	}
	/**
	* Check if workers are available and initialized.
	*/
	isAvailable() {
		return this.hasBrowserSupport() && this.workers.length > 0 && !this.isTerminated;
	}
	/**
	* Execute a task using an available worker from the pool.
	*/
	async execute(task) {
		if (this.isTerminated) throw new Error("WorkerPool has been terminated");
		if (!this.isAvailable()) throw new Error("Workers not available");
		return new Promise((resolve, reject) => {
			this.taskQueue.push({
				resolve,
				reject,
				task
			});
			this.processQueue();
		});
	}
	processQueue() {
		while (this.availableWorkers.length > 0 && this.taskQueue.length > 0) {
			const worker = this.availableWorkers.shift();
			const queuedTask = this.taskQueue.shift();
			if (!worker || !queuedTask) break;
			const { resolve, reject, task } = queuedTask;
			task(worker).then((result) => {
				resolve(result);
				this.availableWorkers.push(worker);
				this.processQueue();
			}).catch((error) => {
				reject(error instanceof Error ? error : new Error(String(error)));
				this.availableWorkers.push(worker);
				this.processQueue();
			});
		}
	}
	/**
	* Terminate all workers and clear the task queue.
	*/
	terminate() {
		this.isTerminated = true;
		for (const { reject } of this.taskQueue) reject(/* @__PURE__ */ new Error("WorkerPool terminated"));
		this.taskQueue = [];
		for (const worker of this.workers) worker.terminate();
		this.workers = [];
		this.availableWorkers = [];
	}
};

//#endregion
export { WorkerPool };
//# sourceMappingURL=WorkerPool.js.map