/*
 * Copyright (c) 2022.
 * Author Peter Placzek (tada5hi)
 * For the full copyright and license information,
 * view the LICENSE file that was distributed with this source code.
 */

import {Namespace, Server, Socket} from "socket.io";
import {HttpServerInterface} from "../../config/http/server";
import {Environment} from "../../env";
import {createAdapter} from "@socket.io/redis-adapter";
import {MemorySocketEventMessage, subscribeEventsForSocketServer} from "../memory-event-bus/socket";
import {Config} from "../../config";
import {AuthUser} from "@chamesu/common/domains/auth/user";

export interface SocketInterface extends Socket {
    user?: AuthUser,
    userId?: number,
    userToken?: string,
    chatRooms: string[]
}

export interface ServerInterface extends Server {

}

export interface NamespaceInterface extends Namespace {

}

type SocketIoContext = {
    env: Environment,
    httpServer: HttpServerInterface,
    config: Config
}

function createSocketServer({ httpServer, config } : SocketIoContext) {
    const socketServer = new Server({
        cors: {
            credentials: true
        },
        transports: ['websocket', 'polling'],
        serveClient: true
    });

    socketServer.adapter(createAdapter(config.redisPub, config.redisSub));
    socketServer.attach(httpServer);

    subscribeEventsForSocketServer(socketServer, (memoryEventMessage: MemorySocketEventMessage) => {
        if(typeof memoryEventMessage.room === 'undefined') {
            socketServer
                .of(memoryEventMessage.namespace ?? '/')
                .emit(memoryEventMessage.event, memoryEventMessage.payload);
        } else {
            socketServer
                .of(memoryEventMessage.namespace ?? '/')
                .in(memoryEventMessage.room)
                .emit(memoryEventMessage.event, memoryEventMessage.payload);
        }
    });

    return socketServer;
}

export default createSocketServer;
