"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.IOSocketManager = void 0;
const socket_io_1 = require("socket.io");
const core_1 = require("@microlambda/core");
const types_1 = require("@microlambda/types");
const rxjs_1 = require("rxjs");
const operators_1 = require("rxjs/operators");
const runner_core_1 = require("@microlambda/runner-core");
class IOSocketManager {
    constructor(port, server, scheduler, logger, graph) {
        this._serviceToListen = '';
        this._graphUpdated$ = new rxjs_1.Subject();
        this._scheduler = scheduler;
        const log = logger.scope('@microlambda/server/io');
        log.info('Attaching Websocket', {
            cors: {
                origin: ['http://localhost:4200', 'http://localhost:' + port],
                credentials: true,
            },
        });
        this._io = new socket_io_1.Server(server, {
            cors: {
                origin: ['http://localhost:4200', 'http://localhost:' + port],
                credentials: true,
            },
        });
        this._io.on("connect_error", (err) => {
            log.error(`connect_error due to ${err.message}`);
        });
        this._graph = graph;
        this._io.on('connection', (socket) => {
            socket.on('service.start', (serviceName) => {
                log.info('received service.start request', serviceName);
                const service = this._graph.services.get(serviceName);
                if (!service) {
                    log.error('unknown service', serviceName);
                }
                else {
                    this._scheduler.startOne(service);
                }
            });
            socket.on('service.restart', (serviceName) => {
                log.info('received service.restart request', serviceName);
                const service = this._graph.services.get(serviceName);
                if (!service) {
                    log.error('unknown service', serviceName);
                }
                else {
                    this._scheduler.restartOne(service);
                }
            });
            socket.on('service.stop', (serviceName) => {
                log.info('received service.stop request', serviceName);
                const service = this._graph.services.get(serviceName);
                if (!service) {
                    log.error('unknown service', serviceName);
                }
                else {
                    this._scheduler.stopOne(service);
                }
            });
            socket.on('send.service.logs', (service) => {
                this._serviceToListen = service;
            });
        });
        this._graphUpdated$.pipe((0, operators_1.debounceTime)(200)).subscribe(() => {
            log.info('graph updated');
            this._io.emit('graph.updated');
        });
        this._scheduler.events$.subscribe((evt) => {
            if ((0, core_1.isStopServiceEvent)(evt)) {
                switch (evt.type) {
                    case 'stopping':
                        this.statusUpdated(evt.service, types_1.ServiceStatus.STOPPING);
                        break;
                    case 'stopped':
                        this.statusUpdated(evt.service, types_1.ServiceStatus.STOPPED);
                        break;
                }
            }
            else {
                this._handleRunCommandEvent(evt);
            }
        });
    }
    _handleRunCommandEvent(evt) {
        switch (evt.type) {
            case runner_core_1.RunCommandEventEnum.NODE_STARTED:
                switch (evt.cmd) {
                    case 'start':
                        this.statusUpdated(evt.workspace, types_1.ServiceStatus.STARTING);
                        break;
                    case 'transpile':
                        this.transpilingStatusUpdated(evt.workspace, types_1.TranspilingStatus.TRANSPILING);
                        break;
                    case 'build':
                        this.typeCheckStatusUpdated(evt.workspace, types_1.TypeCheckStatus.CHECKING);
                        break;
                }
                break;
            case runner_core_1.RunCommandEventEnum.NODE_PROCESSED:
                switch (evt.cmd) {
                    case 'start':
                        this.statusUpdated(evt.workspace, types_1.ServiceStatus.RUNNING);
                        break;
                    case 'transpile':
                        this.transpilingStatusUpdated(evt.workspace, types_1.TranspilingStatus.TRANSPILED);
                        break;
                    case 'build':
                        this.typeCheckStatusUpdated(evt.workspace, types_1.TypeCheckStatus.SUCCESS);
                        break;
                }
                break;
            case runner_core_1.RunCommandEventEnum.NODE_ERRORED:
                switch (evt.cmd) {
                    case 'start':
                        this.statusUpdated(evt.workspace, types_1.ServiceStatus.CRASHED);
                        break;
                    case 'transpile':
                        this.transpilingStatusUpdated(evt.workspace, types_1.TranspilingStatus.ERROR_TRANSPILING);
                        break;
                    case 'build':
                        this.typeCheckStatusUpdated(evt.workspace, types_1.TypeCheckStatus.ERROR);
                        break;
                }
                break;
            case runner_core_1.RunCommandEventEnum.NODE_INTERRUPTED:
                switch (evt.cmd) {
                    case 'start':
                        this.statusUpdated(evt.workspace, types_1.ServiceStatus.STOPPED);
                        break;
                    case 'transpile':
                        this.transpilingStatusUpdated(evt.workspace, types_1.TranspilingStatus.NOT_TRANSPILED);
                        break;
                    case 'build':
                        this.typeCheckStatusUpdated(evt.workspace, types_1.TypeCheckStatus.NOT_CHECKED);
                        break;
                }
                break;
        }
    }
    _graphUpdated() {
        this._graphUpdated$.next();
    }
    statusUpdated(node, status) {
        this._graphUpdated();
        this._io.emit('node.status.updated', { node: node.name, status });
    }
    transpilingStatusUpdated(node, status) {
        this._graphUpdated();
        this._io.emit('transpiling.status.updated', {
            node: node.name,
            status,
        });
    }
    typeCheckStatusUpdated(node, status) {
        this._graphUpdated();
        this._io.emit('type.checking.status.updated', {
            node: node.name,
            status,
        });
    }
    eventLogAdded(log) {
        this._io.emit('event.log.added', log);
    }
    handleServiceLog(service, data) {
        if (this._serviceToListen === service) {
            this._io.emit(service + '.log.added', data);
        }
    }
    handleTscLogs(node, data) {
        this._io.emit('tsc.log.emitted', { node, data });
    }
    schedulerStatusChanged(status) {
        this._io.emit('scheduler.status.changed', status);
    }
}
exports.IOSocketManager = IOSocketManager;
//# sourceMappingURL=socket.js.map