const { SlashCommandBuilder } = require('@discordjs/builders');
const { MessageEmbed } = require('discord.js');
const help = require('../helpFunctions.js');
const PATH = './database/events.json';
const eventsJSON = require('../database/events.json');
const { writeToFile } = require('../helpFunctions.js');

module.exports = {
	data: new SlashCommandBuilder()
		.setName('event')
		.setDescription('Adds events to celebrate!')
        .addSubcommand(subcommand =>
            subcommand.setName('add')
                .setDescription('Adds new event to the database')
                .addStringOption(option => option.setName('name')
                    .setDescription('Name of the event you want to add')
                    .setRequired(true))
                .addIntegerOption(option =>
                    option.setName('day')
                    .setDescription('Day of event')
                    .setRequired(true))
                .addIntegerOption(option =>
                    option.setName('month')
                    .setDescription('Month of event')
                    .setRequired(true))
                .addBooleanOption(option =>
                    option.setName('global')
                    .setDescription('Should this event display on all servers?')))
        .addSubcommand(subcommand =>
            subcommand.setName('delete')
                .setDescription('Deletes event from database')
                .addStringOption(option => option.setName('name')
                    .setDescription('Name of the event you want to delete'))
                .addIntegerOption(option => option.setName('id')
                    .setDescription('Id of the even you want to change')))
        .addSubcommandGroup(subcommandGroup =>
            subcommandGroup.setName('change')
                .setDescription('Change the event entry')
                .addSubcommand(subcommand =>
                    subcommand.setName('date')
                        .setDescription('Change date of an event')
                        .addIntegerOption(option =>
                            option.setName('day')
                            .setDescription('New event day')
                            .setRequired(true))
                        .addIntegerOption(option =>
                            option.setName('month')
                            .setDescription('New event month')
                            .setRequired(true))
                        .addIntegerOption(option => option.setName('id')
                            .setDescription('Id of the even you want to change'))
                        .addStringOption(option => option.setName('name')
                            .setDescription('Name of the event you want to change')))
                .addSubcommand(subcommand =>
                    subcommand.setName('name')
                        .setDescription('Change name of an event')
                        .addStringOption(option =>
                            option.setName('new-name')
                            .setDescription('New name of the event')
                            .setRequired(true))
                        .addIntegerOption(option => option.setName('id')
                            .setDescription('Id of the even you want to change'))
                        .addStringOption(option => option.setName('name')
                            .setDescription('Name of the event you want to change'))))
        .addSubcommand(subcommand =>
            subcommand.setName('list')
            .setDescription('List all events')),
        async execute(interaction) {
            // make this help function you basically copy it evrytime (in birthday.js aswell)
            const error = catchErrors(interaction.options);
            if (error != null) {
                await interaction.reply(error);
            }
            let subcommandGroup;
            try {
                subcommandGroup = interaction.options.getSubcommandGroup();
            }
            catch {
                subcommandGroup = undefined;
            }
            const subcommand = interaction.options.getSubcommand();
            const key = idOrName(interaction.options);
            if (subcommandGroup == undefined) {
                switch (subcommand) {
                    case 'list':
                        await interaction.reply({ embeds: [listEvents(interaction)] });
                        break;
                    case 'add':
                        await interaction.reply(addEvent(interaction));
                        break;
                    case 'delete':
                        await interaction.reply(deleteEvent(interaction, key));
                        break;
                }
            }
            else {
                switch (subcommand) {
                    case 'date':
                        await interaction.reply(changeEventDate(interaction, key));
                        break;
                    case 'name':
                        await interaction.reply(changeEventName(interaction, key));
                        break;
                }
            }
        },
};

// TODO add event GLOBAL
// TODO add event local
// if the guild isnt there add it


