"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createSocketServer = void 0;
const ws_1 = require("ws");
const createSocketServer = ({ server, onJoin, onJoinGroup }) => {
    const socketServer = new ws_1.Server({ server });
    const rooms = {};
    const subscriptions = new Map();
    const getRoom = (message) => {
        return 'id' in message
            ? `${message.streamName}:id:${message.id}`
            : `${message.streamName}:group-id:${message.groupId}`;
    };
    socketServer.on('connection', (socket) => {
        subscriptions.set(socket, new Set());
        socket.on('message', async (payload) => {
            const message = JSON.parse(payload.toString());
            if (message.type === 'join') {
                const room = getRoom(message.data);
                if (!rooms[room]) {
                    rooms[room] = new Map();
                }
                if ('id' in message.data) {
                    const item = await onJoin(message.data.streamName, message.data.id);
                    if (item) {
                        const resultMessage = {
                            streamName: message.data.streamName,
                            id: message.data.id,
                            event: { type: 'sync', data: item },
                        };
                        socket.send(JSON.stringify(resultMessage));
                    }
                }
                else {
                    const items = await onJoinGroup(message.data.streamName, message.data.groupId);
                    if (items) {
                        const resultMessage = {
                            streamName: message.data.streamName,
                            groupId: message.data.groupId,
                            event: { type: 'sync', data: items },
                        };
                        socket.send(JSON.stringify(resultMessage));
                    }
                }
                rooms[room].set(message.data.subscriptionId, socket);
                subscriptions.get(socket)?.add([room, message.data.subscriptionId]);
            }
            else if (message.type === 'leave') {
                const room = getRoom(message.data);
                if (rooms[room]) {
                    rooms[room].delete(message.data.subscriptionId);
                }
            }
        });
        socket.on('close', () => {
            subscriptions.get(socket)?.forEach(([room, subscriptionId]) => {
                rooms[room]?.delete(subscriptionId);
            });
            subscriptions.delete(socket);
        });
    });
    const pushEvent = (message) => {
        const room = getRoom(message);
        if (rooms[room]) {
            rooms[room].forEach((socket) => socket.send(JSON.stringify(message)));
        }
    };
    return { pushEvent, socketServer };
};
exports.createSocketServer = createSocketServer;
