using System;

namespace JNGame.Math
{
    /// <summary>
    /// 伪随机序列计算器
    /// </summary>
    public partial class Random
    {
        /// <summary>
        /// 随机数种子
        /// </summary>
        public ulong randSeed = 1;

        /// <summary>
        /// 构造伪随机
        /// </summary>
        /// <param name="seed"></param>
        public Random(uint seed = 17)
        {
            randSeed = seed;
        }

        /// <summary>
        /// 返回[0, 4294967295)范围内的一个无符号整数
        /// </summary>
        /// <returns></returns>
        public uint Next()
        {
            randSeed = randSeed * 1103515245 + 36153;
            return (uint)(randSeed / 65536);
        }
        
        /// <summary>
        /// 返回[0, max)范围内的一个无符号整数
        /// </summary>
        /// <param name="max">随机范围最大值,产出的随机数不包括该值</param>
        /// <returns></returns>
        public uint Next(uint max)
        {
            return Next() % max;
        }

        /// <summary>
        /// 返回[0, max)范围内的一个有符号整数
        /// </summary>
        /// <param name="max">随机范围最大值,产出的随机数不包括该值</param>
        /// <returns></returns>
        public int Next(int max)
        {
            return (int)(Next() % max);
        }
        
        /// <summary>
        /// 返回[min, max)范围内的一个无符号整数
        /// </summary>
        /// <param name="min">随机范围最小值,产出的随机数包括该值</param>
        /// <param name="max">随机范围最大值,产出的随机数不包括该值</param>
        /// <returns></returns>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public uint Range(uint min, uint max)
        {
            if (min > max)
                throw new ArgumentOutOfRangeException("minValue",
                    string.Format("'{0}' cannot be greater than {1}.", min, max));

            uint num = max - min;
            return this.Next(num) + min;
        }

        /// <summary>
        /// 返回[min, max)范围内的一个有符号整数
        /// </summary>
        /// <param name="min">随机范围最小值,产出的随机数包括该值</param>
        /// <param name="max">随机范围最大值,产出的随机数不包括该值</param>
        /// <returns></returns>
        public int Range(int min, int max)
        {
            if (min >= max - 1)
                return min;
            int num = max - min;

            return this.Next(num) + min;
        }

        /// <summary>
        /// 返回[min, max)范围内的一个定点数
        /// </summary>
        /// <param name="min">随机范围最小值,产出的随机数包括该值</param>
        /// <param name="max">随机范围最大值,产出的随机数不包括该值</param>
        /// <returns></returns>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public LFloat Range(LFloat min, LFloat max)
        {
            if (min > max)
                throw new ArgumentOutOfRangeException("minValue",
                    string.Format("'{0}' cannot be greater than {1}.", min, max));

            uint num = (uint)(max.rawValue - min.rawValue);
            return new LFloat(true, Next(num) + min.rawValue);
        }
    }
#if false
    public class LRandom {
        private static Random _i = new Random(3274);
        public static LFloat value => _i.value;
        public static uint Next(){return _i.Next();}
        public static uint Next(uint max){return _i.Next(max);}
        public static int Next(int max){return _i.Next(max);}
        public static uint Range(uint min, uint max){return _i.Range(min, max);}
        public static int Range(int min, int max){return _i.Range(min, max);}
        public static LFloat Range(LFloat min, LFloat max){return _i.Range(min, max);}
    }
#endif
}