"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.start = void 0;
const path_1 = __importDefault(require("path"));
const express_1 = __importDefault(require("express"));
const signal_exit_1 = require("signal-exit");
const bluebird_1 = __importDefault(require("bluebird"));
const body_parser_1 = __importDefault(require("body-parser"));
const http_codes_1 = require("http-codes");
const app_1 = require("./app");
const constants_1 = require("./constants");
const server_utils_1 = require("../server-utils");
const common_utils_1 = require("../common-utils");
const plugins_1 = require("./routes/plugins");
const start = async ({ paths, testplane, guiApi, configs }) => {
    const { options, pluginConfig } = configs;
    const app = app_1.App.create(paths, testplane, configs);
    const server = (0, express_1.default)();
    server.use(body_parser_1.default.json({ limit: constants_1.MAX_REQUEST_SIZE }));
    await guiApi.initServer(server);
    // allow plugins to precede default server routes
    server.use((0, plugins_1.initPluginsRoutes)(express_1.default.Router(), pluginConfig));
    server.use(express_1.default.static(path_1.default.join(__dirname, '../static'), { index: 'gui.html' }));
    server.use(express_1.default.static(path_1.default.join(process.cwd(), pluginConfig.path)));
    server.get('/', (_req, res) => res.sendFile(path_1.default.join(__dirname, '../static', 'gui.html')));
    server.get('/events', (_req, res) => {
        res.writeHead(http_codes_1.OK, { 'Content-Type': 'text/event-stream' });
        app.addClient(res);
    });
    server.set('json replacer', (_key, val) => {
        return typeof val === 'function' ? val.toString() : val;
    });
    server.get('/init', async (_req, res) => {
        try {
            await (0, server_utils_1.initializeCustomGui)(testplane, pluginConfig);
            res.json(app.data);
        }
        catch (e) {
            const error = e;
            if (!app.data) {
                throw new Error(`Failed to initialize custom GUI ${error.message}`);
            }
            res.json({
                ...app.data,
                customGuiError: {
                    response: {
                        status: http_codes_1.INTERNAL_SERVER_ERROR,
                        data: `Error while trying to initialize custom GUI: ${error.message}`
                    }
                }
            });
        }
    });
    server.post('/run', (req, res) => {
        try {
            // do not wait for completion so that response does not hang and browser does not restart it by timeout
            app.run(req.body);
            res.sendStatus(http_codes_1.OK);
        }
        catch (e) {
            res.status(http_codes_1.INTERNAL_SERVER_ERROR).send(`Error while trying to run tests: ${e.message}`);
        }
    });
    server.post('/run-custom-gui-action', async ({ body: payload }, res) => {
        try {
            await (0, server_utils_1.runCustomGuiAction)(testplane, pluginConfig, payload);
            res.sendStatus(http_codes_1.OK);
        }
        catch (e) {
            res.status(http_codes_1.INTERNAL_SERVER_ERROR).send(`Error while running custom gui action: ${e.message}`);
        }
    });
    server.post('/reference-data-to-update', (req, res) => {
        try {
            const data = app.getTestsDataToUpdateRefs(req.body);
            res.json(data);
        }
        catch (error) {
            res.status(http_codes_1.INTERNAL_SERVER_ERROR).send({ error: error.message });
        }
    });
    server.post('/update-reference', (req, res) => {
        app.updateReferenceImage(req.body)
            .then((updatedTests) => res.json(updatedTests))
            .catch(({ message }) => res.status(http_codes_1.INTERNAL_SERVER_ERROR).send({ error: message }));
    });
    server.post('/undo-accept-images', (req, res) => {
        app.undoAcceptImages(req.body)
            .then((updated) => res.json(updated))
            .catch(({ message }) => res.status(http_codes_1.INTERNAL_SERVER_ERROR).send({ error: message }));
    });
    server.post('/get-find-equal-diffs-data', (req, res) => {
        try {
            const data = app.getImageDataToFindEqualDiffs(req.body);
            res.json(data);
        }
        catch (e) {
            res.status(http_codes_1.INTERNAL_SERVER_ERROR).send({ error: e.message });
        }
    });
    server.post('/find-equal-diffs', async (req, res) => {
        try {
            const result = await app.findEqualDiffs(req.body);
            res.json(result);
        }
        catch (e) {
            res.status(http_codes_1.INTERNAL_SERVER_ERROR).send({ error: e.message });
        }
    });
    (0, signal_exit_1.onExit)(() => {
        app.finalize();
        common_utils_1.logger.log('server shutting down');
    });
    server.post('/stop', (_req, res) => {
        try {
            // pass 0 to prevent terminating testplane process
            testplane.halt(new Error('Tests were stopped by the user'), 0);
            res.sendStatus(http_codes_1.OK);
        }
        catch (e) {
            res.status(http_codes_1.INTERNAL_SERVER_ERROR).send(`Error while stopping tests: ${e.message}`);
        }
    });
    await app.initialize();
    const { port, hostname } = options;
    await bluebird_1.default.fromCallback((callback) => {
        const httpServer = server.listen(port, hostname, callback);
        httpServer.keepAliveTimeout = constants_1.KEEP_ALIVE_TIMEOUT;
        httpServer.headersTimeout = constants_1.HEADERS_TIMEOUT;
    });
    const data = { url: `http://${hostname}:${port}` };
    await guiApi.serverReady(data);
    return data;
};
exports.start = start;
//# sourceMappingURL=server.js.map