"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (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;
};
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());
    });
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.executeTest = exports.startDashboard = exports.checkVersion = void 0;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const serve_handler_1 = __importDefault(require("serve-handler"));
const http = __importStar(require("http"));
const child_process = __importStar(require("child_process"));
const logger_1 = __importDefault(require("./logger"));
const package_json_1 = __importDefault(require("../package.json"));
const https = __importStar(require("https"));
const semver = __importStar(require("semver"));
function get(url) {
    return new Promise((resolve, reject) => {
        const request = https.get(url, (res) => {
            if (res.statusCode < 200 || res.statusCode >= 299) {
                reject(res.statusMessage);
                return;
            }
            res.setEncoding('utf8');
            let body = '';
            res.on('data', (data) => {
                body += data;
            });
            res.on('end', () => {
                const inner = body.trim().replace(/^"/, '').replace(/"$/, '');
                if (!semver.valid(inner)) {
                    reject(`Invalid semver ${body}`);
                }
                else {
                    resolve(semver.clean(inner));
                }
            });
        });
        request.on('error', (err) => reject(err));
    });
}
const checkVersion = () => __awaiter(void 0, void 0, void 0, function* () {
    const localVersion = package_json_1.default.version;
    let externalVersion;
    try {
        externalVersion = yield get(`https://app.reflow.io/.package.version`);
    }
    catch (e) {
        console.error(`Failed to load API package version at "https://app.reflow.io/.package.version": ${e}`);
    }
    const diff = semver.diff(localVersion, externalVersion);
    if (!semver.gte(localVersion, externalVersion) && diff === 'major') {
        console.error(`An update to ${externalVersion} is available. This version of reflowio (${localVersion}) is outdated by a major version, which implies it will not run without fatal errors.`);
        process.exit(1);
    }
    if (!semver.gte(localVersion, externalVersion)) {
        console.error(`An update to ${externalVersion} is available. This version of reflowio (${localVersion}) is outdated.`);
    }
    logger_1.default.verbose(`Local Version = ${localVersion}`);
    logger_1.default.verbose(`API Version = ${externalVersion}`);
});
exports.checkVersion = checkVersion;
const startDashboard = () => __awaiter(void 0, void 0, void 0, function* () {
    yield exports.checkVersion();
    const dashboardPath = checkDirectory(__dirname, '..', 'dashboard') || checkDirectory(__dirname, '..', '..', 'webapp', 'build');
    if (!dashboardPath) {
        throw new Error(`cannot find dashboard path at ${path.resolve(__dirname, '..', 'dashboard')}`);
    }
    const browserPath = checkDirectory(__dirname, '..', 'browser') || checkDirectory(__dirname, '..', '..', 'browser', 'build');
    const browserIndexPath = path.resolve(browserPath, 'index.js');
    if (!browserPath || !fs.existsSync(browserIndexPath)) {
        throw new Error(`cannot find browser at ${path.resolve(__dirname, '..', 'browser')}`);
    }
    const sp = child_process.fork(browserIndexPath, [], {
        stdio: 'inherit',
        env: Object.assign(Object.assign({}, process.env), { DEPLOY_CONFIG_FILE: undefined }),
    });
    const server = http.createServer((request, response) => {
        return serve_handler_1.default(request, response, {
            public: dashboardPath,
            cleanUrls: false,
            rewrites: [
                { source: '/app/**', destination: 'index.html' },
                { source: '/', destination: 'index.html' },
            ],
        });
    });
    server.listen(3100, () => {
        logger_1.default.log('Dashboard running at http://localhost:3100');
    });
    server.on('exit', (signal) => {
        sp.kill(signal);
    });
    sp.on('exit', (signal) => {
        process.exit(signal);
    });
});
exports.startDashboard = startDashboard;
function executeTest(testName) {
    return __awaiter(this, void 0, void 0, function* () {
        yield exports.checkVersion();
        const dashboardPath = checkDirectory(__dirname, '..', 'dashboard') || checkDirectory(__dirname, '..', '..', 'webapp', 'build');
        if (!dashboardPath) {
            throw new Error(`cannot find dashboard path at ${path.resolve(__dirname, '..', 'dashboard')}`);
        }
        const browserPath = checkDirectory(__dirname, '..', 'browser') || checkDirectory(__dirname, '..', '..', 'browser', 'build');
        const browserIndexPath = path.resolve(browserPath, 'index.js');
        if (!browserPath || !fs.existsSync(browserIndexPath)) {
            throw new Error(`cannot find browser at ${path.resolve(__dirname, '..', 'browser')}`);
        }
        const { browser, param = [], dryRun } = this.opts();
        const variables = param
            .map((v) => v.split('='))
            .map(([key, value]) => ({
            variable: key,
            value,
        }));
        const sp = child_process.fork(browserIndexPath, [], {
            stdio: 'inherit',
            env: Object.assign(Object.assign({}, process.env), { DEPLOY_CONFIG_FILE: undefined, STARTUP_MODE: 'SINGLE_RUN', STARTUP_MODE_META: JSON.stringify({
                    testName,
                    browser,
                    variables,
                    dryRun,
                }) }),
        });
        const server = http.createServer((request, response) => {
            return serve_handler_1.default(request, response, {
                public: dashboardPath,
                cleanUrls: false,
                rewrites: [
                    { source: '/app/**', destination: 'index.html' },
                    { source: '/', destination: 'index.html' },
                ],
            });
        });
        server.listen(3100, () => {
            logger_1.default.log('Dashboard running at http://localhost:3100');
        });
        logger_1.default.log(`Please login to http://localhost:3100 to run test "${testName}"`);
        server.on('exit', (signal) => {
            sp.kill(signal);
        });
        sp.on('exit', (signal) => {
            process.exit(signal);
        });
    });
}
exports.executeTest = executeTest;
const checkDirectory = (...paths) => {
    const p = path.resolve(...paths);
    if (fs.existsSync(p)) {
        return p;
    }
    return undefined;
};
//# sourceMappingURL=api.js.map