//-----------------------------------------------------------------------------
// 
//      Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
//
//      Licensed under the Apache License, Version 2.0 (the "License").
//      You may not use this file except in compliance with the License.
//      A copy of the License is located at
//
//      http://aws.amazon.com/apache2.0
//
//      or in the "license" file accompanying this file. This file is distributed
//      on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
//      express or implied. See the License for the specific language governing
//      permissions and limitations under the License.
// 
//-----------------------------------------------------------------------------
using System;
using System.Globalization;
using System.Linq;
using System.Threading;
namespace Amazon.XRay.Recorder.Core.Internal.Utils
{
    /// 
    /// An thread safe wrapper for System.Random
    /// 
    public static class ThreadSafeRandom
    {
        private static readonly Random _global = new Random();
        private static readonly ThreadLocal _local = new ThreadLocal(() =>
        {
            int seed;
            lock (_global)
            {
                seed = _global.Next();
            }
            return new Random(seed);
        });
        /// 
        /// Generate a random hex number
        /// 
        /// Digits of the hex number
        /// The generated hex number
        public static string GenerateHexNumber(int digits)
        {
            if (digits < 0)
            {
                throw new ArgumentException("Length can't be a negative number.", nameof(digits));
            }
            byte[] bytes = new byte[digits / 2];
            ThreadSafeRandom.NextBytes(bytes);
            string hexNumber = string.Concat(bytes.Select(x => x.ToString("x2", CultureInfo.InvariantCulture)).ToArray());
            if (digits % 2 != 0)
            {
                hexNumber += ThreadSafeRandom.Next(16).ToString("x", CultureInfo.InvariantCulture);
            }
            return hexNumber;
        }
        /// 
        /// Thread safe version of System.Random.NextDouble().
        /// Returns a random floating-point number that is greater than or equal to 0.0, and less than 1.0.
        /// 
        /// A double-precision floating point number that is greater than or equal to 0.0, and less than 1.0.
        public static double NextDouble()
        {
            return _local.Value.NextDouble();
        }
        /// 
        /// Fills the elements of a specified array of bytes with random numbers
        /// 
        /// An array of bytes to contain random numbers
        private static void NextBytes(byte[] buffer)
        {
            _local.Value.NextBytes(buffer);
        }
        /// 
        /// Returns a non-negative random integer that is less than the specified maximum
        /// 
        /// Max value of the random integer
        /// A 32-bit signed integer that is greater than or equal to 0, and less than maxValue
        private static int Next(int maxValue)
        {
            return _local.Value.Next(maxValue);
        }
    }
}