using System;
using System.Collections.Generic;
namespace Chernobyl
{
    /// 
    /// A  type that produces deterministic values. This is useful for testing
    /// code that uses randomness.
    /// 
    public class NotRandom : Random
    {
        /// 
        /// Constructor.
        /// 
        /// The list of values to return when asked to produce random numbers.
        /// This list will be iterated through to produce the values.
        public NotRandom(IReadOnlyList values)
        {
            _values = values;
        }
        /// 
        public override int Next()
        {
            var value = _values[Increment()];
            return (int)value;
        }
        /// 
        public override int Next(int maxValue)
        {
            // Search our list an appropriate value.
            for (int i = 0; i < _values.Count; i++)
            {
                var value = _values[Increment()];
                if (value < maxValue)
                    return (int)value;
            }
            throw new ArgumentOutOfRangeException(nameof(maxValue), maxValue,
                "Unable to locate a value less than the max value provided.");
        }
        /// 
        public override int Next(int minValue, int maxValue)
        {
            minValue.Throw(nameof(minValue)).IfGreaterThanOrEqualTo(maxValue, nameof(maxValue));
            // Search our list an appropriate value.
            for (int i = 0; i < _values.Count; i++)
            {
                var value = _values[Increment()];
                if (minValue <= value && value < maxValue)
                    return (int)value;
            }
            throw new ArgumentOutOfRangeException(nameof(maxValue), maxValue,
                "Unable to locate a value greater than or equal to the min value  and less than the " +
                "max value provided.");
        }
        /// 
        public override void NextBytes(byte[] buffer)
        {
            // TODO: implement this when needed.
            throw new NotImplementedException();
        }
        /// 
        public override double NextDouble()
        {
            return Next() / 1.0;
        }
        /// 
        protected override double Sample()
        {
            // TODO: implement this when needed.
            throw new NotImplementedException();
        }
        /// 
        /// Returns and increments the current value.
        /// 
        /// The current value before being incremented.
        int Increment()
        {
            int current = _currentIndex;
            _currentIndex++;
            if (_values.Count <= _currentIndex)
                _currentIndex = 0;
            return current;
        }
        readonly IReadOnlyList _values;
        int _currentIndex;
    }
}