// wasm/c/lumbda-c.loader.js
// C tier loader — Emscripten ES module factory.
//
// Exports createCTier({ baseURL }) -> Promise<{ evalLisp(src) -> Promise<string> }>.
// Output capture: Emscripten routes stdout/stderr through Module.print /
// Module.printErr callbacks. We accumulate per-eval and return joined.

async function _bootstrap() {
    // Use import.meta.url so paths resolve relative to THIS loader file —
    // not the caller. Works in both window and Worker contexts because both
    // have a defined import.meta.url for ES modules.
    const factoryURL = new URL("./lumbda-c.js", import.meta.url).href;
    const wasmDir = new URL("./", import.meta.url).href;
    const { default: createLumbdaC } = await import(/* @vite-ignore */ factoryURL);

    let outBuf = [];
    let errBuf = [];
    const module = await createLumbdaC({
        locateFile: (p) => wasmDir + p,
        print: (line) => outBuf.push(line),
        printErr: (line) => errBuf.push(line),
    });

    const _init = module.cwrap("lumbda_wasm_init", null, []);
    const _eval = module.cwrap("lumbda_wasm_eval", "number", ["string"]);
    const _free = module.cwrap("lumbda_wasm_free_result", null, ["number"]);

    _init();

    return {
        async evalLisp(src) {
            outBuf = [];
            errBuf = [];
            const errPtr = _eval(src);
            let errMsg = "";
            if (errPtr) {
                errMsg = module.UTF8ToString(errPtr);
                _free(errPtr);
            }
            let out = outBuf.join("\n");
            if (out) out += "\n";
            if (errBuf.length) out += errBuf.join("\n") + "\n";
            if (errMsg) out += errMsg + "\n";
            return out;
        },
    };
}

// Closure-encapsulated singleton (see lumbda-c.loader.js for rationale).
export const createCTier = (() => {
    let tier = null;
    return async () => {
        if (!tier) tier = await _bootstrap();
        return tier;
    };
})();
