"use strict";
Object.defineProperty(exports, "__esModule", {
    value: true
});
Object.defineProperty(exports, "exec", {
    enumerable: true,
    get: function() {
        return exec;
    }
});
function _child_process() {
    const data = require("child_process");
    _child_process = function() {
        return data;
    };
    return data;
}
function _crypto() {
    const data = require("crypto");
    _crypto = function() {
        return data;
    };
    return data;
}
function _promises() {
    const data = require("fs/promises");
    _promises = function() {
        return data;
    };
    return data;
}
function _path() {
    const data = require("path");
    _path = function() {
        return data;
    };
    return data;
}
const _fs = require("./fs");
const _os = require("./os");
async function exec(options) {
    let command = options.command;
    let args = options.args ?? [];
    if (options.usePowershell && (0, _os.isWindows)()) {
        args.unshift("-Command", command);
        args = [
            `"${args.slice(1).join(" ")}"`
        ];
        command = "powershell.exe";
    }
    if (options.escapeCommand) {
        command = `"${command}"`;
    }
    let commandStr = command;
    // Create a temporary script file if the command contains newlines
    let tmpScriptPath;
    if (commandStr.includes("\n")) {
        tmpScriptPath = (0, _path().resolve)(await (0, _fs.tmpDir)(), `${(0, _crypto().randomUUID)()}.sh`);
        await (0, _promises().writeFile)(tmpScriptPath, commandStr, "utf8");
    }
    const req = {
        command: commandStr,
        args: args ?? [],
        env: options.env ?? {},
        shell: options.shell ?? true,
        cwd: options.cwd ?? undefined,
        stdio: typeof options.io === "string" ? options.io : options.io ? "inherit" : "pipe",
        returnChild: options.returnChild
    };
    const execRes = await new Promise((resolvePromise, rejectPromise)=>{
        const env = req.env;
        const cwd = req.cwd != null ? (0, _path().resolve)(req.cwd) : undefined;
        if (tmpScriptPath) {
            commandStr = `bash "${tmpScriptPath}"`;
        }
        const child = (0, _child_process().spawn)(commandStr, req.args, {
            env,
            shell: req.shell,
            cwd,
            stdio: req.stdio,
            detached: options.detached
        });
        if (req.returnChild) {
            return resolvePromise(child);
        }
        let stdout = "";
        const stderr = "";
        let exitCode = null;
        let signal = null;
        let killTimer;
        let alreadyFinished = false;
        const finish = ()=>{
            if (alreadyFinished) {
                throw new Error("Already finished. This should not happen");
            }
            alreadyFinished = true;
            clearTimeout(killTimer);
            const res = {
                stdout,
                stderr,
                command: commandStr,
                exitCode: exitCode ?? 0,
                signal: signal ?? undefined
            };
            if (exitCode !== 0 && options.throw) {
                return rejectPromise(res);
            }
            resolvePromise(res);
        };
        child.stdout?.on("data", (data)=>{
            stdout += data;
            if (options.verbose) {
                process.stdout.write(data);
            }
        });
        child.stderr?.on("data", (data)=>{
            stdout += data;
            if (options.verbose) {
                process.stderr.write(data);
            }
        });
        child.on("exit", (_exitCode, _signal)=>{
            exitCode = _exitCode;
            signal = _signal;
            finish();
        });
    });
    execRes.command = req.command;
    return execRes;
}
