package com.trunksbomb.minetriad.card;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

import com.trunksbomb.minetriad.MineTriad;

import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;

public final class CardRegistry {
    private static final int[][][] TT_LEVEL_STATS = {
            {
                    { 1, 4, 1, 5 }, // Geezard
                    { 1, 1, 1, 3 }, // Funguar
                    { 3, 3, 3, 5 }, // Bite Bug
                    { 1, 1, 1, 2 }, // Red Bat
                    { 1, 3, 1, 5 }, // Blobra
                    { 4, 1, 4, 4 }, // Gayla
                    { 4, 5, 4, 1 }, // Gesper
                    { 2, 5, 2, 1 }, // Fastitocalon-F
                    { 6, 1, 6, 1 }, // Blood Soul
                    { 4, 2, 4, 3 }, // Caterchipillar
                    { 2, 1, 2, 6 } // Cockatrice
            },
            {
                    { 3, 1, 3, 1 }, // Grat
                    { 2, 2, 2, 3 }, // Buel
                    { 3, 3, 3, 4 }, // Mesmerize
                    { 4, 1, 4, 3 }, // Glacial Eye
                    { 5, 4, 5, 3 }, // Belhelmel
                    { 2, 3, 2, 5 }, // Thrustaevis
                    { 3, 1, 3, 5 }, // Anacondaur
                    { 5, 2, 5, 2 }, // Creeps
                    { 5, 4, 5, 2 }, // Grendal
                    { 1, 2, 1, 7 }, // Jelleye
                    { 5, 2, 5, 3 } // Grand Mantis
            },
            {
                    { 3, 6, 3, 2 }, // Forbidden
                    { 1, 3, 1, 6 }, // Armadodo
                    { 5, 5, 5, 5 }, // Tri-Face
                    { 1, 5, 1, 3 }, // Fastitocalon
                    { 5, 1, 5, 3 }, // Snow Lion
                    { 3, 6, 3, 3 }, // Ochu
                    { 2, 6, 2, 4 }, // SAM08G
                    { 7, 4, 7, 2 }, // Death Claw
                    { 6, 2, 6, 3 }, // Cactuar
                    { 4, 6, 4, 4 }, // Tonberry
                    { 3, 2, 3, 5 } // Abyss Worm
            },
            {
                    { 3, 6, 3, 7 }, // Turtapod
                    { 4, 5, 4, 5 }, // Vysage
                    { 2, 6, 2, 7 }, // T-Rexaur
                    { 6, 7, 6, 3 }, // Bomb
                    { 4, 6, 4, 7 }, // Blitz
                    { 1, 3, 1, 6 }, // Wendigo
                    { 4, 4, 4, 4 }, // Torama
                    { 3, 7, 3, 6 }, // Imp
                    { 7, 2, 7, 3 }, // Blue Dragon
                    { 5, 5, 5, 6 }, // Adamantoise
                    { 4, 5, 4, 3 } // HexDragon
            },
            {
                    { 6, 5, 6, 5 }, // Iron Giant
                    { 5, 6, 5, 7 }, // Behemoth
                    { 5, 6, 5, 3 }, // Chimera
                    { 2, 10, 2, 1 }, // Pupu
                    { 6, 2, 6, 7 }, // Elastoid
                    { 7, 5, 7, 4 }, // GIM47N
                    { 4, 7, 4, 2 }, // Malboro
                    { 7, 2, 7, 4 }, // Ruby Dragon
                    { 7, 3, 7, 6 }, // Elnoyle
                    { 6, 7, 6, 4 }, // Tonberry King
                    { 2, 6, 2, 7 } // Wedge, Biggs
            },
            {
                    { 8, 8, 8, 4 }, // Fujin, Rajin
                    { 3, 8, 3, 4 }, // Elvoret
                    { 7, 8, 7, 3 }, // X-ATM092
                    { 8, 2, 8, 5 }, // Granaldo
                    { 8, 8, 8, 3 }, // Gerogero
                    { 8, 2, 8, 2 }, // Iguion
                    { 4, 8, 4, 5 }, // Abadon
                    { 5, 8, 5, 6 }, // Trauma
                    { 4, 8, 4, 8 }, // Oilboyle
                    { 8, 5, 8, 4 }, // Shumi Tribe
                    { 8, 5, 8, 1 } // Krysta
            },
            {
                    { 4, 4, 4, 8 }, // Propagator
                    { 4, 8, 4, 4 }, // Jumbo Cactuar
                    { 6, 6, 6, 8 }, // Tri-Point
                    { 6, 6, 6, 8 }, // Gargantua
                    { 7, 6, 7, 3 }, // Mobile Type 8
                    { 5, 3, 5, 8 }, // Sphinxara
                    { 5, 8, 5, 4 }, // Tiamat
                    { 8, 7, 8, 5 }, // BGH251F2
                    { 4, 8, 4, 7 }, // Red Giant
                    { 7, 8, 7, 7 }, // Catoblepas
                    { 1, 7, 1, 8 } // Ultima Weapon
            },
            {
                    { 8, 4, 8, 9 }, // Chubby Chocobo
                    { 7, 6, 7, 3 }, // Angelo
                    { 9, 7, 9, 6 }, // Gilgamesh
                    { 9, 3, 9, 2 }, // Mini Mog
                    { 8, 4, 8, 4 }, // Chicobo
                    { 9, 9, 9, 4 }, // Quezacotl
                    { 4, 7, 4, 9 }, // Shiva
                    { 2, 6, 2, 8 }, // Ifrit
                    { 6, 9, 6, 2 }, // Siren
                    { 9, 1, 9, 9 }, // Sacred
                    { 2, 5, 2, 9 } // Minotaur
            },
            {
                    { 8, 4, 8, 4 }, // Carbuncle
                    { 8, 8, 8, 3 }, // Diablos
                    { 1, 10, 1, 7 }, // Leviathan
                    { 3, 10, 3, 5 }, // Odin
                    { 7, 1, 7, 7 }, // Pandemona
                    { 6, 4, 6, 10 }, // Cerberus
                    { 4, 10, 4, 2 }, // Alexander
                    { 7, 2, 7, 10 }, // Phoenix
                    { 2, 8, 2, 6 }, // Bahamut
                    { 10, 1, 10, 10 }, // Doomtrain
                    { 9, 4, 9, 10 } // Eden
            },
            {
                    { 2, 7, 2, 8 }, // Ward
                    { 6, 7, 6, 10 }, // Kiros
                    { 3, 10, 3, 9 }, // Laguna
                    { 6, 8, 6, 4 }, // Selphie
                    { 10, 6, 10, 2 }, // Quistis
                    { 9, 6, 9, 10 }, // Irvine
                    { 10, 5, 10, 6 }, // Zell
                    { 2, 10, 2, 10 }, // Rinoa
                    { 3, 10, 3, 3 }, // Edea
                    { 10, 9, 10, 4 }, // Seifer
                    { 6, 4, 6, 9 } // Squall
            } };

