"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
const childProcess = require("child_process");
const fs_1 = require("fs");
const path_1 = require("path");
const readline_1 = require("readline");
const enums_1 = require("./enums");
exports.killAllProcessAndRelatedCommand = args => {
    if (!args || args.length === 0)
        return;
    args = Array.isArray(args) ? args : [args];
    const greps = new Array();
    args.forEach(e => greps.push(`| grep -ie "${e}"`));
    greps.push("| awk '{print $2}'", "| xargs kill -9");
    const output = childProcess.execSync("/bin/ps aux", ...greps, {
        shell: true,
        encoding: "UTF8",
        timeout: 10000
    });
};
exports.isProcessAlive = (arg) => {
    const result = childProcess.spawnSync(`/bin/ps aux`, [`| grep -i ${arg} | grep -v grep`], {
        shell: true
    });
    const test = !result.output.every(output => !output || output.length === 0)
        && result.output
            .filter(output => output && output.length > 0)
            .every(f => {
            return new RegExp(arg.toString().trim()).test(f + "");
        });
    console.log(`Is process ${arg} alive: ${test}`);
    return test;
};
function executeCommand(args, cwd = process.cwd(), timeout = 720000) {
    const [baseCommand, ...commands] = args.trim().split(" ").filter(c => c && c.trim() !== "");
    const output = childProcess.spawnSync(baseCommand, commands, {
        cwd: cwd,
        shell: true,
        encoding: "UTF8",
        timeout: timeout
    });
    return output && output.stdout && output.stdout.toString();
}
exports.executeCommand = executeCommand;
function waitForOutput(process, matcher, errorMatcher, timeout) {
    return new Promise(function (resolve, reject) {
        const abortWatch = setTimeout(function () {
            process.kill();
            console.log("Timeout expired, output not detected for: " + matcher);
            resolve(false);
        }, timeout);
        process.stdout.on("data", function (data) {
            let line = "" + data;
            console.log(line);
            if (errorMatcher.test(line)) {
                clearTimeout(abortWatch);
                resolve(false);
            }
            if (matcher.test(line)) {
                clearTimeout(abortWatch);
                resolve(true);
            }
        });
    });
}
exports.waitForOutput = waitForOutput;
function isWin() {
    return /^win/.test(process.platform);
}
exports.isWin = isWin;
function isMac() {
    return /^darwin/.test(process.platform);
}
exports.isMac = isMac;
function killProcessByName(name) {
    if (!isWin()) {
        executeCommand("killall " + name);
    }
    else {
        childProcess.execSync('taskkill /IM ' + name + ' /T /F');
    }
}
exports.killProcessByName = killProcessByName;
function killPid(pid, signal = "SIGINT") {
    if (!isWin()) {
        try {
            const result = process.kill(pid, signal);
            const killCommandLog = executeCommand(`kill -9 ${pid}`);
            logWarn(killCommandLog);
        }
        catch (error) { }
    }
    else {
        childProcess.execSync('taskkill /PID ' + pid + ' /T /F || true');
    }
}
exports.killPid = killPid;
function tailFileUntil(file, condition, index = 0) {
    const log = fs_1.readFileSync(file, "UTF8");
    const logTail = log.substr(index, log.length - 1);
    let result = false;
    if (logTail.includes(condition)) {
        result = true;
    }
    index = log.length - 1;
    return {
        result: result,
        index: index,
    };
}
exports.tailFileUntil = tailFileUntil;
exports.sortDescByApiLevelPredicate = (a, b) => { return (+a.apiLevel !== NaN && +b.apiLevel) ? +b.apiLevel - +a.apiLevel : -1; };
exports.sortAscByApiLevelPredicate = (a, b) => { return (+a.apiLevel !== NaN && +b.apiLevel) ? +a.apiLevel - +b.apiLevel : -1; };
exports.filterPredicate = (searchQuery, device) => (!searchQuery || searchQuery === null || Object.getOwnPropertyNames(searchQuery).length === 0)
    ? true : Object.getOwnPropertyNames(searchQuery)
    .every(prop => searchQuery[prop] && typeof searchQuery[prop] !== 'object' ? new RegExp(searchQuery[prop], "ig").test(device[prop]) : true);
