import { logger } from "../logger.js";
import { WorkerPool } from "../workers/WorkerPool.js";
import { getEncoderWorkerUrl } from "../workers/encoderWorkerInline.js";
import { encodeCanvasOnMainThread } from "./mainThreadEncoder.js";
import { encodeCanvasInWorker } from "./workerEncoder.js";

//#region src/preview/encoding/canvasEncoder.ts
let _workerPool = null;
let _workerPoolWarningLogged = false;
/**
* Get or create the worker pool for canvas encoding.
* Returns null if workers are not available.
*/
function getWorkerPool() {
	if (_workerPool) return _workerPool;
	if (typeof Worker === "undefined" || typeof OffscreenCanvas === "undefined" || typeof createImageBitmap === "undefined") {
		if (!_workerPoolWarningLogged) {
			_workerPoolWarningLogged = true;
			logger.warn("[canvasEncoder] Web Workers or OffscreenCanvas not available, using main thread fallback");
		}
		return null;
	}
	try {
		_workerPool = new WorkerPool(getEncoderWorkerUrl());
		if (!_workerPool.isAvailable()) {
			const reason = _workerPool.workerCount === 0 ? "no workers created (check console for errors)" : "workers not available";
			_workerPool = null;
			if (!_workerPoolWarningLogged) {
				_workerPoolWarningLogged = true;
				logger.warn(`[canvasEncoder] Worker pool initialization failed (${reason}), using main thread fallback`);
			}
		}
	} catch (error) {
		_workerPool = null;
		if (!_workerPoolWarningLogged) {
			_workerPoolWarningLogged = true;
			const errorMessage = error instanceof Error ? error.message : String(error);
			logger.warn(`[canvasEncoder] Failed to create worker pool: ${errorMessage} - using main thread fallback`);
		}
	}
	return _workerPool;
}
/**
* Encode canvases to data URLs in parallel using worker pool.
* Falls back to main thread encoding if workers are unavailable.
*
* When RenderContext and sourceMap are provided:
* - Checks cache for static elements (ef-image, ef-waveform)
*
* @param canvases - Array of canvases to encode
* @param options - Encoding options including optional renderContext and sourceMap
* @returns Promise resolving to array of encoded results
*/
async function encodeCanvasesInParallel(canvases, options = {}) {
	const { scale: canvasScale = 1, renderContext, sourceMap } = options;
	const workerPool = getWorkerPool();
	const encodeCanvas = async (canvas) => {
		try {
			if (canvas.width === 0 || canvas.height === 0) return null;
			const preserveAlpha = canvas.dataset.preserveAlpha === "true";
			const sourceElement = sourceMap?.get(canvas);
			if (renderContext && sourceElement) {
				const cachedDataUrl = renderContext.getCachedCanvasDataUrl(sourceElement);
				if (cachedDataUrl) return {
					canvas,
					dataUrl: cachedDataUrl,
					preserveAlpha
				};
			}
			let sourceCanvas = canvas;
			if (canvasScale < 1) {
				const scaledWidth = Math.floor(canvas.width * canvasScale);
				const scaledHeight = Math.floor(canvas.height * canvasScale);
				const scaledCanvas = document.createElement("canvas");
				scaledCanvas.width = scaledWidth;
				scaledCanvas.height = scaledHeight;
				const scaledCtx = scaledCanvas.getContext("2d");
				if (scaledCtx) {
					scaledCtx.drawImage(canvas, 0, 0, scaledWidth, scaledHeight);
					sourceCanvas = scaledCanvas;
				}
			}
			let dataUrl;
			if (workerPool) dataUrl = await workerPool.execute((worker) => encodeCanvasInWorker(worker, sourceCanvas, preserveAlpha));
			else {
				const encoded = encodeCanvasOnMainThread(sourceCanvas, canvasScale);
				if (!encoded) return null;
				dataUrl = encoded.dataUrl;
			}
			if (renderContext && sourceElement) renderContext.setCachedCanvasDataUrl(sourceElement, dataUrl);
			return {
				canvas,
				dataUrl,
				preserveAlpha
			};
		} catch (error) {
			logger.warn("[canvasEncoder] Worker encoding failed, using main thread fallback:", error);
			const encoded = encodeCanvasOnMainThread(canvas, canvasScale);
			if (encoded) {
				logger.warn("[canvasEncoder] Main thread fallback succeeded");
				return {
					canvas,
					...encoded
				};
			}
			logger.warn("[canvasEncoder] Main thread encoding also failed, skipping canvas:", error);
			return null;
		}
	};
	const encodingTasks = canvases.map(encodeCanvas);
	return (await Promise.all(encodingTasks)).filter((r) => r !== null);
}

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