"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const os_1 = __importDefault(require("os"));
const path_1 = __importDefault(require("path"));
const lodash_1 = __importDefault(require("lodash"));
const p_queue_1 = __importDefault(require("p-queue"));
const cli_commands_1 = require("./lib/cli-commands");
const config_1 = require("./lib/config");
const constants_1 = require("./lib/constants");
const plugin_api_1 = require("./lib/plugin-api");
const static_1 = require("./lib/report-builder/static");
const server_utils_1 = require("./lib/server-utils");
const sqlite_client_1 = require("./lib/sqlite-client");
const create_workers_1 = require("./lib/workers/create-workers");
const image_store_1 = require("./lib/image-store");
const cache_1 = require("./lib/cache");
const images_info_saver_1 = require("./lib/images-info-saver");
const testplane_1 = require("./lib/test-adapter/testplane");
exports.default = (testplane, opts) => {
    if (testplane.isWorker()) {
        return;
    }
    const config = (0, config_1.parseConfig)(opts);
    if (!config.enabled) {
        return;
    }
    const htmlReporter = plugin_api_1.HtmlReporter.create(config, { toolName: constants_1.ToolName.Testplane });
    testplane.htmlReporter = htmlReporter;
    let isCliCommandLaunched = false;
    let handlingTestResults;
    let staticReportBuilder;
    const withMiddleware = (fn) => {
        return (...args) => {
            // If any CLI command was launched, e.g. merge-reports, we need to interrupt regular flow
            if (isCliCommandLaunched) {
                return;
            }
            return fn.call(undefined, ...args);
        };
    };
    testplane.on(testplane.events.CLI, (commander) => {
        lodash_1.default.values(cli_commands_1.cliCommands).forEach((command) => {
            // eslint-disable-next-line @typescript-eslint/no-var-requires
            require(path_1.default.resolve(__dirname, 'lib/cli-commands', command))(commander, config, testplane);
            commander.prependListener(`command:${command}`, () => {
                isCliCommandLaunched = true;
            });
        });
    });
    testplane.on(testplane.events.INIT, withMiddleware(async () => {
        const dbClient = await sqlite_client_1.SqliteClient.create({ htmlReporter, reportPath: config.path });
        const imageStore = new image_store_1.SqliteImageStore(dbClient);
        const expectedPathsCache = new cache_1.Cache(server_utils_1.getExpectedCacheKey);
        const imagesInfoSaver = new images_info_saver_1.ImagesInfoSaver({
            imageFileSaver: htmlReporter.imagesSaver,
            expectedPathsCache,
            imageStore,
            reportPath: htmlReporter.config.path
        });
        staticReportBuilder = static_1.StaticReportBuilder.create(htmlReporter, config, { dbClient, imagesInfoSaver });
        handlingTestResults = Promise.all([
            staticReportBuilder.saveStaticFiles(),
            handleTestResults(testplane, staticReportBuilder)
        ]).then(async () => {
            await staticReportBuilder.finalize();
        }).then(async () => {
            await htmlReporter.emitAsync(htmlReporter.events.REPORT_SAVED, { reportPath: config.path });
        });
        htmlReporter.emit(htmlReporter.events.DATABASE_CREATED, dbClient.getRawConnection());
    }));
    testplane.on(testplane.events.RUNNER_START, withMiddleware((runner) => {
        staticReportBuilder.registerWorkers((0, create_workers_1.createWorkers)(runner));
    }));
    testplane.on(testplane.events.RUNNER_END, withMiddleware(async () => {
        try {
            await handlingTestResults;
            (0, server_utils_1.logPathToHtmlReport)(config);
        }
        catch (e) {
            (0, server_utils_1.logError)(e);
        }
    }));
};
async function handleTestResults(testplane, reportBuilder) {
    return new Promise((resolve, reject) => {
        const queue = new p_queue_1.default({ concurrency: os_1.default.cpus().length });
        const promises = [];
        [
            { eventName: testplane.events.TEST_PASS },
            { eventName: testplane.events.RETRY },
            { eventName: testplane.events.TEST_FAIL },
            { eventName: testplane.events.TEST_PENDING }
        ].forEach(({ eventName }) => {
            testplane.on(eventName, (testResult) => {
                promises.push(queue.add(async () => {
                    const formattedResult = (0, server_utils_1.formatTestResult)(testResult, (0, testplane_1.getStatus)(eventName, testplane.events, testResult));
                    await reportBuilder.addTestResult(formattedResult);
                }).catch(reject));
            });
        });
        testplane.on(testplane.events.RUNNER_END, () => {
            return Promise.all(promises).then(() => resolve(), reject);
        });
    });
}
//# sourceMappingURL=testplane.js.map