"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.startServer = void 0;
const tslib_1 = require("tslib");
const express_1 = tslib_1.__importDefault(require("express"));
const http_1 = require("http");
const cors_1 = tslib_1.__importDefault(require("cors"));
const body_parser_1 = require("body-parser");
const logs_1 = require("./utils/logs");
tslib_1.__exportStar(require("./socket"), exports);
const startServer = (port = 4545, project, logger, scheduler) => {
    const log = logger.scope('api');
    const app = (0, express_1.default)();
    app.use((0, cors_1.default)({
        origin: ['http://localhost:4200', 'http://localhost:' + port],
        credentials: true,
    }));
    app.use((0, body_parser_1.json)());
    app.use('/', express_1.default.static(__dirname + '/static'));
    app.get('/api/ping', (req, res) => {
        res.status(200).send('Pong');
    });
    app.get('/api/graph', async (req, res) => {
        const summaryMapper = (n) => ({
            name: n.name,
            version: n.version || '',
            type: n.isService ? 'service' : 'package',
            port: n.isService ? (n.ports?.http || null) : null,
            enabled: n.hasCommand('start'),
            transpiled: n.transpiled,
            typeChecked: n.typechecked,
            status: n.started,
            children: Array.from(n.descendants.values()).map((n) => n.name),
            metrics: n.metrics,
        });
        const response = {
            packages: [...project.packages.values()].map(summaryMapper),
            services: [...project.services.values()].map(summaryMapper),
        };
        res.json(response);
    });
    const getSliceFromQuery = (req) => {
        if (!req.query.slice) {
            return [0];
        }
        const rawSlice = req.query.slice.toString().split(',');
        if (rawSlice.length === 0 || rawSlice.length > 2 || rawSlice.some((str) => !Number.isInteger(Number(str)))) {
            log.warn('Invalid slice', rawSlice);
            return [0];
        }
        return rawSlice[1] ? [Number(rawSlice[0]), Number(rawSlice[1])] : [Number(rawSlice[0])];
    };
    app.get('/api/logs', (req, res) => {
        if (project.logger) {
            let logs = project.logger.buffer
                .filter((log) => ['warn', 'info', 'error', 'debug'].includes(log.level));
            if (req.query.scope && typeof req.query.scope === 'string') {
                logs = logs.filter((entry) => entry.scope?.includes(req.query.scope.toString()));
            }
            return res.json((0, logs_1.getTrimmedSlice)(logs, getSliceFromQuery(req)));
        }
        else {
            return res.json({ data: [], metadata: { count: 0, slice: [0, 0] } });
        }
    });
    app.put('/api/graph', (req, res) => {
        log.debug('PUT /api/graph/');
        log.debug('Body', req.body);
        switch (req.body?.action) {
            case 'startAll':
                scheduler.startAll();
                break;
            case 'stopAll':
                scheduler.stopAll();
                break;
            case 'restartAll':
                scheduler.restartAll();
                break;
            default:
                return res.status(422).send('Invalid action');
        }
        return res.status(204).send();
    });
    app.put('/api/services/:service', (req, res) => {
        const serviceName = req.params.service;
        log.debug('PUT /api/services/:service', serviceName);
        log.debug('Body', req.body);
        const service = project.services.get(serviceName);
        if (!service) {
            log.error('GET /api/services/:service/logs - 404: No such service');
            return res.status(404).send();
        }
        switch (req.body?.action) {
            case 'start':
                scheduler.startOne(service);
                break;
            case 'stop':
                scheduler.stopOne(service);
                break;
            case 'restart':
                scheduler.restartOne(service);
                break;
            default:
                return res.status(400).send('Invalid action');
        }
        return res.status(204).send();
    });
    app.get('/api/nodes/:node/tsc/logs', (req, res) => {
        const nodeName = req.params.node;
        const node = project.workspaces.get(nodeName);
        if (!node) {
            log.error('GET /api/nodes/:node/tsc/logs - 404 : No such node', nodeName);
            return res.status(404).send();
        }
        const logs = node.logs('in-memory')?.get('build');
        if (logs) {
            return res.json((0, logs_1.getTrimmedSlice)(logs, getSliceFromQuery(req)));
        }
        else {
            return res.json({ data: [], metadata: { count: 0, slice: [0, 0] } });
        }
    });
    app.get('/api/services/:service/logs', (req, res) => {
        const serviceName = req.params.service;
        const service = project.services.get(serviceName);
        if (!service) {
            log.error('GET /api/services/:service/logs - 404: No such service');
            return res.status(404).send();
        }
        const logs = service.logs('in-memory')?.get('start');
        if (logs) {
            return res.json((0, logs_1.getTrimmedSlice)(logs, getSliceFromQuery(req)));
        }
        else {
            return res.json({ data: [], metadata: { count: 0, slice: [0, 0] } });
        }
    });
    const http = (0, http_1.createServer)(app);
    return new Promise((resolve) => {
        http.listen(port, () => {
            resolve(http);
        });
    });
};
exports.startServer = startServer;
//# sourceMappingURL=index.js.map