function changeEventDate(interaction, key) {
    if (key == null) {
        return 'I need id or name of the event you want to edit';
    }
    const newDay = interaction.options.getInteger('day');
    const newMonth = interaction.options.getInteger('month');
    // TODO deduplicate
    if (!isNaN(key)) {
        const id = parseFloat(key);
        if (id % 10 == 0) {
            let globalEvents = eventsJSON.global;
            for (let i = 0; i < globalEvents.length; i++) {
                const name = globalEvents[i].name;
                if (globalEvents[i].id == id) {
                    const prevDay = globalEvents[i].day;
                    const prevMonth = globalEvents[i].month;
                    let fstPart = globalEvents.slice(0, i);
                    let sndPart = globalEvents.slice(i + 1);
                    globalEvents = fstPart.concat(sndPart);

                    for (let j = 0; j < globalEvents.length; j++) {
                        if ((newMonth == globalEvents[i].month && newDay >= globalEvents.day)
                            || newMonth < globalEvents[i].month) {
                                fstPart = globalEvents.slice(0, j);
                                fstPart.push({ id: id, name: name, day: newDay, month: newMonth });
                                sndPart = globalEvents.slice(j + 1);
                                eventsJSON.global = fstPart.concat(sndPart);

                                const error = writeToFile(eventsJSON, PATH);
                                if (error != null) {
                                    return error;
                                }
                                return `Successfuly changed global event ${name}  date ` +
                                        `from ${prevDay}. ${prevMonth}. ` +
                                        `to ${newDay}. ${newMonth}.`;
                            }
                    }
                    globalEvents.push({ id: id, name: name, day: newDay, month: newMonth });
                    eventsJSON.global = globalEvents;
                    const error = writeToFile(eventsJSON, PATH);
                    if (error != null) {
                        return error;
                    }
                    return `Successfuly changed global event ${name}  date ` +
                            `from ${prevDay}. ${prevMonth}. ` +
                            `to ${newDay}. ${newMonth}.`;
                }
            }
        }
        else {
            const guildEvents = eventsJSON[interaction.guild.id];
            for (let i = 0; i < guildEvents.length; i++) {
                const name = guildEvents[i].name;
                if (guildEvents[i].id == id) {
                    const prevDay = guildEvents[i].day;
                    const prevMonth = guildEvents[i].month;
                    let fstPart = guildEvents.slice(0, i);
                    let sndPart = guildEvents.slice(i + 1);
                    for (let j = 0; j < guildEvents.length; j++) {
                        if ((newMonth == guildEvents[i].month &&
                            newDay >= guildEvents.day) ||
                            newMonth < guildEvents[i].month) {
                            fstPart = guildEvents.slice(0, j);
                            fstPart.push({ id: id, name: name, day: newDay, month: newMonth });
                            sndPart = guildEvents.slice(j + 1);
                            eventsJSON[interaction.guild.id] = fstPart.concat(sndPart);
                            const error = writeToFile(eventsJSON, PATH);
                            if (error != null) {
                                return error;
                            }
                            return `Successfuly changed guild event ${name}  date ` +
                                    `from ${prevDay}. ${prevMonth}. ` +
                                    `to ${newDay}. ${newMonth}.`;
                        }
                    }
                    guildEvents.push({ id: id, name: name, day: newDay, month: newMonth });
                    eventsJSON.global = guildEvents;
                    const error = writeToFile(eventsJSON, PATH);
                    if (error != null) {
                        return error;
                    }
                    return `Successfuly changed guild event ${name}  date ` +
                    `from ${prevDay}. ${prevMonth}. ` +
                    `to ${newDay}. ${newMonth}.`;
                }
            }
        }
    }
    else {
        let globalEvents = eventsJSON.global;
            for (let i = 0; i < globalEvents.length; i++) {
                const name = globalEvents[i].name;
                const id = globalEvents[i].id;
                if (globalEvents[i].name == name) {
                    const prevDay = globalEvents[i].day;
                    const prevMonth = globalEvents[i].month;
                    let fstPart = globalEvents.slice(0, i);
                    let sndPart = globalEvents.slice(i + 1);
                    globalEvents = fstPart.concat(sndPart);

                    for (let j = 0; j < globalEvents.length; j++) {
                        if ((newMonth == globalEvents[i].month && newDay >= globalEvents.day)
                            || newMonth < globalEvents[i].month) {
                            fstPart = globalEvents.slice(0, j);
                            fstPart.push({ id: id, name: name, day: newDay, month: newMonth });
                            sndPart = globalEvents.slice(j);
                            eventsJSON.global = fstPart.concat(sndPart);

                            const error = writeToFile(eventsJSON, PATH);
                            if (error != null) {
                                return error;
                            }
                            return `Successfuly changed global event ${name}` +
                                    `  date from ${prevDay}. ${prevMonth}.`;
                        }
                }
            }
        }
        const guildEvents = eventsJSON[interaction.guild.id];
            for (let i = 0; i < guildEvents.length; i++) {
                const name = guildEvents[i].name;
                const id = globalEvents[i].id;
                if (guildEvents[i].name == name) {
                    const prevDay = guildEvents[i].day;
                    const prevMonth = guildEvents[i].month;
                    let fstPart = guildEvents.slice(0, i);
                    let sndPart = guildEvents.slice(i + 1);
                    for (let j = 0; j < guildEvents.length; j++) {
                        if ((newMonth == guildEvents[i].month &&
                            newDay >= guildEvents.day) ||
                            newMonth < guildEvents[i].month) {
                            fstPart = guildEvents.slice(0, j);
                            fstPart.push({ id: id, name: name, day: newDay, month: newMonth });
                            sndPart = guildEvents.slice(j);
                            eventsJSON.global = fstPart.concat(sndPart);
                            eventsJSON[interaction.guild.id] = fstPart.concat(sndPart);
                            const error = writeToFile(eventsJSON, PATH);
                            if (error != null) {
                                return error;
                            }
                            return `Successfuly changed guild event ${name} date` +
                                    ` from ${prevDay}. ${prevMonth}.`;
                        }
                    }
                }
            }
    }
    return 'There was an error (probably entered wrong id/name)';
}

