using System.Collections.Immutable;
using PkmnLib.Static.Utils;

namespace PkmnLib.Static;

/// <summary>
/// An item category defines which bag slot items are stored in.
/// </summary>
public enum ItemCategory
{
    /// <summary>
    /// This is where most items should go.
    /// </summary>
    MiscItem,

    /// <summary>
    /// Pokeballs are used for capturing Pokémons.
    /// </summary>
    Pokeball,

    /// <summary>
    /// Medicine is used for healing HP, PP, and status effects.
    /// </summary>
    Medicine,

    /// <summary>
    /// Berry is used for all berries.
    /// </summary>
    Berry,

    /// <summary>
    /// TMHM is used for Technical and Hidden Machines.
    /// </summary>
    TmHm,

    /// <summary>
    /// Form Changer is used for items that change forms, such as mega stones.
    /// </summary>
    FormChanger,

    /// <summary>
    /// Key Items are single stored items, generally used for story progression.
    /// </summary>
    KeyItem,

    /// <summary>
    /// Mail is used for mail items.
    /// </summary>
    Mail,
}

/// <summary>
/// A battle item category defines how the item is categorized when in battle.
/// </summary>
public enum BattleItemCategory
{
    /// <summary>
    /// This item can't be used in battle.
    /// </summary>
    None,

    /// <summary>
    /// This item is used for healing Pokémon.
    /// </summary>
    Healing,

    /// <summary>
    /// This item is used for healing Pokémon from a status.
    /// </summary>
    StatusHealing,

    /// <summary>
    /// This item is used for capturing Pokémon.
    /// </summary>
    Pokeball,

    /// <summary>
    /// This item does not belong in above categories, but is still a battle item.
    /// </summary>
    MiscBattleItem,
}

/// <summary>
/// An item is an object which the player can pick up, keep in their Bag, and use in some manner.
/// </summary>
public interface IItem : INamedValue
{
    /// <summary>
    /// Which bag slot items are stored in.
    /// </summary>
    ItemCategory Category { get; }

    /// <summary>
    /// How the item is categorized when in battle.
    /// </summary>
    BattleItemCategory BattleCategory { get; }

    /// <summary>
    /// The buying value of the item.
    /// </summary>
    int Price { get; }

    /// <summary>
    /// A set of arbitrary flags that can be set on the item.
    /// </summary>
    ImmutableHashSet<StringKey> Flags { get; }

    /// <summary>
    /// Checks whether the item has a specific flag.
    /// </summary>
    /// <param name="key">The flag to check for.</param>
    /// <returns>True if the item has the flag, false otherwise.</returns>
    bool HasFlag(string key);
}

/// <inheritdoc />
public class ItemImpl : IItem
{
    /// <inheritdoc cref="ItemImpl"/>
    public ItemImpl(StringKey name, ItemCategory category, BattleItemCategory battleCategory, int price,
        IEnumerable<StringKey> flags)
    {
        Name = name;
        Category = category;
        BattleCategory = battleCategory;
        Price = price;
        Flags = [..flags];
    }

    /// <inheritdoc />
    public StringKey Name { get; }

    /// <inheritdoc />
    public ItemCategory Category { get; }

    /// <inheritdoc />
    public BattleItemCategory BattleCategory { get; }

    /// <inheritdoc />
    public int Price { get; }

    /// <inheritdoc />
    public ImmutableHashSet<StringKey> Flags { get; }

    /// <inheritdoc />
    public bool HasFlag(string key)
    {
        return Flags.Contains(key);
    }
}