/*-------------------------------------------------------------------------
 * drawElements Quality Program Random Shader Generator
 * ----------------------------------------------------
 *
 * 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 Utilities.
 *//*--------------------------------------------------------------------*/

#include "rsgUtils.hpp"

#include <set>
#include <string>

using std::set;
using std::string;
using std::vector;

namespace rsg
{

void addNewUniforms (vector<const ShaderInput*>& uniforms, set<string>& addedUniforms, const Shader& shader)
{
	const vector<ShaderInput*>& shaderUniforms = shader.getUniforms();
	for (vector<ShaderInput*>::const_iterator i = shaderUniforms.begin(); i != shaderUniforms.end(); i++)
	{
		const ShaderInput* uniform = *i;
		if (addedUniforms.find(uniform->getVariable()->getName()) == addedUniforms.end())
		{
			addedUniforms.insert(uniform->getVariable()->getName());
			uniforms.push_back(uniform);
		}
	}
}

void computeUnifiedUniforms (const Shader& vertexShader, const Shader& fragmentShader, std::vector<const ShaderInput*>& uniforms)
{
	set<string> addedUniforms;
	addNewUniforms(uniforms, addedUniforms, vertexShader);
	addNewUniforms(uniforms, addedUniforms, fragmentShader);
}

void computeRandomValue (de::Random& rnd, ValueAccess dst, ConstValueRangeAccess valueRange)
{
	const VariableType& type = dst.getType();

	switch (type.getBaseType())
	{
		case VariableType::TYPE_FLOAT:
			for (int ndx = 0; ndx < type.getNumElements(); ndx++)
			{
				const float quantizeStep = 1.0f/8.0f;
				float minVal = valueRange.component(ndx).getMin().asFloat();
				float maxVal = valueRange.component(ndx).getMax().asFloat();
				dst.component(ndx).asFloat() = getQuantizedFloat(rnd, minVal, maxVal, quantizeStep);
			}
			break;

		case VariableType::TYPE_BOOL:
			for (int ndx = 0; ndx < type.getNumElements(); ndx++)
			{
				int minVal = valueRange.component(ndx).getMin().asBool() ? 1 : 0;
				int maxVal = valueRange.component(ndx).getMin().asBool() ? 1 : 0;
				dst.component(ndx).asBool() = rnd.getInt(minVal, maxVal) == 1;
			}
			break;

		case VariableType::TYPE_INT:
		case VariableType::TYPE_SAMPLER_2D:
		case VariableType::TYPE_SAMPLER_CUBE:
			for (int ndx = 0; ndx < type.getNumElements(); ndx++)
			{
				int	minVal = valueRange.component(ndx).getMin().asInt();
				int maxVal = valueRange.component(ndx).getMax().asInt();
				dst.component(ndx).asInt() = rnd.getInt(minVal, maxVal);
			}
			break;

		case VariableType::TYPE_ARRAY:
		{
			int numElements = type.getNumElements();
			for (int ndx = 0; ndx < numElements; ndx++)
				computeRandomValue(rnd, dst.arrayElement(ndx), valueRange.arrayElement(ndx));
			break;
		}

		case VariableType::TYPE_STRUCT:
		{
			int numMembers = (int)type.getMembers().size();
			for (int ndx = 0; ndx < numMembers; ndx++)
				computeRandomValue(rnd, dst.member(ndx), valueRange.member(ndx));
			break;
		}

		default:
			TCU_FAIL("Invalid type");
	}
}

void computeUniformValues (de::Random& rnd, std::vector<VariableValue>& values, const std::vector<const ShaderInput*>& uniforms)
{
	DE_ASSERT(values.empty());
	for (vector<const ShaderInput*>::const_iterator i = uniforms.begin(); i != uniforms.end(); i++)
	{
		const ShaderInput* uniform = *i;
		values.push_back(VariableValue(uniform->getVariable()));
		computeRandomValue(rnd, values[values.size()-1].getValue(), uniform->getValueRange());
	}
}

bool isUndefinedValueRange (ConstValueRangeAccess valueRange)
{
	switch (valueRange.getType().getBaseType())
	{
		case VariableType::TYPE_FLOAT:
		case VariableType::TYPE_INT:
		{
			bool	isFloat	= valueRange.getType().getBaseType() == VariableType::TYPE_FLOAT;
			Scalar	infMin	= isFloat ? Scalar::min<float>() : Scalar::min<int>();
			Scalar	infMax	= isFloat ? Scalar::max<float>() : Scalar::max<int>();

			for (int ndx = 0; ndx < valueRange.getType().getNumElements(); ndx++)
			{
				if (valueRange.getMin().component(ndx).asScalar() != infMin ||
					valueRange.getMax().component(ndx).asScalar() != infMax)
					return false;
			}
			return true;
		}

		case VariableType::TYPE_BOOL:
			return false;

		default:
			TCU_FAIL("Unsupported type");
	}
}

VariableType computeRandomType (GeneratorState& state, int maxScalars)
{
	DE_ASSERT(maxScalars >= 1);

	static const VariableType::Type baseTypes[] =
	{
		VariableType::TYPE_BOOL,
		VariableType::TYPE_INT,
		VariableType::TYPE_FLOAT
		// \todo [pyry] Other types
	};

	VariableType::Type baseType = VariableType::TYPE_LAST;
	state.getRandom().choose(baseTypes, baseTypes + DE_LENGTH_OF_ARRAY(baseTypes), &baseType, 1);

	switch (baseType)
	{
		case VariableType::TYPE_BOOL:
		case VariableType::TYPE_INT:
		case VariableType::TYPE_FLOAT:
		{
			const int minVecLength = 1;
			const int maxVecLength = 4;
			return VariableType(baseType, state.getRandom().getInt(minVecLength, de::min(maxScalars, maxVecLength)));
		}

		default:
			DE_ASSERT(DE_FALSE);
			throw Exception("computeRandomType(): Unsupported type");
	}
}

void computeRandomValueRange (GeneratorState& state, ValueRangeAccess valueRange)
{
	const VariableType&	type	= valueRange.getType();
	de::Random&			rnd		= state.getRandom();

	switch (type.getBaseType())
	{
		case VariableType::TYPE_BOOL:
			for (int ndx = 0; ndx < type.getNumElements(); ndx++)
			{
				bool minVal = rnd.getBool();
				bool maxVal = minVal ? true : rnd.getBool();
				valueRange.getMin().component(ndx).asBool() = minVal;
				valueRange.getMax().component(ndx).asBool() = maxVal;
			}
			break;

		case VariableType::TYPE_INT:
			for (int ndx = 0; ndx < type.getNumElements(); ndx++)
			{
				const int minIntVal		= -16;
				const int maxIntVal		=  16;
				const int maxRangeLen	= maxIntVal - minIntVal;

				int rangeLen	= rnd.getInt(0, maxRangeLen);
				int minVal		= minIntVal + rnd.getInt(0, maxRangeLen-rangeLen);
				int maxVal		= minVal + rangeLen;

				valueRange.getMin().component(ndx).asInt() = minVal;
				valueRange.getMax().component(ndx).asInt() = maxVal;
			}
			break;

		case VariableType::TYPE_FLOAT:
			for (int ndx = 0; ndx < type.getNumElements(); ndx++)
			{
				const float step			= 0.1f;
				const int	maxSteps		= 320;
				const float minFloatVal		= -16.0f;

				int rangeLen	= rnd.getInt(0, maxSteps);
				int minStep		= rnd.getInt(0, maxSteps-rangeLen);

				float minVal	= minFloatVal + step*minStep;
				float maxVal	= minVal + step*rangeLen;

				valueRange.getMin().component(ndx).asFloat() = minVal;
				valueRange.getMax().component(ndx).asFloat() = maxVal;
			}
			break;

		default:
			DE_ASSERT(DE_FALSE);
			throw Exception("computeRandomValueRange(): Unsupported type");
	}
}

int getTypeConstructorDepth (const VariableType& type)
{
	switch (type.getBaseType())
	{
		case VariableType::TYPE_STRUCT:
		{
			const vector<VariableType::Member>& members		= type.getMembers();
			int									maxDepth	= 0;
			for (vector<VariableType::Member>::const_iterator i = members.begin(); i != members.end(); i++)
			{
				const VariableType&	memberType	= i->getType();
				int					depth		= 0;
				switch (memberType.getBaseType())
				{
					case VariableType::TYPE_STRUCT:
						depth = getTypeConstructorDepth(memberType);
						break;

					case VariableType::TYPE_BOOL:
					case VariableType::TYPE_FLOAT:
					case VariableType::TYPE_INT:
						depth = memberType.getNumElements() == 1 ? 1 : 2;
						break;

					default:
						DE_ASSERT(DE_FALSE);
						break;
				}

				maxDepth = de::max(maxDepth, depth);
			}
			return maxDepth + 1;
		}

		case VariableType::TYPE_BOOL:
		case VariableType::TYPE_FLOAT:
		case VariableType::TYPE_INT:
			return 2; // One node for ctor, another for value

		default:
			DE_ASSERT(DE_FALSE);
			return 0;
	}
}

int getConservativeValueExprDepth (const GeneratorState& state, ConstValueRangeAccess valueRange)
{
	// \todo [2011-03-22 pyry] Do a look-up into variable manager?
	DE_UNREF(state);
	return getTypeConstructorDepth(valueRange.getType());
}

static float computeRangeLengthSum (ConstValueRangeAccess valueRange)
{
	const VariableType&	type		= valueRange.getType();
	float				rangeLength	= 0.0f;

	switch (type.getBaseType())
	{
		case VariableType::TYPE_FLOAT:
			for (int ndx = 0; ndx < type.getNumElements(); ndx++)
			{
				float minVal = valueRange.component(ndx).getMin().asFloat();
				float maxVal = valueRange.component(ndx).getMax().asFloat();
				rangeLength += maxVal - minVal;
			}
			break;

		case VariableType::TYPE_BOOL:
			for (int ndx = 0; ndx < type.getNumElements(); ndx++)
			{
				int minVal = valueRange.component(ndx).getMin().asBool() ? 1 : 0;
				int maxVal = valueRange.component(ndx).getMin().asBool() ? 1 : 0;
				rangeLength += (float)(maxVal - minVal);
			}
			break;

		case VariableType::TYPE_INT:
		case VariableType::TYPE_SAMPLER_2D:
		case VariableType::TYPE_SAMPLER_CUBE:
			for (int ndx = 0; ndx < type.getNumElements(); ndx++)
			{
				int	minVal = valueRange.component(ndx).getMin().asInt();
				int maxVal = valueRange.component(ndx).getMax().asInt();
				rangeLength += (float)(maxVal - minVal);
			}
			break;

		case VariableType::TYPE_ARRAY:
		{
			int numElements = type.getNumElements();
			for (int ndx = 0; ndx < numElements; ndx++)
				rangeLength += computeRangeLengthSum(valueRange.arrayElement(ndx));
			break;
		}

		case VariableType::TYPE_STRUCT:
		{
			int numMembers = (int)type.getMembers().size();
			for (int ndx = 0; ndx < numMembers; ndx++)
				rangeLength += computeRangeLengthSum(valueRange.member(ndx));
			break;
		}

		default:
			TCU_FAIL("Invalid type");
	}

	return rangeLength;
}

float computeDynamicRangeWeight (ConstValueRangeAccess valueRange)
{
	const VariableType& type		= valueRange.getType();
	float				rangeLenSum	= computeRangeLengthSum(valueRange);
	int					numScalars	= type.getScalarSize();

	return rangeLenSum / (float)numScalars;
}

} // rsg
