/*
 * 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 {AppContext} from "../../index";
import {UserSocketHandler, useUserSocketHandler} from "./entities/user";
import {GuestSocketHandler} from "./entities/guest";
import createAuthMiddleware from "./middleware";
import createSocketEventHandler from "./events";
import {GuestStatusModule} from "./entities/guest/status";
import {GuestEvent} from "./entities/guest/event";
import {UserEvent, useUserEvent} from "./entities/user/event";
import {useUserEventCache} from "./entities/user/cache";
import {SocketInterface} from "../../../modules/socket";
import {useUserStatus} from "./entities/user/status";
import {ContactSocketHandler} from "./entities/contact";
import {useContactEventCache} from "./entities/contact/cache";
import {useContactEvent} from "./entities/contact/event";
import {useContactStatusHandler} from "./entities/contact/status";

export type AuthSocketAppContext = {
    userHandler: UserSocketHandler,
    guestHandler: GuestSocketHandler,
    contactHandler?: ContactSocketHandler
};

export default function createAuthSocketApp(ctx: AppContext) {
    const guestHandler = new GuestSocketHandler({
        event: new GuestEvent('/'),
        status: new GuestStatusModule(ctx.config.redisDatabase, {redis: { statusGroupKey: 'guestList' }})
    });

    const userHandler = useUserSocketHandler({
        cache: useUserEventCache(ctx.config.redisDatabase),
        notify: useUserEvent('/'),
        status: useUserStatus(ctx.config.redisDatabase),
    }, {
        socket: {
            userKey: 'user'
        }
    })

    guestHandler.checkIntegrity(ctx.socketServer).then(r => r);
    userHandler.checkIntegrity(ctx.socketServer).then(r => r);

    const contactHandler = new ContactSocketHandler({
        cache: useContactEventCache(ctx.config.redisDatabase),
        notify: useContactEvent('/'),
        status: useContactStatusHandler(ctx.config.redisDatabase)
    });

    contactHandler.checkIntegrity(ctx.socketServer).then(r => r);

    ctx.socketServer.use(createAuthMiddleware(
        async function (socket: SocketInterface) {
            await userHandler.add(socket);
    }, async function (socket: SocketInterface) {
        await guestHandler.add(socket);
    }));

    const aCtx : AuthSocketAppContext = {
        userHandler,
        guestHandler,
        contactHandler
    }

    createSocketEventHandler(ctx, aCtx);
}
