"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const core_1 = require("@yinuo-ngm/core");
const bootstrap_1 = require("@yinuo-ngm/bootstrap");
const websocket_1 = __importDefault(require("@fastify/websocket"));
const fastify_plugin_1 = __importDefault(require("fastify-plugin"));
const topics_1 = require("./topics");
const ws_context_1 = require("./ws.context");
const ws_router_1 = require("./ws.router");
function uid() {
    return Math.random().toString(16).slice(2) + Date.now().toString(16);
}
exports.default = (0, fastify_plugin_1.default)(async function wsPlugin(fastify) {
    await fastify.register(websocket_1.default);
    const clients = new Map();
    const router = new ws_router_1.WsRouter();
    const taskHandler = (0, topics_1.createTaskTopicHandler)({
        getTaskSnapshotByTaskId: (taskId) => fastify.core.task.getSnapshotByTaskId(taskId),
        getTaskTailLogsByRun: (runId, tail) => fastify.core.task.getTailLogsByRun(runId, tail),
        resizeRun: (taskId, cols, rows) => fastify.core.task.resizeRun(taskId, cols, rows),
    }, () => clients.values());
    router.register(taskHandler);
    const syslogHandler = (0, topics_1.createSyslogTopicHandler)({ getSyslogTail: (tail) => fastify.core.sysLog.tail(tail) }, () => clients.values());
    router.register(syslogHandler);
    const svnSyncHandler = (0, topics_1.createSvnSyncTopicHandler)({
        getSvnRuntimeByProjectId: (projectId, tail) => fastify.core.svnSync.getRuntimeByProjectId(projectId, tail),
    }, () => clients.values());
    router.register(svnSyncHandler);
    const nginxHandler = (0, topics_1.createNginxTopicHandler)({ logService: fastify.nginx.log }, () => clients.values());
    router.register(nginxHandler);
    const offs = [];
    const events = fastify.core.events;
    offs.push(events.on(core_1.Events.TASK_OUTPUT, (e) => {
        taskHandler.pushOutput(e);
    }));
    offs.push(events.on(core_1.Events.TASK_STARTED, (e) => {
        taskHandler.pushEvent("started", e);
    }));
    offs.push(events.on(core_1.Events.TASK_STOP_REQUESTED, (e) => {
        taskHandler.pushEvent("stopRequested", e);
    }));
    offs.push(events.on(core_1.Events.TASK_EXITED, (e) => {
        taskHandler.pushEvent("exited", e);
    }));
    offs.push(events.on(core_1.Events.TASK_FAILED, (e) => {
        taskHandler.pushEvent("failed", e);
    }));
    offs.push(events.on(core_1.Events.SYSLOG_APPENDED, (e) => {
        syslogHandler.push(e.entry);
    }));
    offs.push(events.on(bootstrap_1.BootstrapEvents.DONE, (e) => {
        taskHandler.pushEvent("bootstrapDone", e);
    }));
    offs.push(events.on(bootstrap_1.BootstrapEvents.FAILED, (e) => {
        taskHandler.pushEvent("bootstrapFailed", e);
    }));
    offs.push(events.on(bootstrap_1.BootstrapEvents.NEED_PICK_ROOT, (e) => {
        taskHandler.pushEvent("bootstrapNeedPickRoot", e);
    }));
    offs.push(events.on(core_1.Events.SVN_SYNC_STARTED, (e) => {
        svnSyncHandler.pushEvent("started", e);
    }));
    offs.push(events.on(core_1.Events.SVN_SYNC_OUTPUT, (e) => {
        svnSyncHandler.pushEvent("output", e);
    }));
    offs.push(events.on(core_1.Events.SVN_SYNC_PROGRESS, (e) => {
        svnSyncHandler.pushEvent("progress", e);
    }));
    offs.push(events.on(core_1.Events.SVN_SYNC_DONE, (e) => {
        svnSyncHandler.pushEvent("done", e);
    }));
    fastify.addHook("onClose", async () => {
        offs.forEach((off) => {
            try {
                off();
            }
            catch { }
        });
        fastify.nginx.log.stopAll();
        clients.clear();
    });
    fastify.get("/ws", { websocket: true }, (ws) => {
        const connId = uid();
        const ctx = new ws_context_1.WsContext(connId, ws);
        clients.set(connId, ctx);
        ctx.send({ op: "hello", connId, ts: Date.now() });
        ws.on("message", (data) => router.handleRaw(ctx, data));
        ws.on("close", () => {
            ctx.clearAll();
            clients.delete(connId);
        });
    });
});
