"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.makeExecuteScript = void 0;
const driver_1 = require("@applitools/driver");
const spec = __importStar(require("@applitools/spec-driver-webdriver"));
const utils = __importStar(require("@applitools/utils"));
function makeExecuteScript({ req, core }) {
    return async function executeScript({ session, request, response, logger, }) {
        var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r;
        var _s, _t;
        const requestBody = await utils.streams.toJSON(request);
        if ((_a = requestBody.script) === null || _a === void 0 ? void 0 : _a.startsWith('applitools:')) {
            logger.log(`Custom script execution was intercepted with body:`, requestBody);
            const [options] = (_b = requestBody.args) !== null && _b !== void 0 ? _b : [];
            if (requestBody.script === 'applitools:startTest') {
                if ((_c = session.tests) === null || _c === void 0 ? void 0 : _c.current) {
                    await session.tests.current.abort({ settings: { testMetadata: session.metadata }, logger });
                    (_d = (_s = session.tests).ended) !== null && _d !== void 0 ? _d : (_s.ended = []);
                    session.tests.ended.push(session.tests.current);
                    session.tests.current = undefined;
                }
                const driver = await (0, driver_1.makeDriver)({
                    driver: {
                        sessionId: session.sessionId,
                        serverUrl: session.ecServerUrl,
                        capabilities: session.capabilities,
                        proxy: session.proxy,
                    },
                    spec,
                    logger,
                });
                const environment = await driver.getEnvironment();
                (_e = session.tests) !== null && _e !== void 0 ? _e : (session.tests = {});
                session.tests.current = await core.openFunctionalSession({
                    settings: {
                        eyesServerUrl: session.credentials.eyesServerUrl,
                        apiKey: session.credentials.apiKey,
                        proxy: session.proxy,
                        appName: (_g = (_f = options === null || options === void 0 ? void 0 : options.appName) !== null && _f !== void 0 ? _f : session.options.appName) !== null && _g !== void 0 ? _g : ((await driver.getTitle()) || 'default'),
                        testName: (_h = options === null || options === void 0 ? void 0 : options.testName) !== null && _h !== void 0 ? _h : session.options.testName,
                        batch: { ...session.options.batch, ...options === null || options === void 0 ? void 0 : options.batch },
                        environment: {
                            hostingApp: `${(_j = environment.browserName) !== null && _j !== void 0 ? _j : ''} ${(_k = environment.browserVersion) !== null && _k !== void 0 ? _k : ''}`.trim(),
                            os: `${(_l = environment.platformName) !== null && _l !== void 0 ? _l : ''} ${(_m = environment.platformVersion) !== null && _m !== void 0 ? _m : ''}`.trim(),
                            deviceName: environment.deviceName,
                            viewportSize: await driver.getViewportSize(),
                            ecSessionId: session.sessionId,
                        },
                    },
                    logger,
                });
                response.writeHead(200, { 'content-type': 'application/json' }).end(JSON.stringify({ value: null }));
                return;
            }
            else if (requestBody.script === 'applitools:endTest') {
                if ((_o = session.tests) === null || _o === void 0 ? void 0 : _o.current) {
                    await session.tests.current.close({
                        settings: { status: options === null || options === void 0 ? void 0 : options.status, testMetadata: session.metadata },
                        logger,
                    });
                    (_p = (_t = session.tests).ended) !== null && _p !== void 0 ? _p : (_t.ended = []);
                    session.tests.ended.push(session.tests.current);
                    session.tests.current = undefined;
                }
                response.writeHead(200, { 'content-type': 'application/json' }).end(JSON.stringify({ value: null }));
                return;
            }
            else if (requestBody.script === 'applitools:getResults') {
                if ((_q = session.tests) === null || _q === void 0 ? void 0 : _q.ended) {
                    const results = await Promise.all(session.tests.ended.map(test => test.getResults({ logger })));
                    response.writeHead(200, { 'content-type': 'application/json' }).end(JSON.stringify({ value: results.flat() }));
                }
                else {
                    response.writeHead(200, { 'content-type': 'application/json' }).end(JSON.stringify({ value: [] }));
                }
                return;
            }
            else if (requestBody.script === 'applitools:metadata') {
                logger.log('Session metadata requested, returning', session.metadata);
                response
                    .writeHead(200, { 'content-type': 'application/json' })
                    .end(JSON.stringify({ value: (_r = session.metadata) !== null && _r !== void 0 ? _r : [] }));
                session.metadata = [];
                return;
            }
        }
        await req(request.url, { baseUrl: session.ecServerUrl, body: requestBody, io: { request, response }, logger });
    };
}
exports.makeExecuteScript = makeExecuteScript;
