using PkmnLib.Static.Utils;

namespace PkmnLib.Static;

/// <summary>
/// A nature is an attribute on a Pokémon that modifies the effective base stats on a Pokémon. They
/// can have an increased statistic and a decreased statistic, or be neutral.
/// </summary>
public interface INature : INamedValue
{
    /// <summary>
    /// The stat that should receive the increased modifier.
    /// </summary>
    Statistic IncreasedStat { get; }

    /// <summary>
    /// The stat that should receive the decreased modifier.
    /// </summary>
    Statistic DecreasedStat { get; }

    /// <summary>
    /// The amount that the increased stat gets modified by.
    /// </summary>
    float IncreasedModifier { get; }

    /// <summary>
    /// The amount that the decreased stat gets modified by.
    /// </summary>
    float DecreasedModifier { get; }

    /// <summary>
    /// Calculates the modifier for a given stat. If it's the increased stat, returns the increased
    /// modifier, if it's the decreased stat, returns the decreased modifier. Otherwise returns 1.0.
    /// </summary>
    /// <param name="stat">The stat to calculate the modifier for.</param>
    /// <returns>The calculated modifier.</returns>
    float GetStatModifier(Statistic stat);

    /// <summary>
    /// Checks if two natures are equal.
    /// </summary>
    /// <param name="other">The other nature to compare to.</param>
    /// <returns>True if the natures are equal, false otherwise.</returns>
    bool Equals(INature other);
}

/// <inheritdoc />
public class Nature(
    StringKey name,
    Statistic increaseStat,
    Statistic decreaseStat,
    float increaseModifier,
    float decreaseModifier) : INature
{
    /// <inheritdoc />
    public StringKey Name { get; } = name;

    /// <inheritdoc />
    public Statistic IncreasedStat { get; } = increaseStat;

    /// <inheritdoc />
    public Statistic DecreasedStat { get; } = decreaseStat;

    /// <inheritdoc />
    public float IncreasedModifier { get; } = increaseModifier;

    /// <inheritdoc />
    public float DecreasedModifier { get; } = decreaseModifier;

    /// <inheritdoc />
    public float GetStatModifier(Statistic stat)
    {
        if (stat == IncreasedStat && stat != DecreasedStat)
            return IncreasedModifier;
        if (stat == DecreasedStat && stat != IncreasedStat)
            return DecreasedModifier;
        return 1.0f;
    }

    /// <inheritdoc />
    public bool Equals(INature? other) =>
        other is not null && StringComparer.InvariantCultureIgnoreCase.Equals(Name, other.Name);
}