"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.installTask = installTask;
const worker_threads_1 = require("worker_threads");
const evaluator_1 = require("../language/evaluator");
const runtime_1 = require("../language/runtime");
const NULL = new evaluator_1.NullObj();
function asString(obj) {
    return obj instanceof evaluator_1.StringObj ? obj.value : null;
}
/**
 * Concurrent task scheduling — green tasks via NexusRuntime and optional
 * Worker-thread offload for CPU-bound string jobs.
 */
function installTask(env, runtime) {
    const rt = runtime ?? new runtime_1.NexusRuntime();
    env.set("spawn_task", new evaluator_1.BuiltinObj((...args) => {
        if (args.length !== 1) {
            return new evaluator_1.ErrorObj("spawn_task: want 1 function");
        }
        const fn = args[0];
        // Functions are applied by evaluator; here we schedule a no-op marker
        // and return a task id. Full fn application happens via spawn expr.
        const handle = rt.spawn(async () => {
            void fn;
        });
        return new evaluator_1.IntegerObj(handle.id);
    }));
    env.set("task_yield", new evaluator_1.BuiltinObj(() => {
        return new runtime_1.PromiseObj(rt.yield().then(() => NULL));
    }));
    env.set("worker_hash", new evaluator_1.BuiltinObj((...args) => {
        if (args.length !== 1) {
            return new evaluator_1.ErrorObj("worker_hash: want 1 string");
        }
        const input = asString(args[0]);
        if (input === null) {
            return new evaluator_1.ErrorObj("worker_hash: want string");
        }
        const promise = new Promise((resolve) => {
            // Inline worker source to avoid extra files
            const code = `
          const { parentPort, workerData } = require('worker_threads');
          const crypto = require('crypto');
          const digest = crypto.createHash('sha256').update(workerData, 'utf8').digest('hex');
          parentPort.postMessage(digest);
        `;
            try {
                const worker = new worker_threads_1.Worker(code, {
                    eval: true,
                    workerData: input,
                });
                worker.on("message", (msg) => {
                    resolve(new evaluator_1.StringObj(msg));
                    void worker.terminate();
                });
                worker.on("error", (err) => {
                    resolve(new evaluator_1.ErrorObj(`worker_hash: ${err.message}`));
                });
            }
            catch (err) {
                // Fallback on hosts that block workers
                const crypto = require("crypto");
                resolve(new evaluator_1.StringObj(crypto.createHash("sha256").update(input, "utf8").digest("hex")));
                void err;
            }
        });
        return new runtime_1.PromiseObj(promise);
    }));
    env.set("task_drain", new evaluator_1.BuiltinObj(() => new runtime_1.PromiseObj(rt.drain().then(() => NULL))));
}
//# sourceMappingURL=task.js.map