using System.Diagnostics.CodeAnalysis;
using PkmnLib.Static.Utils;

namespace PkmnLib.Static.Libraries;

/// <summary>
/// The library for all growth rates in the game.
/// </summary>
public interface IReadOnlyGrowthRateLibrary : IEnumerable<IGrowthRate>
{
    /// <summary>
    /// Tries to get a growth rate from the library. Returns false if the growth rate is not found.
    /// </summary>
    bool TryGet(StringKey key, [MaybeNullWhen(false)] out IGrowthRate value);

    /// <summary>
    /// Gets a random growth rate from the library. 
    /// </summary>
    IGrowthRate GetRandom(IRandom random);

    /// <summary>
    /// Gets the amount of growth rates in the library.
    /// </summary>
    int Count { get; }

    /// <summary>
    /// Whether the library is empty.
    /// </summary>
    bool IsEmpty { get; }

    /// <summary>
    /// Calculates the experience for a given growth key name and a certain level.
    /// </summary>
    uint CalculateExperience(StringKey key, LevelInt level);

    /// <summary>
    /// Calculates the level for a given growth key name and a certain experience.
    /// </summary>
    LevelInt CalculateLevel(StringKey key, uint experience);
}

/// <inheritdoc cref="IReadOnlyGrowthRateLibrary"/>
public class GrowthRateLibrary : DataLibrary<IGrowthRate>, IReadOnlyGrowthRateLibrary
{
    /// <inheritdoc />
    public uint CalculateExperience(StringKey key, LevelInt level)
    {
        if (!TryGet(key, out var growthRate))
        {
            throw new KeyNotFoundException($"Growth rate {key} not found.");
        }
        return growthRate.CalculateExperience(level);
    }

    /// <inheritdoc />
    public LevelInt CalculateLevel(StringKey key, uint experience)
    {
        if (!TryGet(key, out var growthRate))
        {
            throw new KeyNotFoundException($"Growth rate {key} not found.");
        }
        return growthRate.CalculateLevel(experience);
    }
}