function changeEventName(interaction, key) {
    if (key == null) {
        return 'I need id or name of the event you want to edit';
    }
    // TODO deduplicate
    if (!isNaN(key)) {
        const id = parseFloat(key);
        if (id % 10 == 0) {
            const globalEvents = eventsJSON.global;
            for (let i = 0; i < globalEvents.length; i++) {
                const name = globalEvents[i].name;
                if (globalEvents[i].id == id) {
                    globalEvents[i].name = interaction.options.getString('name');
                    eventsJSON.global = globalEvents;
                    const error = writeToFile(eventsJSON, PATH);
                    if (error != null) {
                        return error;
                    }
                    return 'Successfuly changed name of global event' +
                            `${name} to ${interaction.options.getString('name')}`;
                }
            }
        }
        else {
            const guildEvents = eventsJSON[interaction.guild.id];
            for (let i = 0; i < guildEvents.length; i++) {
                const name = guildEvents[i].name;
                if (guildEvents[i].id == id) {
                    guildEvents[i].name = interaction.options.getString('name');
                    eventsJSON[interaction.guild.id] = guildEvents;
                    const error = writeToFile(eventsJSON, PATH);
                    if (error != null) {
                        return error;
                    }
                    return 'Successfuly changed name of guild event' +
                            `${name} to ${interaction.options.getString('name')}`;
                }
            }
        }
    }
    else {
        const globalEvents = eventsJSON.global;
        for (let i = 0; i < globalEvents.length; i++) {
            const name = globalEvents[i].name;
            if (name == key) {
                globalEvents[i].name = interaction.options.getString('name');
                eventsJSON.global = globalEvents;
                const error = writeToFile(eventsJSON, PATH);
                if (error != null) {
                    return error;
                }
                return 'Successfuly changed name of global event' +
                        `${name} to ${interaction.options.getString('name')}`;
            }
        }
        const guildEvents = eventsJSON[interaction.guild.id];
        for (let i = 0; i < guildEvents.length; i++) {
            const name = guildEvents[i].name;
            if (name == key) {
                guildEvents[i].name = interaction.options.getString('name');
                eventsJSON[interaction.guild.id] = guildEvents;
                const error = writeToFile(eventsJSON, PATH);
                if (error != null) {
                    return error;
                }
                return 'Successfuly changed name of guild event' +
                        `${name} to ${interaction.options.getString('name')}`;
            }
        }
    }
    return 'There was an error (probably entered wrong id/name)';
}

