import { wrap, expose, transferHandlers } from 'comlink';
import { IPFSContentTransferHandler } from './serializers';
import { serializeError } from 'serialize-error';
const isSharedWorkersSupported = typeof SharedWorker !== 'undefined';
const isSharedWorkerUsed = isSharedWorkersSupported && !process.env.IS_DEV;
function installTransferHandlers() {
    transferHandlers.set('IPFSContent', IPFSContentTransferHandler);
}
function safeStringify(obj) {
    try {
        return JSON.stringify(obj);
    }
    catch (error) {
        const serializedError = serializeError(error);
        return JSON.stringify(serializedError, null, 2);
    }
}
function overrideLogging(worker) {
    const consoleLogMap = {
        log: { original: console.log },
        error: { original: console.error },
        warn: { original: console.warn },
    };
    const replaceConsoleLog = (method) => {
        const { original } = consoleLogMap[method];
        consoleLogMap[method].original = console[method];
        console[method] = (...args) => {
            original.apply(console, args);
            const serializableArgs = args.map((arg) => safeStringify(arg));
            worker.postMessage({ type: 'console', method, args: serializableArgs });
        };
    };
    Object.keys(consoleLogMap).forEach((method) => replaceConsoleLog(method));
}
function installLoggingHandler(worker, name) {
    worker.addEventListener('message', (event) => {
        var _a;
        if (((_a = event === null || event === void 0 ? void 0 : event.data) === null || _a === void 0 ? void 0 : _a.type) === 'console') {
            const { method, args } = event === null || event === void 0 ? void 0 : event.data;
            console[method](name, ...args);
        }
    });
}
export function createWorkerApi(workerUrl, workerName) {
    installTransferHandlers();
    if (isSharedWorkerUsed) {
        const worker = new SharedWorker(workerUrl, { name: workerName });
        installLoggingHandler(worker.port, workerName);
        return { worker, workerApiProxy: wrap(worker.port) };
    }
    const worker = new Worker(workerUrl);
    return { worker, workerApiProxy: wrap(worker) };
}
export function exposeWorkerApi(worker, api) {
    installTransferHandlers();
    if (typeof (worker === null || worker === void 0 ? void 0 : worker.onconnect) !== 'undefined') {
        worker === null || worker === void 0 ? void 0 : worker.onconnect = (e) => {
            const port = e.ports[0];
            overrideLogging(port);
            expose(api, port);
        };
    }
    else {
        expose(api);
    }
}
//# sourceMappingURL=factoryMethods.js.map