/*-------------------------------------------------------------------------
 * 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 Shader Class.
 *//*--------------------------------------------------------------------*/

#include "rsgShader.hpp"

using std::vector;

namespace rsg
{

namespace
{

template <typename T>
void deleteVectorElements (std::vector<T*>& vec)
{
	for (typename std::vector<T*>::iterator i = vec.begin(); i != vec.end(); i++)
		delete *i;
	vec.clear();
}

} // anonymous

Function::Function (void)
{
}

Function::Function (const char* name)
	: m_name(name)
{
}

Function::~Function (void)
{
	deleteVectorElements(m_parameters);
}

ShaderInput::ShaderInput (const Variable* variable, ConstValueRangeAccess valueRange)
	: m_variable	(variable)
	, m_min			(variable->getType().getScalarSize())
	, m_max			(variable->getType().getScalarSize())
{
	ValueAccess(variable->getType(), &m_min[0]) = valueRange.getMin().value();
	ValueAccess(variable->getType(), &m_max[0]) = valueRange.getMax().value();
}

Shader::Shader (Type type)
	: m_type			(type)
	, m_mainFunction	("main")
{
}

Shader::~Shader (void)
{
	deleteVectorElements(m_functions);
	deleteVectorElements(m_globalStatements);
	deleteVectorElements(m_inputs);
	deleteVectorElements(m_uniforms);
}

void Shader::getOutputs (vector<const Variable*>& outputs) const
{
	outputs.clear();
	const vector<Variable*>& globalVars = m_globalScope.getDeclaredVariables();
	for (vector<Variable*>::const_iterator i = globalVars.begin(); i != globalVars.end(); i++)
	{
		const Variable* var = *i;
		if (var->getStorage() == Variable::STORAGE_SHADER_OUT)
			outputs.push_back(var);
	}
}

void Shader::tokenize (GeneratorState& state, TokenStream& str) const
{
	// Add default precision for float in fragment shaders \todo [pyry] Proper precision handling
	if (state.getShader().getType() == Shader::TYPE_FRAGMENT)
		str << Token::PRECISION << Token::MEDIUM_PRECISION << Token::FLOAT << Token::SEMICOLON << Token::NEWLINE;

	// Tokenize global declaration statements
	for (int ndx = (int)m_globalStatements.size()-1; ndx >= 0; ndx--)
		m_globalStatements[ndx]->tokenize(state, str);

	// Tokenize all functions
	for (int ndx = (int)m_functions.size()-1; ndx >= 0; ndx--)
	{
		str << Token::NEWLINE;
		m_functions[ndx]->tokenize(state, str);
	}

	// Tokenize main
	str << Token::NEWLINE;
	m_mainFunction.tokenize(state, str);
}

void Shader::execute (ExecutionContext& execCtx) const
{
	// Execute global statements (declarations)
	for (vector<Statement*>::const_reverse_iterator i = m_globalStatements.rbegin(); i != m_globalStatements.rend(); i++)
		(*i)->execute(execCtx);

	// \todo [2011-03-08 pyry] Proper function calls
	m_mainFunction.getBody().execute(execCtx);
}

void Function::tokenize (GeneratorState& state, TokenStream& str) const
{
	// Return type
	m_returnType.tokenizeShortType(str);

	// Function name
	DE_ASSERT(m_name != "");
	str << Token(m_name.c_str());

	// Parameters
	str << Token::LEFT_PAREN;

	for (vector<Variable*>::const_iterator i = m_parameters.begin(); i != m_parameters.end(); i++)
	{
		if (i != m_parameters.begin())
			str << Token::COMMA;
		(*i)->tokenizeDeclaration(state, str);
	}

	str << Token::RIGHT_PAREN << Token::NEWLINE;

	// Tokenize body
	m_functionBlock.tokenize(state, str);
}

} // rsg
