import { onMessage, postMessage } from '#worker-polyfill';
import { checkError, compress, decompress, fromHeap, Helper, Module, ModuleReady, setWasmCallbacks } from './common.js';
import { checkLevel } from '../utils.js';
let mode;
let ptr;
/** Called when chunks generated from wasm */
function onChunkData(state, ctx, dst, dstSize) {
    if (ptr !== ctx || state !== mode) {
        postMessage([null, null, new Error(`Invalid context for ${state}`)]);
    }
    const chunk = fromHeap(dst, dstSize);
    postMessage([null, chunk], [chunk.buffer]);
}
/** stream mode clean up */
function cleanUp() {
    ptr = undefined;
    mode = undefined;
}
setWasmCallbacks({
    onCompressorData: (ctx, dst, dstSize) => onChunkData('Compressor', ctx, dst, dstSize),
    onDecompressorData: (ctx, dst, dstSize) => onChunkData('Decompressor', ctx, dst, dstSize),
});
onMessage(async (data) => {
    const [seq, method, args] = data;
    try {
        switch (method) {
            case 'compress': {
                const [data, level] = args;
                const src = ArrayBuffer.isView(data) ? data : new Uint8Array(await data.arrayBuffer());
                const dst = compress(src, level);
                postMessage([seq, dst], [dst.buffer]);
                break;
            }
            case 'decompress': {
                const [data] = args;
                const src = ArrayBuffer.isView(data) ? data : new Uint8Array(await data.arrayBuffer());
                const dst = decompress(src);
                postMessage([seq, dst], [dst.buffer]);
                break;
            }
            case 'Compressor': {
                if (ptr != null || mode != null) {
                    throw new Error('Invalid context');
                }
                let [level] = args;
                level = checkLevel(level);
                ptr = checkError(Module._CompressorCreate(level));
                mode = 'Compressor';
                postMessage([seq]);
                break;
            }
            case 'Decompressor': {
                if (ptr != null || mode != null) {
                    throw new Error('Invalid context');
                }
                ptr = checkError(Module._DecompressorCreate());
                mode = 'Decompressor';
                postMessage([seq]);
                break;
            }
            case 'push': {
                if (ptr == null || mode == null) {
                    throw new Error('Invalid context');
                }
                const [src] = args;
                const helper = new Helper();
                try {
                    const srcSize = src.byteLength;
                    const srcPtr = helper.toHeap(src);
                    if (mode === 'Compressor') {
                        checkError(Module._CompressorData(ptr, srcPtr, srcSize));
                    }
                    else {
                        checkError(Module._DecompressorData(ptr, srcPtr, srcSize));
                    }
                }
                catch (ex) {
                    cleanUp();
                    postMessage([null, null, ex]);
                }
                finally {
                    helper.finalize();
                }
                break;
            }
            case 'end': {
                if (ptr == null || mode == null) {
                    throw new Error('Invalid context');
                }
                try {
                    if (mode === 'Compressor') {
                        checkError(Module._CompressorEnd(ptr));
                    }
                    else {
                        checkError(Module._DecompressorEnd(ptr));
                    }
                    postMessage([seq]);
                }
                finally {
                    cleanUp();
                }
                break;
            }
            default:
                throw new Error('Invalid method');
        }
    }
    catch (err) {
        postMessage([seq, null, err]);
    }
});
void ModuleReady.then(() => postMessage('ready'));
//# sourceMappingURL=worker.js.map