#ifndef _DERANDOM_HPP
#define _DERANDOM_HPP
/*-------------------------------------------------------------------------
 * drawElements C++ Base Library
 * -----------------------------
 *
 * Copyright 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License 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.
 *
 *//*!
 * \file
 * \brief Random number generator utilities.
 *//*--------------------------------------------------------------------*/

#include "deDefs.hpp"
#include "deRandom.h"

#include <iterator>		// std::distance()
#include <algorithm>	// std::swap()

namespace de
{

//! Random self-test - compare returned values against hard-coded values.
void Random_selfTest (void);

class Random
{
public:
					Random				(deUint32 seed)	{ deRandom_init(&m_rnd, seed);					}
					~Random				(void)			{}

	float			getFloat			(void)			{ return deRandom_getFloat(&m_rnd);				}
	double			getDouble			(void)			{ return deRandom_getDouble(&m_rnd);			}
	bool			getBool				(void)			{ return deRandom_getBool(&m_rnd) == DE_TRUE;	}

	float			getFloat			(float min, float max);
	double			getDouble			(double min, double max);
	int				getInt				(int min, int max);

	deUint64		getUint64			(void)			{ deUint32 upper = getUint32(); return (deUint64)upper << 32ull | (deUint64)getUint32(); }
	deUint32		getUint32			(void)			{ return deRandom_getUint32(&m_rnd);			}
	deUint16		getUint16			(void)			{ return (deUint16)deRandom_getUint32(&m_rnd);	}
	deUint8			getUint8			(void)			{ return (deUint8)deRandom_getUint32(&m_rnd);	}

	template <class InputIter, class OutputIter>
	void			choose				(InputIter first, InputIter last, OutputIter result, int numItems);

	template <typename T, class InputIter>
	T				choose				(InputIter first, InputIter last);

	// \note Weights must be floats
	template <typename T, class InputIter, class WeightIter>
	T				chooseWeighted		(InputIter first, InputIter last, WeightIter weight);

	template <class Iterator>
	void			shuffle				(Iterator first, Iterator last);

	bool			operator==			(const Random& other) const;
	bool			operator!=			(const Random& other) const;

private:
	deRandom		m_rnd;
} DE_WARN_UNUSED_TYPE;

// Inline implementations

inline float Random::getFloat (float min, float max)
{
	DE_ASSERT(min <= max);
	return min + (max-min)*getFloat();
}

inline double Random::getDouble (double min, double max)
{
	DE_ASSERT(min <= max);
	return min + (max-min)*getDouble();
}

inline int Random::getInt (int min, int max)
{
	DE_ASSERT(min <= max);
	if (min == (int)0x80000000 && max == (int)0x7fffffff)
		return (int)getUint32();
	else
		return min + (int)(getUint32() % (deUint32)(max-min+1));
}

// Template implementations

template <class InputIter, class OutputIter>
void Random::choose (InputIter first, InputIter last, OutputIter result, int numItems)
{
	// Algorithm: Reservoir sampling
	// http://en.wikipedia.org/wiki/Reservoir_sampling
	// \note Will not work for suffling an array. Use suffle() instead.

	int ndx;
	for (ndx = 0; first != last; ++first, ++ndx)
	{
		if (ndx < numItems)
			*(result + ndx) = *first;
		else
		{
			int r = getInt(0, ndx);
			if (r < numItems)
				*(result + r) = *first;
		}
	}

	DE_ASSERT(ndx >= numItems);
}

template <typename T, class InputIter>
T Random::choose (InputIter first, InputIter last)
{
	T val = T();
	DE_ASSERT(first != last);
	choose(first, last, &val, 1);
	return val;
}

template <typename T, class InputIter, class WeightIter>
T Random::chooseWeighted (InputIter first, InputIter last, WeightIter weight)
{
	// Compute weight sum
	float	weightSum	= 0.0f;
	int		ndx;
	for (ndx = 0; (first + ndx) != last; ndx++)
		weightSum += *(weight + ndx);

	// Random point in 0..weightSum
	float p = getFloat(0.0f, weightSum);

	// Find item in range
	InputIter	lastNonZero	= last;
	float		curWeight	= 0.0f;
	for (ndx = 0; (first + ndx) != last; ndx++)
	{
		float w = *(weight + ndx);

		curWeight += w;

		if (p < curWeight)
			return *(first + ndx);
		else if (w > 0.0f)
			lastNonZero = first + ndx;
	}

	DE_ASSERT(lastNonZero != last);
	return *lastNonZero;
}

template <class Iterator>
void Random::shuffle (Iterator first, Iterator last)
{
	using std::swap;

	// Fisher-Yates suffle
	int numItems = (int)std::distance(first, last);

	for (int i = numItems-1; i >= 1; i--)
	{
		int j = getInt(0, i);
		swap(*(first + i), *(first + j));
	}
}

template<typename T>	T			randomScalar	(de::Random& rnd, T minValue, T maxValue);
template<> inline		float		randomScalar	(de::Random& rnd, float minValue, float maxValue)		{ return rnd.getFloat(minValue, maxValue); }
template<> inline		deInt32		randomScalar	(de::Random& rnd, deInt32 minValue, deInt32 maxValue)	{ return rnd.getInt(minValue, maxValue); }
template<> inline		deUint32	randomScalar	(de::Random& rnd, deUint32 minValue, deUint32 maxValue)	{ return minValue + rnd.getUint32() % (maxValue - minValue + 1); }

} // de

#endif // _DERANDOM_HPP
