using pkNX.Structures;
using System;
using static pkNX.Structures.Species;

namespace pkNX.Randomization;

public class FormRandomizer
{
    private readonly IPersonalTable Personal;

    public FormRandomizer(IPersonalTable t)
    {
        Personal = t;
    }

    public int GetRandomForme(int species, bool mega, bool fused, bool alola, bool galar, IPersonalInfo[]? stats = null)
    {
        stats ??= Personal.Table;
        if (stats[species].FormCount <= 1)
            return 0;
        bool IsGen6 = Personal.MaxSpeciesID == 721;

        switch ((Species)species)
        {
            // Rayquaza's Forme Count was unchanged in SWSH despite Megas being removed, so just in case the user allows random Megas, disallow this invalid Forme.
            case Rayquaza when Personal.Table.Length == 1192:
                return 0;
            case Unown:
            case Deerling:
            case Sawsbuck:
                return 31; // Random
            case Greninja when !mega:
                return 0;
            case Scatterbug:
            case Spewpa:
            case Vivillon:
                return 30; // save file specific
            case Zygarde when !IsGen6:
                return Util.Random.Next(4); // Complete Forme is battle only
            case Minior:
                return Util.Random.Next(7); // keep the core color a surprise

            case Meowth when galar:
                return Util.Random.Next(3); // Kanto, Alola, Galar

            // only allow Standard, not Zen Mode
            case Darmanitan when galar:
            {
                int form = Util.Random.Next(stats[species].FormCount);
                return form & 2;
            }

            // some species have 1 invalid form among several other valid forms, handle them here
            case Pikachu when Personal.Table.Length == 1192:
            case Slowbro when galar:
            {
                int form = Util.Random.Next(stats[species].FormCount - 1);
                int banned = GetInvalidForm(species, galar, Personal);
                if (form == banned)
                    form++;
                return form;
            }
        }

        if (Personal.Table.Length == 980 && species is (int)Pikachu or (int)Eevee) // gg tableB -- no starters, they crash trainer battles.
            return 0;
        if (alola && Legal.EvolveToAlolanForms.Contains((ushort)species))
            return Util.Random.Next(2);
        if (galar && Legal.EvolveToGalarForms.Contains((ushort)species))
            return Util.Random.Next(2);
        if (!Legal.BattleExclusiveForms.Contains(species) || mega || (fused && Legal.BattleFusions.Contains(species)))
            return Util.Random.Next(stats[species].FormCount); // Slot-Random
        return 0;
    }

    public static int GetInvalidForm(int species, bool galar, IPersonalTable stats) => species switch
    {
        (int)Pikachu when stats.Table.Length == 1192 => 8, // LGPE Partner Pikachu
        (int)Slowbro when galar => 1, // Mega Slowbro
        _ => throw new ArgumentOutOfRangeException(nameof(species)),
    };
}