function deleteEvent(interaction, key) {
    if (key == null) {
        return 'I need id or name of the event you want to delete';
    }
    // TODO deduplicate
    if (!isNaN(key)) {
        const id = parseFloat(key);
        if (id % 10 == 0) {
            const globalEvents = eventsJSON.global;
            for (let i = 0; i < globalEvents.length; i++) {
                const name = globalEvents[i].name;
                if (globalEvents[i].id == id) {
                    const fstPart = globalEvents.slice(0, i);
                    const sndPart = globalEvents.slice(i + 1);
                    eventsJSON.global = fstPart.concat(sndPart);
                    const error = writeToFile(eventsJSON, PATH);
                    if (error != null) {
                        return error;
                    }
                    return `Successfuly deleted global event ${name} from database`;
                }
            }
        }
        else {
            const guildEvents = eventsJSON[interaction.guild.id];
            for (let i = 0; i < guildEvents.length; i++) {
                const name = guildEvents[i].name;
                if (guildEvents[i].id == id) {
                    const fstPart = guildEvents.slice(0, i);
                    const sndPart = guildEvents.slice(i + 1);
                    eventsJSON[interaction.guild.id] = fstPart.concat(sndPart);
                    const error = writeToFile(eventsJSON, PATH);
                    if (error != null) {
                        return error;
                    }
                    return `Successfuly deleted guild event ${name} from database`;
                }
            }
        }
    }
    else {
        const guildEvents = eventsJSON[interaction.guild.id];
        for (let i = 0; i < guildEvents.length; i++) {
            const name = guildEvents[i].name;
            if (name == key) {
                const fstPart = guildEvents.slice(0, i);
                const sndPart = guildEvents.slice(i + 1);
                eventsJSON[interaction.guild.id] = fstPart.concat(sndPart);
                const error = writeToFile(eventsJSON, PATH);
                if (error != null) {
                    return error;
                }
                return `Successfuly deleted guild event ${name} from database`;
            }
        }
        const globalEvents = eventsJSON.global;
        for (let i = 0; i < globalEvents.length; i++) {
            const name = globalEvents[i].name;
            if (name == key) {
                const fstPart = globalEvents.slice(0, i);
                const sndPart = globalEvents.slice(i + 1);
                eventsJSON.global = fstPart.concat(sndPart);
                const error = writeToFile(eventsJSON, PATH);
                if (error != null) {
                    return error;
                }
                return `Successfuly deleted global event ${name} from database`;
            }
        }
    }
    return 'There was an error (probably entered wrong id/name)';
}

function addEvent(interaction) {
    const name = interaction.options.getString('name');
    const day = interaction.options.getInteger('day');
    const month = interaction.options.getInteger('month');

    let isGlobal;
    try {
        isGlobal = interaction.options.getBoolean('global');
    }
    catch {
        isGlobal = false;
    }
    // TODO if duplicate send if they want to add it anyway and 2 buttons yes/no

    const ms = new Date().getMilliseconds();
    let id = (100000 * day) + (100 * (ms % 1000)) + (month * 10);

    if (isGlobal) {
        const globalEvents = eventsJSON.global;
        for (let i = 0; i < globalEvents.length; i++) {
            // TODO make this help function you basically copy it evrytime (in birthday.js aswell)
            if ((globalEvents[i].month == month && globalEvents[i].day >= day) || globalEvents[i].month > month) {
                const fstPart = globalEvents.slice(0, i);
                const sndPart = globalEvents.slice(i);
                fstPart.push({ id: id, name: name, day: day, month: month });
                eventsJSON.global = fstPart.concat(sndPart);
                const error = help.writeToFile(eventsJSON, PATH);
                if (error != null) {
                    return 'There was an error while updating event list';
                }
                return `Successfuly added global event ${name} to event list`;
            }
        }
        globalEvents.push({ id: id, name: name, day: day, month: month });
        eventsJSON.global = globalEvents;
        const error = help.writeToFile(eventsJSON, PATH);
        if (error != null) {
            return 'There was an error while updating event list';
        }
        return `Successfuly added guild event ${name} to event list`;
    }
    else {
        const guildEvents = eventsJSON[interaction.guild.id];
        id++;
        if (guildEvents == undefined) {
            eventsJSON[interaction.guild.id] = [{ id: id, name: name, day: day, month: month }];
            const error = help.writeToFile(eventsJSON, PATH);
            if (error != null) {
                return 'There was an error while updating event list';
            }
            return `Successfuly added guild event ${name} to event list`;
        }
        else {
            for (let i = 0; i < guildEvents.length; i++) {
                if ((guildEvents[i].month == month && guildEvents[i].day >= day) || guildEvents[i].month > month) {
                    const fstPart = guildEvents.slice(0, i);
                    const sndPart = guildEvents.slice(i);
                    fstPart.push({ id: id, name: name, day: day, month: month });
                    eventsJSON[interaction.guild.id] = fstPart.concat(sndPart);
                    const error = help.writeToFile(eventsJSON, PATH);
                    if (error != null) {
                        return 'There was an error while updating event list';
                    }
                    return `Successfuly added guild event ${name} to event list`;
                }
            }
            guildEvents.push({ id: id, name: name, day: day, month: month });
            eventsJSON[interaction.guild.id] = guildEvents;
            const error = help.writeToFile(eventsJSON, PATH);
            if (error != null) {
                return 'There was an error while updating event list';
            }
            return `Successfuly added guild event ${name} to event list`;
        }
    }
}

