// wasm/python/lumbda-py.js
// Python tier loader — Pyodide (CPython-in-WASM) hosting lumbda.py.
//
// ES module form so it works in both window and Web Worker contexts.
// Exports createPythonTier() -> Promise<{ evalLisp(src) -> Promise<string> }>.

const PYODIDE_VERSION = "0.27.2";
const PYODIDE_INDEX_URL = `https://cdn.jsdelivr.net/pyodide/v${PYODIDE_VERSION}/full/`;

async function _bootstrap() {
    // Dynamic ES-module import works in both window and Worker (module type)
    // contexts. The CDN ships pyodide.mjs alongside pyodide.js.
    const { loadPyodide } = await import(PYODIDE_INDEX_URL + "pyodide.mjs");
    const pyodide = await loadPyodide({ indexURL: PYODIDE_INDEX_URL });

    // Pull lumbda.py + stdlib.lsp into Pyodide's virtual FS. Paths resolve
    // relative to THIS loader (under python/) for both window and Worker.
    const pyURL = new URL("./lumbda.py", import.meta.url).href;
    const stdlibURL = new URL("./stdlib.lsp", import.meta.url).href;
    const lumbdaSrc = await (await fetch(pyURL)).text();
    const stdlibSrc = await (await fetch(stdlibURL)).text();
    pyodide.FS.writeFile("/home/pyodide/lumbda.py", lumbdaSrc);
    pyodide.FS.writeFile("/home/pyodide/stdlib.lsp", stdlibSrc);

    await pyodide.runPythonAsync(`
import sys, io
sys.path.insert(0, "/home/pyodide")
import lumbda
_env = lumbda.make_global_env()
for _e in lumbda.read_all(lumbda.PRELUDE):
    lumbda.leval(_e, _env)

def _lumbda_eval(src):
    buf = io.StringIO()
    old = sys.stdout
    sys.stdout = buf
    last = None
    try:
        for e in lumbda.read_all(src):
            last = lumbda.leval(e, _env)
    except Exception as ex:
        sys.stdout = old
        return f"{buf.getvalue()}error: {ex}"
    sys.stdout = old
    out = buf.getvalue()
    if last is not None and not isinstance(last, lumbda._Void):
        rep = lumbda.show(last)
        if out and not out.endswith("\\n"):
            out += "\\n"
        out += rep
    return out
`);

    return {
        async evalLisp(src) {
            pyodide.globals.set("_src_in", src);
            return await pyodide.runPythonAsync("_lumbda_eval(_src_in)");
        },
    };
}

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