'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
const logger_1 = require("./logger");
const socket_io_1 = require("socket.io");
const EventEmitter_1 = require("./EventEmitter");
const SocketEvents_1 = require("./SocketEvents");
const logger = (0, logger_1.module)('Socket');
/**
 * The constructor
 */
class SocketManager extends EventEmitter_1.TypedEventEmitter {
    io;
    activeSockets = new Map();
    authMiddleware;
    /**
     * Binds socket.io to `server`
     *
     */
    bindServer(server) {
        this.io = new socket_io_1.Server(server, {
            path: '/socket.io',
        });
        this.io.on('error', (err) => {
            logger.error(`Socket error: ${err.message}`);
        });
        this.io
            .use(this._authMiddleware())
            .on('connection', this._onConnection.bind(this));
    }
    _authMiddleware() {
        return (socket, next) => {
            if (this.authMiddleware !== undefined) {
                this.authMiddleware(socket, next);
            }
            else {
                next();
            }
        };
    }
    /**
     * Handles new socket connections
     *
     */
    _onConnection(socket) {
        logger.debug(`New connection ${socket.id}`);
        // add socket to active sockets
        this.activeSockets.set(socket.id, socket);
        this.emit('clients', 'connection', this.activeSockets);
        // register inbound events from this socket
        for (const k in SocketEvents_1.inboundEvents) {
            const eventName = SocketEvents_1.inboundEvents[k];
            // pass socket reference as first parameter
            socket.on(eventName, this._emitEvent.bind(this, eventName, socket));
        }
        // https://socket.io/docs/v4/server-socket-instance/#events
        socket.on('disconnect', (reason) => {
            logger.debug(`User disconnected from ${socket.id}: ${reason}`);
            this.activeSockets.delete(socket.id);
            this.emit('clients', 'disconnect', this.activeSockets);
        });
    }
    /**
     * Logs and emits the `eventName` with `socket` and `args` as parameters
     *
     */
    _emitEvent(eventName, socket, data) {
        logger.debug(`Event ${eventName} emitted to ${socket.id}`);
        this.emit(eventName, socket, data);
    }
}
exports.default = SocketManager;
