var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    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) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
(function (factory) {
    if (typeof module === "object" && typeof module.exports === "object") {
        var v = factory(require, exports);
        if (v !== undefined) module.exports = v;
    }
    else if (typeof define === "function" && define.amd) {
        define(["require", "exports", "colors/safe", "./sandbox"], factory);
    }
})(function (require, exports) {
    "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    const colors = require("colors/safe");
    const sandbox_1 = require("./sandbox");
    class TestRunner {
        constructor() {
            this.tests = [];
            this.executed = [];
        }
        static get instance() {
            if (!TestRunner._instance) {
                TestRunner._instance = new TestRunner();
            }
            return TestRunner._instance;
        }
        printAll() {
            // var results = this.executed.sort((a,b)=>{
            //     return a.testClass.category.localeCompare(b.testClass.category);
            // });
            // var results = results.sort((a,b)=>{
            //     return a.description.localeCompare(b.description);
            // });
            let errors = 0;
            const errorLogs = [];
            colors.setTheme({
                error: ["red", "bold"]
            });
            for (const result of this.executed) {
                if (result.error) {
                    errorLogs.push(`${result.category} > ${result.description} failed ${result.error.message}.`);
                    errorLogs.push(result.error);
                    errors++;
                }
                else {
                    console.log(`${result.category} > ${result.description} succeeded.`);
                }
                if (result.logText) {
                    console.log(`\t\t${result.logText}`);
                }
            }
            if (errors) {
                for (const iterator of errorLogs) {
                    console.error(colors.red(iterator));
                }
                throw new Error(`${errors} of ${this.executed.length} tests have failed.`);
            }
            else {
                console.log(`${this.executed.length} tests ran successfully.`);
            }
        }
        // public runTest(f: any, target: any): Promise<any> {
        //     return new Promise((resolve, reject) => {
        //         // try {
        //             const t: any = f.apply(target);
        //             if (t && t.then) {
        //                 t.then((v) => {
        //                     resolve(v);
        //                 });
        //                 t.catch((e) => {
        //                     reject(e);
        //                 });
        //                 return;
        //             }
        //             resolve();
        //         // } catch (ex) {
        //         //     reject(ex);
        //         // }
        //     });
        // }
        run(filter) {
            return __awaiter(this, void 0, void 0, function* () {
                if (filter) {
                    let r = null;
                    if (filter.startsWith("/")) {
                        const index = filter.lastIndexOf("/");
                        const options = filter.substr(index + 1);
                        filter = filter.substr(0, index);
                        const exp = filter.substr(1);
                        r = new RegExp(exp, options);
                        this.tests = this.tests.filter((x) => r.test(x.path));
                    }
                    else {
                        const categories = filter.split(",").map((x) => x.trim().toLowerCase().split("."));
                        this.tests = this.tests.filter((x) => {
                            const lc = x.category.toLowerCase();
                            const ln = x.name.toLowerCase();
                            const b = categories.find((c) => c[0] === lc && ((!c[1]) || (c[1] === ln)));
                            return b;
                        });
                    }
                }
                return this._run();
            });
        }
        _run() {
            return __awaiter(this, void 0, void 0, function* () {
                const promises = this.tests.map((peek) => __awaiter(this, void 0, void 0, function* () {
                    this.executed.push(peek);
                    try {
                        yield sandbox_1.default(peek);
                    }
                    catch (e) {
                        peek.error = peek.error || "";
                        peek.error += (e.stack ? (e.toString() + "\r\n" + e.stack) : e);
                    }
                }));
                yield Promise.all(promises);
                this.printAll();
                // const peek: TestMethod = this.tests.shift();
                // this.executed.push(peek);
                // const test: TestItem = new (peek.testClass as {new ()})();
                // try {
                //     await test.init();
                //     // tslint:disable-next-line:ban-types
                //     const fx: Function = test[peek.name];
                //     await this.runTest(fx, test);
                // } catch (e) {
                //     peek.error = e;
                // } finally {
                //     peek.logText = test.logText;
                //     try {
                //         await test.dispose();
                //     } catch (er) {
                //         peek.error = er;
                //     }
                // }
                // await this._run();
            });
        }
    }
    exports.default = TestRunner;
});
//# sourceMappingURL=TestRunner.js.map