/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
 * @module Utils
 */
import { assert } from "@itwin/core-bentley";
/** Create a [[WorkerProxy]] implementing the methods of `T` using the specified worker script.
 * See [this article]($docs/learning/frontend/WorkerProxy.md) for more details and examples.
 * @beta
 */
export function createWorkerProxy(workerJsPath) {
    const tasks = new Map();
    let curMsgId = 0;
    let terminated = false;
    let worker;
    const sameOrigin = workerJsPath.substring(0, globalThis.origin.length) === globalThis.origin;
    if (sameOrigin || !workerJsPath.startsWith("http")) {
        worker = new Worker(workerJsPath);
    }
    else {
        const workerBlob = new Blob([`importScripts("${workerJsPath}");`]);
        const workerBlobUrl = URL.createObjectURL(workerBlob);
        worker = new Worker(workerBlobUrl);
    }
    worker.onmessage = (e) => {
        const response = e.data;
        assert(typeof response === "object");
        assert("result" in response || "error" in response);
        const task = tasks.get(response.msgId);
        if (task) {
            tasks.delete(response.msgId);
            if (response.error)
                task.reject(response.error);
            else
                task.resolve(response.result);
        }
    };
    return new Proxy({}, {
        get(_target, operation) {
            if (operation === "terminate") {
                assert(!terminated);
                terminated = true;
                return () => worker.terminate();
            }
            else if (operation === "isTerminated") {
                return terminated;
            }
            else {
                return async (...args) => new Promise((resolve, reject) => {
                    const msgId = ++curMsgId;
                    tasks.set(msgId, { resolve, reject });
                    worker.postMessage({ operation, payload: args[0], msgId }, args[1] ?? []);
                });
            }
        },
    });
}
//# sourceMappingURL=WorkerProxy.js.map