const spawn = require('child_process').spawn;
const os = require("os");
const fs = require("fs");
const path = require("path");

let grep;
try {
    const failedTests = fs.readFileSync(".failed-tests", "utf8");
    grep = failedTests
        .split(/\r?\n/g)
        .map(test => test.trim())
        .filter(test => test.length > 0)
        .map(escapeRegExp);
}
catch (e) {
    grep = [];
}

let args = [];
let waitForGrepValue = false;
let grepIndex = -1;
process.argv.slice(2).forEach((arg, index) => {
    const [flag, value] = arg.split('=');
    if (flag === "g" || flag === "grep") {
        grepIndex = index - 1;
        waitForGrepValue = arg !== flag;
        if (!waitForGrepValue) grep.push(value.replace(/^"|"$/g, ""));
        return;
    }
    if (waitForGrepValue) {
        grep.push(arg.replace(/^"|"$/g, ""));
        waitForGrepValue = false;
        return;
    }
    args.push(arg);
});

let mocha = "./node_modules/mocha/bin/mocha";
let grepOption;
let grepOptionValue;
let grepFile;
if (grep.length) {
    grepOption = "--grep";
    grepOptionValue = grep.join("|");
    if (grepOptionValue.length > 20) {
        grepFile = path.resolve(os.tmpdir(), ".failed-tests.opts");
        fs.writeFileSync(grepFile, `--grep ${grepOptionValue}`, "utf8");
        grepOption = "--opts";
        grepOptionValue = grepFile;
        mocha = "./node_modules/mocha/bin/_mocha";
    }
}

if (grepOption) {
    if (grepIndex >= 0) {
        args.splice(grepIndex, 0, grepOption, grepOptionValue);
    }
    else {
        args.push(grepOption, grepOptionValue);
    }
}

args.unshift(path.resolve(mocha));

console.log(args.join(" "));
const proc = spawn(process.execPath, args, {
    stdio: 'inherit'
});
proc.on('exit', (code, signal) => {
    process.on('exit', () => {
        if (grepFile) {
            try {
                fs.unlinkSync(grepFile);
            }
            catch (e) {
                if (e.code !== "ENOENT") throw e;
            }
        }

        if (signal) {
            process.kill(process.pid, signal);
        } else {
            process.exit(code);
        }
    });
});

process.on('SIGINT', () => {
    proc.kill('SIGINT');
    proc.kill('SIGTERM');
});

function escapeRegExp(pattern) {
    return pattern
        .replace(/[^-\w\d\s]/g, match => "\\" + match)
        .replace(/\s/g, "\\s");
}