namespace PKHeX.Core
{
    /// <summary>
    /// Beluga specific Dex manipulator, slightly modified from Gen7.
    /// </summary>
    public class Zukan7b : Zukan7
    {
        private const int SIZE_MAGIC = 4; // 0x2F120F17 magic
        private const int SIZE_FLAGS = 4;
        private const int SIZE_MISC = 0x80; // Misc Data (1024 bits)
        private const int SIZE_CAUGHT = 0x68; // 832 bits

        protected override int OFS_CAUGHT => SIZE_MAGIC + SIZE_FLAGS + SIZE_MISC;
        protected override int OFS_SEEN => OFS_CAUGHT + SIZE_CAUGHT;

        protected override int BitSeenSize => 0x8C; // 1120 bits
        protected override int DexLangFlagByteCount => 920; // 0x398 = 817*9, top off the savedata block.
        protected override int DexLangIDCount => 9; // CHT, skipping langID 6 (unused)

        public Zukan7b(SaveFile sav, int dex, int langflag)
        {
            SAV = sav;
            PokeDex = dex;
            PokeDexLanguageFlags = langflag;
            DexFormIndexFetcher = SaveUtil.GetDexFormIndexGG;
            LoadDexList();
        }

        public override void SetDex(PKM pkm)
        {
            if (!TryGetIndex(pkm.AltForm, pkm.Species, out _))
                return;
            SetSizeData(pkm);
            base.SetDex(pkm);
        }

        protected override void SetDex(int species, int bit, int form, int gender, bool shiny, int lang)
        {
            if (IsBuddy(species, form))
                form = 0;
            base.SetDex(species, bit, form, gender, shiny, lang);
        }

        private static bool IsBuddy(int species, int form) => (species == 25 && form == 8) || (species == 133 && form == 1);

        private void SetSizeData(PKM pkm)
        {
            int species = pkm.Species;
            int form = pkm.AltForm;
            if (!TryGetIndex(form, species, out int index))
                return;

            const int group = 0; // what differentiates the 4 groups?
            int offset = 0x3978 + (index * 6) + (group * 0x45C); //0x1170/4
            // todo?
        }

        private static bool TryGetIndex(int form, int species, out int index)
        {
            index = -1;
            if (form == 0 && species <= 151)
            {
                index = species - 1;
                return true;
            }
            for (int i = 0; i < SizeDexInfoTable.Length; i += 3)
            {
                if (SizeDexInfoTable[i] != species)
                    continue;
                if (SizeDexInfoTable[i + 1] != form)
                    continue;
                index = SizeDexInfoTable[i + 2];
                return true;
            }
            return false;
        }

        public static readonly ushort[] SizeDexInfoTable =
        {
            // spec, form, index
            808, 0, 151,
            809, 0, 152,

            003, 1, 153,
            006, 1, 154,
            006, 2, 155,
            009, 1, 156,
            015, 1, 157,
            018, 1, 158,
            019, 1, 159,
            020, 1, 160,
            026, 1, 161,
            027, 1, 162,
            028, 1, 163,
            037, 1, 164,
            038, 1, 165,
            050, 1, 166,
            051, 1, 167,
            052, 1, 168,
            053, 1, 169,
            065, 1, 170,
            074, 1, 171,
            075, 1, 172,
            076, 1, 173,
            080, 1, 174,
            088, 1, 175,
            089, 1, 176,
            094, 1, 177,
            103, 1, 178,
            105, 1, 179,
            115, 1, 180,
            127, 1, 181,
            130, 1, 182,
            142, 1, 183,
            150, 1, 184,
            150, 2, 185,
        };

        protected override bool GetSaneFormsToIterate(int species, out int formStart, out int formEnd, int formIn)
        {
            switch (species)
            {
                case 020: // Raticate
                case 105: // Marowak
                    formStart = 0;
                    formEnd = 1;
                    return true;

                default:
                    int count = SaveUtil.GetDexFormCountGG(species);
                    formStart = formEnd = 0;
                    return count < formIn;
            }
        }
    }
}