"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ProcessPipePromise = void 0;
exports.flattenArgList = flattenArgList;
exports.createKit_Command = createKit_Command;
const tslib_1 = require("tslib");
const os = tslib_1.__importStar(require("os"));
const child_process_1 = require("child_process");
const which = tslib_1.__importStar(require("which"));
const director_1 = require("../core/director");
function flattenArgList(args) {
    let ans = [];
    for (let x of args) {
        if (x === undefined || x === null) {
            continue;
        }
        else if (Array.isArray(x)) {
            ans = [...ans, ...flattenArgList(x)];
        }
        else {
            ans.push(x + "");
        }
    }
    return ans;
}
const isWin32 = os.platform() === "win32";
function startPipeline(commands, options) {
    let processes = [];
    if (options.reporter) {
        options.reporter.actions(commands, "command");
    }
    for (let j = commands.length - 1; j >= 0; j--) {
        const [cmd, ...args] = commands[j];
        const realCommand = which.sync(cmd);
        const shellOption = isWin32 && /\.(?:bat|cmd)$/i.test(realCommand) ? { shell: true } : {};
        const p = (0, child_process_1.spawn)(realCommand, args, {
            cwd: options.cwd,
            env: options.env,
            stdio: options.interactive ? "inherit" : "pipe",
            ...shellOption,
        });
        if (options.reporter && !options.interactive) {
            p.stderr.on("data", (data) => options.reporter.redirectStderr(data));
            if (j < commands.length - 1) {
                const next = processes[j + 1];
                p.stdout.on("data", (data) => next.stdin.write(data));
                p.on("close", () => next.stdin.end());
            }
            else {
                p.stdout.on("data", (data) => options.reporter.redirectStdout(data));
            }
        }
        processes[j] = p;
    }
    return new Promise(function (resolve, reject) {
        for (let j = 0; j < processes.length; j++) {
            processes[j].on("exit", function (code, signal) {
                if (signal)
                    reject({ signal });
                else if (code)
                    reject({ code });
                else if (j === processes.length - 1)
                    resolve({ code: 0 });
            });
        }
    });
}
class ProcessPipePromise {
    constructor(options) {
        this.pendingCommands = [];
        this.p = (0, director_1.SleepPromise)(0).then(() => startPipeline(this.pendingCommands, options));
    }
    pipe(...commandLine) {
        this.pendingCommands.push(flattenArgList(commandLine));
        return this;
    }
    then(onfulfilled, onrejected) {
        return this.p.then(onfulfilled, onrejected);
    }
}
exports.ProcessPipePromise = ProcessPipePromise;
function createKit_Command(ce) {
    function startCommand(commandLine, options) {
        return new ProcessPipePromise(options).pipe(...commandLine);
    }
    function runCommand(...commandLine) {
        return startCommand(commandLine, { cwd: ce.cd, env: ce.env, reporter: ce.reporter });
    }
    function runInteractive(...commandLine) {
        return startCommand(commandLine, {
            cwd: ce.cd,
            env: ce.env,
            reporter: ce.reporter,
            interactive: true,
        });
    }
    return {
        run: runCommand,
        interactive: runInteractive,
    };
}
