using System;
using UnityEngine;

namespace pdinklag
{
    [Serializable]
    public struct MinMaxInt
    {
        public static readonly MinMaxInt All = new(int.MinValue, int.MaxValue);

        public int Min;
        public int Max;

        /// <summary>
        /// The difference between min and max.
        /// </summary>
        public int Delta => Max - Min;

        /// <summary>
        /// Constructs a range.
        /// </summary>
        /// <param name="min">the minimum value</param>
        /// <param name="max">the maximum value</param>
        public MinMaxInt(int min, int max)
        {
            Min = min;
            Max = max;
        }

        /// <summary>
        /// Clamps a value to the defined range.
        /// </summary>
        /// <param name="x">the value to clamp</param>
        /// <returns></returns>
        public int Clamp(int x) => Mathf.Clamp(x, Min, Max);

        /// <summary>
        /// Tests if a value is in the defined range.
        /// </summary>
        /// <param name="x">the value in question</param>
        /// <returns></returns>
        public bool Contains(int x) => x >= Min && x <= Max;

        /// <summary>
        /// Expands the range in both directions, i.e. subtracts it from the minimum and adds it from the maximum.
        /// </summary>
        /// <param name="amount">the amount of the expansion</param>
        /// <returns>the expanded range</returns>
        public MinMaxInt Expand(int amount) => new(Min - amount, Max + amount);

        /// <summary>
        /// Reduces the range in both directions, i.e. adds it to the minimum and removes it from the minimum.
        /// 
        /// Note that no checks are made ensuring <code>Max >= Min</code> after this operation.
        /// </summary>
        /// <param name="amount">the amount of the expansion</param>
        /// <returns>the expanded range</returns>
        public MinMaxInt Reduce(int amount) => Expand(-amount);

        /// <summary>
        /// Gets a random value in the defined range, EXCLUDING the maximum.
        /// </summary>
        /// <returns></returns>
        public int RandomExcludingMax() => UnityEngine.Random.Range(Min, Max);

        /// <summary>
        /// Gets a random value in the defined range, INCLUDING the maximum.
        /// </summary>
        /// <returns></returns>
        public int RandomIncludingMax() => UnityEngine.Random.Range(Min, Max + 1);
    }
}
