using System;

namespace BepInEx.Configuration;

/// <summary>
///     Specify the range of acceptable values for a setting.
/// </summary>
public class AcceptableValueRange<T> : AcceptableValueBase where T : IComparable
{
    /// <param name="minValue">Lowest acceptable value</param>
    /// <param name="maxValue">Highest acceptable value</param>
    public AcceptableValueRange(T minValue, T maxValue) : base(typeof(T))
    {
        if (maxValue == null)
            throw new ArgumentNullException(nameof(maxValue));
        if (minValue == null)
            throw new ArgumentNullException(nameof(minValue));
        if (minValue.CompareTo(maxValue) >= 0)
            throw new ArgumentException($"{nameof(minValue)} has to be lower than {nameof(maxValue)}");

        MinValue = minValue;
        MaxValue = maxValue;
    }

    /// <summary>
    ///     Lowest acceptable value
    /// </summary>
    public virtual T MinValue { get; }

    /// <summary>
    ///     Highest acceptable value
    /// </summary>
    public virtual T MaxValue { get; }

    /// <inheritdoc />
    public override object Clamp(object value)
    {
        if (MinValue.CompareTo(value) > 0)
            return MinValue;

        if (MaxValue.CompareTo(value) < 0)
            return MaxValue;

        return value;
    }

    /// <inheritdoc />
    public override bool IsValid(object value) => MinValue.CompareTo(value) <= 0 && MaxValue.CompareTo(value) >= 0;

    /// <inheritdoc />
    public override string ToDescriptionString() => $"# Acceptable value range: From {MinValue} to {MaxValue}";
}
