using System;

namespace PKHeX.Core;

/// <summary>
/// Logic for modifying the Move Shop Record flags of a <see cref="PA8"/>.
/// </summary>
public static class MoveShopRecordApplicator
{
    public static void ClearMoveShopFlags(this IMoveShop8 shop)
    {
        var bits = shop.MoveShopPermitFlags;
        for (int i = 0; i < bits.Length; i++)
            shop.SetPurchasedRecordFlag(i, false);

        if (shop is IMoveShop8Mastery m)
            m.ClearMoveShopFlagsMastered();
    }

    public static void ClearMoveShopFlagsMastered(this IMoveShop8Mastery shop)
    {
        var bits = shop.MoveShopPermitFlags;
        for (int i = 0; i < bits.Length; i++)
            shop.SetMasteredRecordFlag(i, false);
    }

    public static void SetMoveShopFlags(this IMoveShop8Mastery shop, PKM pk)
    {
        Span<int> moves = stackalloc int[4];
        pk.GetMoves(moves);
        shop.SetMoveShopFlags(moves, pk);
    }

    public static void SetMoveShopFlags(this IMoveShop8Mastery shop, ReadOnlySpan<int> moves, PKM pk)
    {
        var index = PersonalTable.LA.GetFormIndex(pk.Species, pk.Form);
        var learn = Legal.LevelUpLA[index];
        var mastery = Legal.MasteryLA[index];
        var level = pk.CurrentLevel;

        shop.SetMoveShopFlags(moves, learn, mastery, level);
    }

    public static void SetMoveShopFlagsAll(this IMoveShop8Mastery shop, PKM pk)
    {
        var index = PersonalTable.LA.GetFormIndex(pk.Species, pk.Form);
        var learn = Legal.LevelUpLA[index];
        var mastery = Legal.MasteryLA[index];
        var level = pk.CurrentLevel;

        shop.SetMoveShopFlagsAll(learn, mastery, level);
    }

    public static void SetMoveShopFlagsAll(this IMoveShop8Mastery shop, Learnset learn, Learnset mastery, int level)
    {
        var possible = shop.MoveShopPermitIndexes;
        var permit = shop.MoveShopPermitFlags;
        for (int index = 0; index < possible.Length; index++)
        {
            var move = possible[index];
            var allowed = permit[index];
            if (!allowed)
                continue;

            SetMasteredFlag(shop, learn, mastery, level, index, move);
        }
    }

    public static void SetMoveShopFlags(this IMoveShop8Mastery shop, ReadOnlySpan<int> moves, Learnset learn, Learnset mastery, int level)
    {
        var possible = shop.MoveShopPermitIndexes;
        var permit = shop.MoveShopPermitFlags;
        foreach (var move in moves)
        {
            var index = possible.IndexOf((ushort)move);
            if (index == -1)
                continue;
            if (!permit[index])
                continue;
            SetMasteredFlag(shop, learn, mastery, level, index, move);
        }
    }

    public static void SetMasteredFlag(IMoveShop8Mastery shop, Learnset learn, Learnset mastery, int level, int index, int move)
    {
        if (shop.GetMasteredRecordFlag(index))
            return;

        if ((uint)learn.GetMoveLevel(move) > level) // Can't learn it yet; must purchase.
        {
            shop.SetPurchasedRecordFlag(index, true);
            shop.SetMasteredRecordFlag(index, true);
            return;
        }

        if (mastery.GetMoveLevel(move) < level) // Can't master it yet; must Seed of Mastery
            shop.SetMasteredRecordFlag(index, true);
    }
}
