import {
    ApplicationCommand,
    ApplicationCommandDataResolvable,
    ApplicationCommandOptionType,
    ApplicationCommandType,
    ChatInputCommandInteraction,
    Collection,
} from "discord.js"
import {commandCharacter} from "./character/index.js"
import {CommandData} from "./types.js"
import {commandBot} from "./bot/index.js"

const commands: CommandData[] = [
    commandCharacter,
    commandBot,
]

export const commandDefinitions: ApplicationCommandDataResolvable[] = commands.map((c) => c.definition)

const _commandNameCache: Record<string, CommandData> = Object.fromEntries(
    commands.map((c) => [c.definition.name, c]),
)

export const invalidCommandError = "No command by that name exists."

export function storeCachedCommands(data: Collection<string, ApplicationCommand>) {
    for (const command of data.values()) {
        if (_commandNameCache.hasOwnProperty(command.name)) {
            _commandNameCache[command.name].setCached(command)
        } else {
            console.log("No such command when caching commands: " + command.name)
        }
    }
}

export async function executeCommand(ev: ChatInputCommandInteraction) {
    const name = ev.commandName
    if (!_commandNameCache.hasOwnProperty(name)) {
        throw invalidCommandError
    }
    await _commandNameCache[name].execute(ev)
}

const otherCommands: ApplicationCommandDataResolvable[] = [
    {
        name: "playstyle",
        type: ApplicationCommandType.ChatInput,
        description: "Updates your play style.",
        options: [
            {
                name: "difficulty",
                type: ApplicationCommandOptionType.Subcommand,
                description: "Alters or displays the reformation difficulty of your currently selected character.",
            },
            {
                name: "preference",
                type: ApplicationCommandOptionType.Subcommand,
                description: "Alters or displays the pred/prey preference of your currently selected character.",
            },
        ],
    },
    {
        name: "team",
        type: ApplicationCommandType.ChatInput,
        description: "Affects teams in battle.",
        options: [
            {
                name: "join",
                type: ApplicationCommandOptionType.Subcommand,
                description: "Leaves the current team, if any, and requests to join the same team (and battle) as another player.",
            },
            {
                name: "leave",
                type: ApplicationCommandOptionType.Subcommand,
                description: "Leaves the current team, if any, and strikes it out alone.",
            },
        ],
    },
    {
        name: "battle",
        type: ApplicationCommandType.ChatInput,
        description: "Takes actions in battle.",
        options: [
            {
                name: "challenge",
                type: ApplicationCommandOptionType.Subcommand,
                description: "Challenges another character to a battle.",
                options: [
                    {
                        name: "target",
                        type: ApplicationCommandOptionType.String,
                        description: "The character you want to challenge.",
                        autocomplete: true,
                    },
                ],
            },
            {
                name: "menu",
                type: ApplicationCommandOptionType.Subcommand,
                description: "Opens the battle menu to select an action for this turn.",
            },
            {
                name: "skill",
                type: ApplicationCommandOptionType.Subcommand,
                description: "Uses a skill.",
                options: [
                    {
                        name: "name",
                        type: ApplicationCommandOptionType.String,
                        description: "The name of the skill to use. Omit to see a list.",
                        autocomplete: true,
                        required: false,
                    },
                    {
                        name: "target",
                        type: ApplicationCommandOptionType.String,
                        description: "The target to use the skill on, if there are multiple options. Omit to see a list.",
                        autocomplete: true,
                        required: false,
                    },
                ],
            },
            {
                name: "item",
                type: ApplicationCommandOptionType.Subcommand,
                description: "Uses an item.",
                options: [
                    {
                        name: "name",
                        type: ApplicationCommandOptionType.String,
                        description: "The name of the item to use. Omit to see a list.",
                        autocomplete: true,
                        required: false,
                    },
                    {
                        name: "target",
                        type: ApplicationCommandOptionType.String,
                        description: "The target to use the item on, if there are multiple options. Omit to see a list.",
                        autocomplete: true,
                        required: false,
                    },
                ],
            },
            {
                name: "vore",
                type: ApplicationCommandOptionType.Subcommand,
                description: "Devours your opponent. Requires your opponent to be at low Confidence.",
                options: [
                    {
                        name: "style",
                        type: ApplicationCommandOptionType.String,
                        description: "The style of devouring to use. Omit to see a list.",
                        autocomplete: true,
                        required: false,
                    },
                ],
            },
            {
                name: "rest",
                type: ApplicationCommandOptionType.Subcommand,
                description: "Takes a breather, recovering your Confidence and Energy at a faster-than-normal rate for this turn.",
            },
            {
                name: "escape",
                type: ApplicationCommandOptionType.Subcommand,
                description: "Tries to escape from a battle or stomach. Requires your opponent to be at low Confidence.",
            },
            {
                name: "surrender",
                type: ApplicationCommandOptionType.Subcommand,
                description: "Lets your opponent do as they will with you by reducing your Confidence or Health to 0.",
            },
            {
                name: "prey",
                type: ApplicationCommandOptionType.SubcommandGroup,
                description: "Commands for when you have a full belly.",
                options: [
                    {
                        name: "release",
                        type: ApplicationCommandOptionType.Subcommand,
                        description: "Releases your prey from your stomach.",
                    },
                    {
                        name: "squish",
                        type: ApplicationCommandOptionType.Subcommand,
                        description: "Squishes your prey, ending the combat. Can only be performed when the prey is at or below 0% Health.",
                    },
                ],
            },
        ],
    },
    {
        name: "safety",
        type: ApplicationCommandType.ChatInput,
        description: "Safety commands for protecting consent and user data.",
        options: [
            {
                name: "exit",
                type: ApplicationCommandOptionType.SubcommandGroup,
                description: "Exits battle(s) and reverts its/their effects on you. To flee in-character, use /battle escape.",
            },
            {
                name: "block",
                type: ApplicationCommandOptionType.SubcommandGroup,
                description: "Manages your block list.",
                options: [
                    {
                        name: "add",
                        type: ApplicationCommandOptionType.Subcommand,
                        description: "Prevents a user or character from challenging you or joining battles you're in.",
                        options: [
                            {
                                name: "user",
                                type: ApplicationCommandOptionType.User,
                                description: "The user to block from challenging you or joining battles you're in.",
                                required: false,
                            },
                            {
                                name: "character",
                                type: ApplicationCommandOptionType.String,
                                description: "The character to block from challenging you or joining battles you're in.",
                                required: false,
                                autocomplete: true,
                            },
                        ],
                    },
                    {
                        name: "remove",
                        type: ApplicationCommandOptionType.Subcommand,
                        description: "Allows a user or character to challenge you and join battles you're in once more.",
                        options: [
                            {
                                name: "user",
                                type: ApplicationCommandOptionType.User,
                                description: "The user to allow to challenge you and join battles you're in once more.",
                                required: false,
                            },
                            {
                                name: "character",
                                type: ApplicationCommandOptionType.String,
                                description: "The character to allow to challenge you and join battles you're in once more.",
                                required: false,
                                autocomplete: true,
                            },
                        ],
                    },
                    {
                        name: "list",
                        type: ApplicationCommandOptionType.Subcommand,
                        description: "Displays your current block list.",
                    },
                ],
            },
            {
                name: "kick",
                type: ApplicationCommandOptionType.SubcommandGroup,
                description: "Manages the list of users kicked from the current battle.",
                options: [
                    {
                        name: "add",
                        type: ApplicationCommandOptionType.Subcommand,
                        description: "Removes a user or character from the current battle and prevents them from rejoining.",
                        options: [
                            {
                                name: "user",
                                type: ApplicationCommandOptionType.User,
                                description: "The user to remove from the current battle and prevent from rejoining.",
                                required: false,
                            },
                            {
                                name: "character",
                                type: ApplicationCommandOptionType.String,
                                description: "The character to remove from the current battle and prevent from rejoining.",
                                required: false,
                                autocomplete: true,
                            },
                        ],
                    },
                    {
                        name: "remove",
                        type: ApplicationCommandOptionType.Subcommand,
                        description: "Allows a user or character to rejoin the current battle.",
                        options: [
                            {
                                name: "user",
                                type: ApplicationCommandOptionType.User,
                                description: "The user to allow to rejoin the current battle.",
                                required: false,
                            },
                            {
                                name: "character",
                                type: ApplicationCommandOptionType.String,
                                description: "The user to allow to rejoin the current battle.",
                                required: false,
                                autocomplete: true,
                            },
                        ],
                    },
                    {
                        name: "list",
                        type: ApplicationCommandOptionType.Subcommand,
                        description: "Displays the list of users forbidden from rejoining the current battle.",
                    },
                ],
            },
            {
                name: "ban",
                type: ApplicationCommandOptionType.SubcommandGroup,
                description: "Manages the ban list of the current server.",
                options: [
                    {
                        name: "add",
                        type: ApplicationCommandOptionType.Subcommand,
                        description: "Bans a user from participating in battles in the current server and kicks them from any they're in.",
                        options: [
                            {
                                name: "user",
                                type: ApplicationCommandOptionType.User,
                                description: "The user to ban from participating in battles in the current server.",
                                required: true,
                            },
                        ],
                    },
                    {
                        name: "remove",
                        type: ApplicationCommandOptionType.Subcommand,
                        description: "Allows a user to resume participating in battles in the current server.",
                        options: [
                            {
                                name: "user",
                                type: ApplicationCommandOptionType.User,
                                description: "The user to allow to participate in battles in the current server once more.",
                                required: true,
                            },
                        ],
                    },
                    {
                        name: "list",
                        type: ApplicationCommandOptionType.Subcommand,
                        description: "Displays this server's current ban list.",
                    },
                ],
            },
            {
                name: "delete",
                type: ApplicationCommandOptionType.Subcommand,
                description: "PERMANENTLY deletes a character, exiting any battles they were part of. See also /character archive.",
            },
            {
                name: "wipe",
                type: ApplicationCommandOptionType.Subcommand,
                description: "PERMANENTLY deletes ALL data about you in the system, erasing you from the system's knowledge.",
            },
        ],
    },
]