/**
 * Events WebSocket Handler
 *
 * Handles WebSocket connections for the event-subscription protocol.
 * Clients can subscribe to channels (tasks, messages, etc.) and receive
 * real-time event updates from the EventBroadcaster.
 */
import { parseClientMessage, getBroadcaster, shouldReceiveEvent, } from '@stoneforge/shared-routes';
import { createLogger } from '../utils/logger.js';
const logger = createLogger('orchestrator:events-ws');
/**
 * Track active event-subscription WebSocket connections
 */
const eventsClients = new Map();
function generateClientId() {
    return `events-${Date.now()}-${Math.random().toString(36).substring(2, 8)}`;
}
function sendToClient(ws, message) {
    try {
        ws.send(JSON.stringify(message));
    }
    catch (err) {
        logger.error('Error sending message to client:', err);
    }
}
/**
 * Handle a new event-subscription WebSocket connection
 */
export function handleEventsWSOpen(ws) {
    const clientId = generateClientId();
    const subscriptions = new Set();
    const eventListener = (event) => {
        if (shouldReceiveEvent(subscriptions, event)) {
            sendToClient(ws, { type: 'event', event });
        }
    };
    ws.data = {
        id: clientId,
        wsType: 'events',
        subscriptions,
        eventListener,
    };
    const broadcaster = getBroadcaster();
    if (broadcaster) {
        broadcaster.addListener(eventListener);
    }
    eventsClients.set(clientId, ws);
    logger.debug(`Client connected: ${clientId}`);
}
/**
 * Handle an event-subscription WebSocket message
 */
export function handleEventsWSMessage(ws, message) {
    const msg = typeof message === 'string' ? message : message.toString();
    const parsed = parseClientMessage(msg);
    if (!parsed) {
        sendToClient(ws, {
            type: 'error',
            code: 'INVALID_MESSAGE',
            message: 'Could not parse message',
        });
        return;
    }
    switch (parsed.type) {
        case 'ping':
            sendToClient(ws, { type: 'pong' });
            break;
        case 'subscribe': {
            for (const channel of parsed.channels) {
                ws.data.subscriptions.add(channel);
            }
            sendToClient(ws, { type: 'subscribed', channels: parsed.channels });
            logger.debug(`Client ${ws.data.id} subscribed to: ${parsed.channels.join(', ')}`);
            break;
        }
        case 'unsubscribe': {
            for (const channel of parsed.channels) {
                ws.data.subscriptions.delete(channel);
            }
            sendToClient(ws, { type: 'unsubscribed', channels: parsed.channels });
            logger.debug(`Client ${ws.data.id} unsubscribed from: ${parsed.channels.join(', ')}`);
            break;
        }
    }
}
/**
 * Handle event-subscription WebSocket close
 */
export function handleEventsWSClose(ws) {
    const { id, eventListener } = ws.data;
    const broadcaster = getBroadcaster();
    if (broadcaster) {
        broadcaster.removeListener(eventListener);
    }
    eventsClients.delete(id);
    logger.debug(`Client disconnected: ${id}`);
}
//# sourceMappingURL=events-websocket.js.map