function listEvents(interaction) {
    const embed = new MessageEmbed()
    .setColor(help.randomColor())
    .setTitle('Literally nothing here');

    let eventIds = [];
    let eventNames = [];
    let eventDates = [];
    const globalEvents = eventsJSON.global;
    // TODO deduplicate
    if (globalEvents != undefined && globalEvents.length > 0) {
        embed.addField('Global events:', '\u200b')
            .setTitle('');
        for (let i = 0; i < globalEvents.length; i++) {
            eventIds.push(globalEvents[i].id);
            eventNames.push(globalEvents[i].name);
            eventDates.push(`${globalEvents[i].day}. ${globalEvents[i].month}.`);
        }
        embed.addField('Id: ', eventIds.join('\n'), true);
        embed.addField('Name: ', eventNames.join('\n'), true);
        embed.addField('Date: ', eventDates.join('\n'), true);
        embed.addField('\u200b', '\u200b');
    }

    const guildEvents = eventsJSON[interaction.guild.id];
    if (guildEvents != undefined && guildEvents.length > 0) {
        eventIds = [];
        eventNames = [];
        eventDates = [];
        embed.addField('Guild events:', '\u200b')
            .setTitle('');
        for (let i = 0; i < guildEvents.length; i++) {
            eventIds.push(guildEvents[i].id);
            eventNames.push(guildEvents[i].name);
            eventDates.push(`${guildEvents[i].day}. ${guildEvents[i].month}.`);
        }
        embed.addField('Id: ', eventIds.join('\n'), true);
        embed.addField('Name: ', eventNames.join('\n'), true);
        embed.addField('Date: ', eventDates.join('\n'), true);
    }
    return embed;
}

function idOrName(options) {
    let id;
    try {
        id = options.getInteger('id');
    }
    catch {
        id = undefined;
    }
    if (id == undefined) {
        let name;
        try {
            name = options.getString('name');
        }
        catch {
            name = undefined;
        }
        if (name == undefined) {
            return null;
        }
        return name;
    }
    return id;
}

function catchErrors(options) {
    const month = options.getInteger('month');
    const day = options.getInteger('day');
    if (month == null || day == null) {
        return null;
    }

    if (month > 12 || month < 1) {
        return 'Bruh, "month" kinda poopy';
    }
    if (day > checkMonth(month) || day < 1) {
        return 'Bruh, "day" kinda poopy';
    }
    return null;
}

function checkMonth(month) {
    switch (month) {
        case 1:
            return 31;
        case 2:
            return 29;
        case 3:
            return 31;
        case 4:
            return 30;
        case 5:
            return 31;
        case 6:
            return 30;
        case 7:
            return 31;
        case 8:
            return 31;
        case 9:
            return 30;
        case 10:
            return 31;
        case 11:
            return 30;
        case 12:
            return 31;
    }
}