import { ChannelType, Client, Collection, Guild, GuildEmoji, GuildInvitableChannelResolvable, IntentsBitField } from 'discord.js';
import { writeFileSync, readdirSync, readFileSync } from 'fs'
import Canvas from 'canvas';
import GIFEncoder from 'gifencoder';
import Sharp from 'sharp';

async function staticToAnimatedEmoji(imagePath: string): Promise<Buffer> {
    const image = Sharp(imagePath);
    const metadata = await image.metadata();
    const data = await image.raw().toBuffer();
    if (!metadata.height || !metadata.width) throw new Error(`${imagePath} has no height or width`);
    const encoder = new GIFEncoder(metadata.width, metadata.height);
    encoder.setRepeat(0);
    encoder.start();

    const canvas = Canvas.createCanvas(metadata.width, metadata.height);
    const ctx = canvas.getContext('2d');
    const imageData = new Canvas.ImageData(
        new Uint8ClampedArray(data),
        canvas.width,
        canvas.height
    );

    ctx.putImageData(imageData, 0, 0);

    encoder.addFrame(ctx);
    encoder.addFrame(ctx);

    encoder.finish();

    let finished = encoder.out.getData();

    return finished;
}

async function uploadEmoji(guild: Guild, toUpload: {name: string, attachment: Buffer}): Promise<GuildEmoji> {
    const emoji = await guild.emojis.create(toUpload)

    return emoji;
}

async function propogateGuilds(client: Client<true>): Promise<Collection<string, Guild>> {
    console.log("Fetching Guilds")
    await client.guilds.fetch();
    let guilds = client.guilds.cache.filter((guild) => guild.ownerId == client.user.id);

    if (guilds.size < 10) {
        console.log(`Creating ${client.user.username} Emoji ${guilds.size + 1}`)
        const created = await client.guilds.create({
            name: `${client.user.username} Emoji ${guilds.size + 1}`
        });
        console.log(`Created: ${created.name}: ${created.id}`)
        return await propogateGuilds(client);
    }

    return guilds;
}

const client = new Client({
    intents: [
        IntentsBitField.Flags.GuildEmojisAndStickers,
        IntentsBitField.Flags.Guilds
    ]
});

client.on('warn', (m) => console.warn(m));
client.on('error', (m) => console.error(m.message));
client.rest.on("rateLimited", rateLimitData => {
    console.table({
        Global: rateLimitData.global,
        Endpoint: rateLimitData.route,
        Limit: rateLimitData.limit,
        TimeToRetry: `${Math.floor((rateLimitData.retryAfter / 1000) / 60)}M ${Math.floor((rateLimitData.retryAfter / 1000) % 60)}S`
    });
});

client.once('ready', async (client) => {
    if (!process.env.EMOJI_DIR) throw new Error("Missing Emoji Directory");
    console.log('ready')
    let emojis: Collection<string, string> = new Collection();
    const dir = readdirSync(process.env.EMOJI_DIR, {
        withFileTypes: true
    }).filter(file => file.isFile());
    console.log(dir)
    const emojiFiles = dir.filter(file => file.name.endsWith('.png'));

    let currentEmojiIndex = 0;
    const guilds = await propogateGuilds(client);
    console.log('Fetched Guilds');

    for (const [_gid, guild] of guilds) {
        if (guild.invites.cache.size > 0) {
            console.log(`${guild.name}: ${guild.invites.cache.first()?.url}`);
        } else {
            if (guild.channels.cache.size === 0) await guild.channels.create({name: 'invite-channel', type: ChannelType.GuildText });
            const channels = guild.channels.cache.filter(channel => !(channel.type == ChannelType.GuildCategory)) as Collection<string, GuildInvitableChannelResolvable>;
            const invite = await guild.invites.create(channels.first()!, {
                temporary: false
            });
            console.log(`${guild.name}: ${invite.url}`);
        }

        for (const [_eid, emoji] of guild.emojis.cache) {
            console.log(`Deleting ${emoji.name}`)
            await emoji.delete();
        }

        let emojiCount = 50;

        while (emojiCount > 0 && !(currentEmojiIndex >= emojiFiles.length)) {
            let emoji = emojiFiles[currentEmojiIndex];
            let attachment = readFileSync(`${process.env.EMOJI_DIR}/${emoji.name}`);
            let longName = emoji.name.split('.')[0].split('_').pop()!.replaceAll(/\-/g, "_");
            let name = longName.substring(0, Math.min(longName.length, 32));
            let i = 1;
            while (emojis.get(name)) {
                name = name.substring(0,-(i.toString().length)) + i
                i++
            }
            const outEmoji = await uploadEmoji(guild, {name, attachment});
            console.log(`${emoji.name.split('.')[0]}: ${outEmoji.id}`);
            emojis.set(emoji.name.split('.')[0], outEmoji.id);

            emojiCount--;
            currentEmojiIndex++;
        }
        console.log(`completed emojis for ${guild.name}`);

    }

    console.log('Creating out.json');

    let json: Record<string, string> = {};
    for (const [k,v] of emojis) {
        console.log(`Mapping ${k} to ${v}`);
        json[k] = v;
    }

    writeFileSync('./out.json', JSON.stringify(json));
    await client.destroy();
    process.exit(0);
})

client.login(process.env.TOKEN)