const { Snowflake, Client, Guild, VoiceBasedChannel, Events, Status, GatewayDispatchEvents } = require("discord.js");

const adapters = new Map();
const trackedClients = new Set();
const trackedShards = new Map();


function trackClient(client) {
    if (trackedClients.has(client)) return;
    trackedClients.add(client);
    client.ws.on(GatewayDispatchEvents.VoiceServerUpdate, (payload) => {
        adapters.get(payload.guild_id)?.onVoiceServerUpdate(payload);
    });
    client.ws.on(GatewayDispatchEvents.VoiceStateUpdate, (payload) => {
        if (payload.guild_id && payload.session_id && payload.user_id === client.user?.id) {
            adapters.get(payload.guild_id)?.onVoiceStateUpdate(payload);
        }
    });
    client.on(Events.ShardDisconnect, (_, shardId) => {
        const guilds = trackedShards.get(shardId);
        if (guilds) {
            for (const guildID of guilds.values()) {
                adapters.get(guildID)?.destroy();
            }
        }
        trackedShards.delete(shardId);
    });
}

function trackGuild(guild) {
    let guilds = trackedShards.get(guild.shardId);
    if (!guilds) {
        guilds = new Set();
        trackedShards.set(guild.shardId, guilds);
    }
    guilds.add(guild.id);
}


module.exports = function (channel) {
    return (methods) => {
        adapters.set(channel.guild.id, methods);
        trackClient(channel.client);
        trackGuild(channel.guild);
        return {
            sendPayload(data) {
                console.log(channel.guild.shard.status);
                // if (channel.guild.shard.status === Status.READY) {
                    console.log("Sending shard data");
                    channel.guild.shard.send(data);
                    return true;
                // }
                console.log("Unable to send channel payload");
                return false;
            },
            destroy() {
                console.log("Destroying adapter");
                return adapters.delete(channel.guild.id);
            },
        };
    };
}