import { ClientEvents, ServerEvents, } from './events.js';
export class SocketGateway {
    nsp;
    eventBus;
    sessionManager;
    terminalManager;
    cleanups = [];
    constructor(nsp, eventBus, sessionManager, terminalManager) {
        this.nsp = nsp;
        this.eventBus = eventBus;
        this.sessionManager = sessionManager;
        this.terminalManager = terminalManager;
        this.registerEventBusForwarders();
    }
    destroy() {
        for (const cleanup of this.cleanups) {
            cleanup();
        }
        this.cleanups = [];
    }
    register(socket) {
        // --- Subscribe / Unsubscribe ---
        socket.on(ClientEvents.SUBSCRIBE, (payload, ack) => {
            this.handleSubscribe(socket, payload, ack);
        });
        socket.on(ClientEvents.UNSUBSCRIBE, (payload, ack) => {
            this.handleUnsubscribe(socket, payload, ack);
        });
        // --- Agent session I/O ---
        socket.on(ClientEvents.INPUT, (payload) => {
            if (!payload?.sessionId || typeof payload.data !== 'string')
                return;
            try {
                this.sessionManager.writeInput(payload.sessionId, payload.data);
            }
            catch (err) {
                console.error(`[SocketGateway] INPUT error for session ${payload.sessionId}:`, err);
            }
        });
        socket.on(ClientEvents.RESIZE, (payload) => {
            if (!payload?.sessionId || typeof payload.cols !== 'number' || typeof payload.rows !== 'number')
                return;
            try {
                this.sessionManager.resize(payload.sessionId, payload.cols, payload.rows);
            }
            catch (err) {
                console.error(`[SocketGateway] RESIZE error for session ${payload.sessionId}:`, err);
            }
        });
        // --- Standalone terminal I/O ---
        socket.on(ClientEvents.TERMINAL_INPUT, (payload) => {
            if (!payload?.terminalId || typeof payload.data !== 'string')
                return;
            try {
                this.terminalManager.write(payload.terminalId, payload.data);
            }
            catch (err) {
                console.error(`[SocketGateway] TERMINAL_INPUT error for terminal ${payload.terminalId}:`, err);
            }
        });
        socket.on(ClientEvents.TERMINAL_RESIZE, (payload) => {
            if (!payload?.terminalId || typeof payload.cols !== 'number' || typeof payload.rows !== 'number')
                return;
            try {
                this.terminalManager.resize(payload.terminalId, payload.cols, payload.rows);
            }
            catch (err) {
                console.error(`[SocketGateway] TERMINAL_RESIZE error for terminal ${payload.terminalId}:`, err);
            }
        });
        // --- Socket disconnect: clean up owned terminals ---
        socket.on('disconnect', () => {
            this.terminalManager.cleanupBySocket(socket.id);
        });
    }
    registerEventBusForwarders() {
        // --- Session events: broadcast to entire namespace (no room filtering) ---
        const onStdout = ({ sessionId, data }) => {
            this.nsp.emit(ServerEvents.SESSION_STDOUT, { sessionId, data });
        };
        const onPatch = ({ sessionId, patch, seq }) => {
            this.nsp.emit(ServerEvents.SESSION_PATCH, { sessionId, patch, seq });
        };
        const onSessionId = ({ sessionId, agentSessionId }) => {
            this.nsp.emit(ServerEvents.SESSION_ID, { sessionId, agentSessionId });
        };
        const onExit = ({ sessionId, exitCode }) => {
            this.nsp.emit(ServerEvents.SESSION_EXIT, {
                sessionId,
                exitCode: typeof exitCode === 'number' ? exitCode : 0,
            });
        };
        const onSessionCompleted = ({ sessionId, status }) => {
            this.nsp.emit(ServerEvents.SESSION_COMPLETED, { sessionId, status });
        };
        const onTask = ({ taskId, projectId, status }) => {
            this.nsp.emit(ServerEvents.TASK_UPDATED, { taskId, projectId, status });
        };
        const onTaskDeleted = ({ taskId, projectId }) => {
            this.nsp.emit(ServerEvents.TASK_DELETED, { taskId, projectId });
        };
        const onWorkspaceCommitMessageUpdated = (payload) => {
            this.nsp.emit(ServerEvents.WORKSPACE_COMMIT_MESSAGE_UPDATED, payload);
        };
        // --- Terminal events: keep room-based dispatch (lifecycle tied to socket) ---
        const onTerminalStdout = ({ terminalId, data }) => {
            this.nsp.to(`terminal:${terminalId}`).emit(ServerEvents.TERMINAL_STDOUT, { terminalId, data });
        };
        const onTerminalExit = ({ terminalId, exitCode }) => {
            this.nsp.to(`terminal:${terminalId}`).emit(ServerEvents.TERMINAL_EXIT, {
                terminalId,
                exitCode: typeof exitCode === 'number' ? exitCode : 0,
            });
        };
        // --- Workspace events: broadcast to entire namespace ---
        const onWorkspaceSetupProgress = (payload) => {
            this.nsp.emit(ServerEvents.WORKSPACE_SETUP_PROGRESS, payload);
        };
        const onWorkspaceHibernated = (payload) => {
            this.nsp.emit(ServerEvents.WORKSPACE_HIBERNATED, payload);
        };
        const onWorkspaceGitChanged = (payload) => {
            this.nsp.emit(ServerEvents.WORKSPACE_GIT_CHANGED, payload);
        };
        const onTeamRunInvalidated = (payload) => {
            this.nsp.emit(ServerEvents.TEAM_RUN_INVALIDATED, payload);
        };
        this.eventBus.on('session:stdout', onStdout);
        this.eventBus.on('session:patch', onPatch);
        this.eventBus.on('session:sessionId', onSessionId);
        this.eventBus.on('session:exit', onExit);
        this.eventBus.on('session:completed', onSessionCompleted);
        this.eventBus.on('task:updated', onTask);
        this.eventBus.on('task:deleted', onTaskDeleted);
        this.eventBus.on('workspace:commit_message_updated', onWorkspaceCommitMessageUpdated);
        this.eventBus.on('terminal:stdout', onTerminalStdout);
        this.eventBus.on('terminal:exit', onTerminalExit);
        this.eventBus.on('workspace:setup_progress', onWorkspaceSetupProgress);
        this.eventBus.on('workspace:hibernated', onWorkspaceHibernated);
        this.eventBus.on('workspace:git_changed', onWorkspaceGitChanged);
        this.eventBus.on('team-run:invalidated', onTeamRunInvalidated);
        this.cleanups.push(() => this.eventBus.off('session:stdout', onStdout), () => this.eventBus.off('session:patch', onPatch), () => this.eventBus.off('session:sessionId', onSessionId), () => this.eventBus.off('session:exit', onExit), () => this.eventBus.off('session:completed', onSessionCompleted), () => this.eventBus.off('task:updated', onTask), () => this.eventBus.off('task:deleted', onTaskDeleted), () => this.eventBus.off('workspace:commit_message_updated', onWorkspaceCommitMessageUpdated), () => this.eventBus.off('terminal:stdout', onTerminalStdout), () => this.eventBus.off('terminal:exit', onTerminalExit), () => this.eventBus.off('workspace:setup_progress', onWorkspaceSetupProgress), () => this.eventBus.off('workspace:hibernated', onWorkspaceHibernated), () => this.eventBus.off('workspace:git_changed', onWorkspaceGitChanged), () => this.eventBus.off('team-run:invalidated', onTeamRunInvalidated));
    }
    handleSubscribe(socket, payload, ack) {
        if (payload.topic === 'terminal' && payload.id) {
            socket.join(`terminal:${payload.id}`);
            socket.emit(ServerEvents.TERMINAL_SUBSCRIBED, { terminalId: payload.id });
        }
        ack?.({ success: true });
    }
    handleUnsubscribe(socket, payload, ack) {
        if (payload.topic === 'terminal' && payload.id) {
            socket.leave(`terminal:${payload.id}`);
            socket.emit(ServerEvents.TERMINAL_UNSUBSCRIBED, { terminalId: payload.id });
        }
        ack?.({ success: true });
    }
}
//# sourceMappingURL=socket-gateway.js.map