    private static final List<CardDefinition> CARD_DEFINITIONS = createDefinitions();
    private static final Map<ResourceLocation, CardDefinition> CARD_LOOKUP = CARD_DEFINITIONS.stream()
            .collect(Collectors.toUnmodifiableMap(CardDefinition::id, Function.identity()));

    private CardRegistry() {
    }

    public static List<CardDefinition> all() {
        return CARD_DEFINITIONS;
    }

    public static CardDefinition get(ResourceLocation id) {
        CardDefinition definition = CARD_LOOKUP.get(id);
        if (definition == null) {
            throw new IllegalArgumentException("Unknown card id: " + id);
        }
        return definition;
    }

    private static List<CardDefinition> createDefinitions() {
        List<CardDefinition> cards = new ArrayList<>();

        registerLevel(cards, 1, Rarity.COMMON,
                seed("chicken", "Chicken"),
                seed("rabbit", "Rabbit"),
                seed("cod", "Cod"),
                seed("salmon", "Salmon"),
                seed("tropical_fish", "Tropical Fish"),
                seed("pufferfish", "Pufferfish"),
                seed("tadpole", "Tadpole"),
                seed("bat", "Bat"),
                seed("bee", "Bee"),
                seed("pig", "Pig"),
                seed("sheep", "Sheep"));

        registerLevel(cards, 2, Rarity.COMMON,
                seed("cow", "Cow"),
                seed("mooshroom", "Mooshroom"),
                seed("goat", "Goat"),
                seed("fox", "Fox"),
                seed("cat", "Cat"),
                seed("wolf", "Wolf"),
                seed("frog", "Frog"),
                seed("turtle", "Turtle"),
                seed("parrot", "Parrot"),
                seed("axolotl", "Axolotl"),
                seed("ocelot", "Ocelot"));

        registerLevel(cards, 3, Rarity.COMMON,
                seed("donkey", "Donkey"),
                seed("mule", "Mule"),
                seed("horse", "Horse"),
                seed("llama", "Llama"),
                seed("camel", "Camel"),
                seed("panda", "Panda"),
                seed("polar_bear", "Polar Bear"),
                seed("dolphin", "Dolphin"),
                seed("squid", "Squid"),
                seed("glow_squid", "Glow Squid"),
                seed("sniffer", "Sniffer"));

        registerLevel(cards, 4, Rarity.UNCOMMON,
                seed("spider", "Spider"),
                seed("cave_spider", "Cave Spider"),
                seed("zombie", "Zombie"),
                seed("husk", "Husk"),
                seed("drowned", "Drowned"),
                seed("skeleton", "Skeleton"),
                seed("stray", "Stray"),
                seed("bogged", "Bogged"),
                seed("slime", "Slime"),
                seed("magma_cube", "Magma Cube"),
                seed("creeper", "Creeper"));

        registerLevel(cards, 5, Rarity.UNCOMMON,
                seed("enderman", "Enderman"),
                seed("witch", "Witch"),
                seed("phantom", "Phantom"),
                seed("silverfish", "Silverfish"),
                seed("endermite", "Endermite"),
                seed("blaze", "Blaze"),
                seed("ghast", "Ghast"),
                seed("piglin", "Piglin"),
                seed("hoglin", "Hoglin"),
                seed("zoglin", "Zoglin"),
                seed("wither_skeleton", "Wither Skeleton"));

        registerLevel(cards, 6, Rarity.RARE,
                seed("guardian", "Guardian"),
                seed("shulker", "Shulker"),
                seed("breeze", "Breeze"),
                seed("pillager", "Pillager"),
                seed("vindicator", "Vindicator"),
                seed("evoker", "Evoker"),
                seed("ravager", "Ravager"),
                seed("zombified_piglin", "Zombified Piglin"),
                seed("piglin_brute", "Piglin Brute"),
                seed("zombie_villager", "Zombie Villager"),
                seed("villager", "Villager"));

        registerLevel(cards, 7, Rarity.RARE,
                seed("wandering_trader", "Wandering Trader"),
                seed("trader_llama", "Trader Llama"),
                seed("iron_golem", "Iron Golem"),
                seed("snow_golem", "Snow Golem"),
                seed("vex", "Vex"),
                seed("allay", "Allay"),
                seed("armadillo", "Armadillo"),
                seed("skeleton_horse", "Skeleton Horse"),
                seed("zombie_horse", "Zombie Horse"),
                seed("elder_guardian", "Elder Guardian"),
                seed("strider", "Strider"));

        registerLevel(cards, 8, Rarity.LEGENDARY,
                seed("wither", "Wither"),
                seed("ender_dragon", "Ender Dragon"),
                seed("beacon", "Beacon"),
                seed("conduit", "Conduit"),
                seed("nether_star", "Nether Star"),
                seed("dragon_egg", "Dragon Egg"),
                seed("elytra", "Elytra"),
                seed("totem_of_undying", "Totem of Undying"),
                seed("ancient_city", "Ancient City"),
                seed("trial_spawner", "Trial Spawner"),
                seed("vault", "Vault"));

        registerLevel(cards, 9, Rarity.LEGENDARY,
                seed("stronghold", "Stronghold"),
                seed("ocean_monument", "Ocean Monument"),
                seed("woodland_mansion", "Woodland Mansion"),
                seed("nether_fortress", "Nether Fortress"),
                seed("bastion_remnant", "Bastion Remnant"),
                seed("end_city", "End City"),
                seed("netherite", "Netherite"),
                seed("poppy", "Poppy"),
                seed("enchanted_golden_apple", "Enchanted Golden Apple"),
                seed("mace", "Mace"),
                seed("recovery_compass", "Recovery Compass"));

        registerLevel(cards, 10, Rarity.LEGENDARY,
                seed("jeb", "Jeb"),
                seed("dinnerbone", "Dinnerbone"),
                seed("cpw", "cpw"),
                seed("direwolf20", "DireWolf20"),
                seed("xisumavoid", "XisumaVoid"),
                seed("docm77", "Docm77"),
                seed("ethoslab", "Etho"),
                seed("mumbojumbo", "Mumbo Jumbo"),
                seed("vintagebeef", "VintageBeef"),
                seed("sphax", "Sphax"),
                seed("c418", "C418"));

        return List.copyOf(cards);
    }

    private static void registerLevel(List<CardDefinition> cards, int level, Rarity rarity, CardSeed... seeds) {
        int[][] levelStats = TT_LEVEL_STATS[level - 1];
        if (seeds.length != levelStats.length) {
            throw new IllegalStateException("Expected " + levelStats.length + " cards for level " + level + " but got " + seeds.length);
        }

        for (int i = 0; i < seeds.length; i++) {
            CardSeed seed = seeds[i];
            cards.add(define(level, seed.path(), seed.displayName(), levelStats[i], rarity));
        }
    }

    private static CardDefinition define(int level, String path, String displayName, int[] pattern, Rarity rarity) {
        return new CardDefinition(
                ResourceLocation.fromNamespaceAndPath(MineTriad.MOD_ID, path),
                Component.literal(displayName),
                level,
                pattern[0],
                pattern[1],
                pattern[2],
                pattern[3],
                rarity);
    }

    private static CardSeed seed(String path, String displayName) {
        return new CardSeed(path, displayName);
    }

    private record CardSeed(String path, String displayName) {
    }
}