exports.filterAndroidPredicate = (searchQuery, device) => (!searchQuery || searchQuery === null || Object.getOwnPropertyNames(searchQuery).length === 0)
    ? true : Object.getOwnPropertyNames(searchQuery)
    .every(prop => {
    if (searchQuery[prop]
        && (prop === "apiLevel" || prop === "releaseVersion")) {
        return new RegExp(searchQuery[prop], "ig").test(device[prop]) || new RegExp(searchQuery[prop], "ig").test(device["releaseVersion"]);
    }
    return searchQuery[prop] && typeof searchQuery[prop] !== 'object' ? new RegExp(searchQuery[prop], "ig").test(device[prop]) : true;
});
function filter(devices, searchQuery) {
    if (searchQuery.type === enums_1.DeviceType.EMULATOR || searchQuery.Platform === enums_1.Platform.ANDROID) {
        return devices.filter((device) => exports.filterAndroidPredicate(searchQuery, device));
    }
    return devices.filter((device) => exports.filterPredicate(searchQuery, device));
}
exports.filter = filter;
function searchFiles(folder, words, recursive = true, files = new Array()) {
    const rootFiles = getFiles(folder);
    const regex = createRegexPattern(words);
    rootFiles.filter(f => {
        const fileFullName = path_1.resolve(folder, f);
        regex.lastIndex = 0;
        let m = regex.test(f);
        if (m) {
            files.push(fileFullName);
        }
        else if (isDirectory(fileFullName) && recursive) {
            searchFiles(fileFullName, words, recursive, files);
        }
    });
    return files;
}
exports.searchFiles = searchFiles;
function isDirectory(fullName) {
    try {
        if (fs_1.statSync(fullName).isDirectory()) {
            return true;
        }
    }
    catch (e) {
        console.log(e.message);
        return false;
    }
    return false;
}
exports.isDirectory = isDirectory;
function getFiles(folder) {
    let files = new Array();
    fs_1.readdirSync(path_1.resolve(folder)).forEach(file => {
        files.push(file);
    });
    return files;
}
exports.getFiles = getFiles;
/// ^nativ\w*(.+).gz$ native*.gz
/// \w*nativ\w*(.+)\.gz$ is like *native*.gz
/// \w*nativ\w*(.+)\.gz\w*(.+)$ is like *native*.gz*
function createRegexPattern(text) {
    let finalRex = "";
    text.split(",").forEach(word => {
        word = word.trim();
        let searchRegex = word;
        if (word !== "" && word !== " ") {
            searchRegex = searchRegex.replace(".", "\\.");
            searchRegex = searchRegex.replace("*", "\\w*(.+)?");
            if (!word.startsWith("*")) {
                searchRegex = "^" + searchRegex;
            }
            if (!word.endsWith("*")) {
                searchRegex += "$";
            }
            if (!finalRex.includes(searchRegex)) {
                finalRex += searchRegex + "|";
            }
        }
    });
    finalRex = finalRex.substring(0, finalRex.length - 1);
    const regex = new RegExp(finalRex, "gi");
    return regex;
}
exports.createRegexPattern = createRegexPattern;
function getAllFileNames(folder) {
    let files = new Array();
    fs_1.readdirSync(path_1.resolve(folder)).forEach(file => {
        files.push(file);
    });
    return files;
}
exports.getAllFileNames = getAllFileNames;
function attachToProcess(processToWatchLog, matcher, timeOut) {
    return __awaiter(this, void 0, void 0, function* () {
        return new Promise((resolve, reject) => {
            waitForResult(processToWatchLog, matcher, timeOut).then((result) => {
                processToWatchLog.kill("SIGINT");
                resolve();
            });
        });
    });
}
exports.attachToProcess = attachToProcess;
function waitForResult(childProcess, matcher, timeout) {
    return __awaiter(this, void 0, void 0, function* () {
        let log = "";
        const reader = readline_1.createInterface({ input: childProcess.stdout });
        return new Promise((resolve, reject) => {
            const abortWatch = setTimeout(function () {
                childProcess.kill();
            }, timeout);
            reader.on("line", line => {
                console.log(line.toString());
                log += line.toString();
                if (matcher.test(line)) {
                    clearTimeout(abortWatch);
                    resolve(log);
                }
            });
        });
    });
}
exports.waitForResult = waitForResult;
exports.wait = miliseconds => {
    const startTime = Date.now();
    while (Date.now() - startTime <= miliseconds) { }
    return true;
};
exports.getRegexResultsAsArray = (regex, str) => {
    let m;
    const result = [];
    while ((m = regex.exec(str)) !== null) {
        if (m.index === regex.lastIndex) {
            regex.lastIndex++;
        }
        m.forEach(element => {
            if (result.indexOf(element) < 0) {
                result.push(element);
            }
        });
    }
    return result;
};
exports.copyIDeviceQuery = (source, target = {}) => {
    Object.getOwnPropertyNames(source)
        .forEach(prop => {
        const p = prop.startsWith("_") ? prop.substring(1) : prop;
        if (source[p]) {
            target[p] = source[p];
        }
    });
    return target;
};
function logInfo(info, obj = undefined) {
    if (obj) {
        info += " " + JSON.stringify(obj);
    }
    console.log(`${ConsoleColor.FgCyan}%s${ConsoleColor.Reset}`, info);
}
exports.logInfo = logInfo;
function logWarn(info, obj = undefined) {
    if (obj) {
        info += " " + JSON.stringify(obj);
    }
    console.log(`${ConsoleColor.BgYellow}${ConsoleColor.FgBlack}%s${ConsoleColor.Reset}`, info);
}
exports.logWarn = logWarn;
function logError(info, obj = undefined) {
    if (obj) {
        info += " " + JSON.stringify(obj);
    }
    console.log(`${ConsoleColor.BgRed}%s${ConsoleColor.Reset}`, info);
}
exports.logError = logError;
var ConsoleColor;
(function (ConsoleColor) {
    ConsoleColor["Reset"] = "\u001B[0m";
    ConsoleColor["Bright"] = "\u001B[1m";
    ConsoleColor["Dim"] = "\u001B[2m";
    ConsoleColor["Underscore"] = "\u001B[4m";
    ConsoleColor["Blink"] = "\u001B[5m";
    ConsoleColor["Reverse"] = "\u001B[7m";
    ConsoleColor["Hidden"] = "\u001B[8m";
    ConsoleColor["FgBlack"] = "\u001B[30m";
    ConsoleColor["FgRed"] = "\u001B[31m";
    ConsoleColor["FgGreen"] = "\u001B[32m";
    ConsoleColor["FgYellow"] = "\u001B[33m";
    ConsoleColor["FgBlue"] = "\u001B[34m";
    ConsoleColor["FgMagenta"] = "\u001B[35m";
    ConsoleColor["FgCyan"] = "\u001B[36m";
    ConsoleColor["FgWhite"] = "\u001B[37m";
    ConsoleColor["BgBlack"] = "\u001B[40m";
    ConsoleColor["BgRed"] = "\u001B[41m";
    ConsoleColor["BgGreen"] = "\u001B[42m";
    ConsoleColor["BgYellow"] = "\u001B[43m";
    ConsoleColor["BgBlue"] = "\u001B[44m";
    ConsoleColor["BgMagenta"] = "\u001B[45m";
    ConsoleColor["BgCyan"] = "\u001B[46m";
    ConsoleColor["BgWhite"] = "\u001B[47m";
})(ConsoleColor || (ConsoleColor = {}));
//# sourceMappingURL=utils.js.map