/*-------------------------------------------------------------------------
 * 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 Statements.
 *//*--------------------------------------------------------------------*/

#include "rsgStatement.hpp"
#include "rsgExpressionGenerator.hpp"
#include "rsgUtils.hpp"

#include <typeinfo>

using std::vector;

namespace rsg
{

namespace
{

inline bool isCurrentTopStatementBlock (const GeneratorState& state)
{
	int stackDepth = state.getStatementDepth();
	return dynamic_cast<const BlockStatement*>(state.getStatementStackEntry(stackDepth-1)) != DE_NULL;
}

template <class T> float		getWeight	(const GeneratorState& state)	{ return T::getWeight(state);	}
template <class T> Statement*	create		(GeneratorState& state)			{ return new T(state);			}

struct StatementSpec
{
	float		(*getWeight)		(const GeneratorState& state);
	Statement*	(*create)			(GeneratorState& state);
};

const StatementSpec* chooseStatement (GeneratorState& state)
{
	static const StatementSpec statementSpecs[] =
	{
		{ getWeight<BlockStatement>,		create<BlockStatement>			},
		{ getWeight<ExpressionStatement>,	create<ExpressionStatement>		},
		{ getWeight<DeclarationStatement>,	create<DeclarationStatement>	},
		{ getWeight<ConditionalStatement>,	create<ConditionalStatement>	}
	};

	float weights[DE_LENGTH_OF_ARRAY(statementSpecs)];

	// Compute weights
	float sum = 0.0f;
	for (int ndx = 0; ndx < (int)DE_LENGTH_OF_ARRAY(statementSpecs); ndx++)
	{
		weights[ndx] = statementSpecs[ndx].getWeight(state);
		sum += weights[ndx];
	}

	DE_ASSERT(sum > 0.0f);

	// Random number in range
	float p = state.getRandom().getFloat(0.0f, sum);

	const StatementSpec* spec			= DE_NULL;
	const StatementSpec* lastNonZero	= DE_NULL;

	// Find element in that point
	sum = 0.0f;
	for (int ndx = 0; ndx < (int)DE_LENGTH_OF_ARRAY(statementSpecs); ndx++)
	{
		sum += weights[ndx];
		if (p < sum)
		{
			spec = &statementSpecs[ndx];
			break;
		}
		else if (weights[ndx] > 0.0f)
			lastNonZero = &statementSpecs[ndx];
	}

	if (!spec)
		spec = lastNonZero;

	return spec;
}

Statement* createStatement (GeneratorState& state)
{
	return chooseStatement(state)->create(state);
}

} // anonymous

Statement::Statement (void)
{
}

Statement::~Statement (void)
{
}

ExpressionStatement::ExpressionStatement (GeneratorState& state)
	: m_expression(DE_NULL)
{
	ExpressionGenerator generator(state);
	m_expression = generator.generate(ValueRange(VariableType(VariableType::TYPE_VOID)));
}

ExpressionStatement::~ExpressionStatement (void)
{
	delete m_expression;
}

float ExpressionStatement::getWeight (const GeneratorState& state)
{
	DE_UNREF(state);
	return 1.0f;
}

void ExpressionStatement::execute (ExecutionContext& execCtx) const
{
	m_expression->evaluate(execCtx);
}

BlockStatement::BlockStatement (GeneratorState& state)
{
	init(state);
}

void BlockStatement::init (GeneratorState& state)
{
	// Select number of children statements to construct
	m_numChildrenToCreate = state.getRandom().getInt(0, state.getShaderParameters().maxStatementsPerBlock);

	// Push scope
	state.getVariableManager().pushVariableScope(m_scope);
}

BlockStatement::~BlockStatement (void)
{
	for (vector<Statement*>::iterator i = m_children.begin(); i != m_children.end(); i++)
		delete *i;
	m_children.clear();
}

void BlockStatement::addChild (Statement* statement)
{
	try
	{
		m_children.push_back(statement);
	}
	catch (const std::exception&)
	{
		delete statement;
		throw;
	}
}

Statement* BlockStatement::createNextChild (GeneratorState& state)
{
	if ((int)m_children.size() < m_numChildrenToCreate)
	{
		// Select and create a new child
		Statement* child = createStatement(state);
		addChild(child);
		return child;
	}
	else
	{
		// Done, pop scope
		state.getVariableManager().popVariableScope();
		return DE_NULL;
	}
}

float BlockStatement::getWeight (const GeneratorState& state)
{
	if (state.getStatementDepth()+1 < state.getShaderParameters().maxStatementDepth)
	{
		if (isCurrentTopStatementBlock(state))
			return 0.2f; // Low probability for anonymous blocks.
		else
			return 1.0f;
	}
	else
		return 0.0f;
}

void BlockStatement::tokenize (GeneratorState& state, TokenStream& str) const
{
	str << Token::LEFT_BRACE << Token::NEWLINE << Token::INDENT_INC;

	for (vector<Statement*>::const_reverse_iterator i = m_children.rbegin(); i != m_children.rend(); i++)
		(*i)->tokenize(state, str);

	str << Token::INDENT_DEC << Token::RIGHT_BRACE << Token::NEWLINE;
}

void BlockStatement::execute (ExecutionContext& execCtx) const
{
	for (vector<Statement*>::const_reverse_iterator i = m_children.rbegin(); i != m_children.rend(); i++)
		(*i)->execute(execCtx);
}

void ExpressionStatement::tokenize (GeneratorState& state, TokenStream& str) const
{
	DE_ASSERT(m_expression);
	m_expression->tokenize(state, str);
	str << Token::SEMICOLON << Token::NEWLINE;
}

namespace
{

inline bool canDeclareVariable (const Variable* variable)
{
	return variable->getStorage() == Variable::STORAGE_LOCAL;
}

bool hasDeclarableVars (const VariableManager& varMgr)
{
	const vector<Variable*>& liveVars = varMgr.getLiveVariables();
	for (vector<Variable*>::const_iterator i = liveVars.begin(); i != liveVars.end(); i++)
	{
		if (canDeclareVariable(*i))
			return true;
	}
	return false;
}

} // anonymous

DeclarationStatement::DeclarationStatement (GeneratorState& state, Variable* variable)
	: m_variable	(DE_NULL)
	, m_expression	(DE_NULL)
{
	if (variable == DE_NULL)
	{
		// Choose random
		// \todo [2011-02-03 pyry] Allocate a new here?
		// \todo [2011-05-26 pyry] Weights?
		const vector<Variable*>&	liveVars = state.getVariableManager().getLiveVariables();
		vector<Variable*>			candidates;

		for (vector<Variable*>::const_iterator i = liveVars.begin(); i != liveVars.end(); i++)
		{
			if (canDeclareVariable(*i))
				candidates.push_back(*i);
		}

		variable = state.getRandom().choose<Variable*>(candidates.begin(), candidates.end());
	}

	DE_ASSERT(variable);
	m_variable = variable;

	const ValueEntry* value = state.getVariableManager().getValue(variable);

	bool createInitializer = false;

	switch (m_variable->getStorage())
	{
		case Variable::STORAGE_CONST:
			DE_ASSERT(value);
			createInitializer = true;
			break;

		case Variable::STORAGE_LOCAL:
			// \note Currently booleans are always treated as not having undefined range and thus
			//       initializer is always created.
			createInitializer = value && !isUndefinedValueRange(value->getValueRange());
			break;

		default:
			createInitializer = false;
			break;
	}

	if (createInitializer)
	{
		ExpressionGenerator generator(state);

		// Take copy of value range for generating initializer expression
		ValueRange valueRange = value->getValueRange();

		// Declare (removes value entry)
		state.getVariableManager().declareVariable(variable);

		bool isConst = m_variable->getStorage() == Variable::STORAGE_CONST;

		if (isConst)
			state.pushExpressionFlags(state.getExpressionFlags() | CONST_EXPR);

		m_expression = generator.generate(valueRange, 1);

		if (isConst)
			state.popExpressionFlags();
	}
	else
		state.getVariableManager().declareVariable(variable);
}

DeclarationStatement::~DeclarationStatement (void)
{
	delete m_expression;
}

float DeclarationStatement::getWeight (const GeneratorState& state)
{
	if (!hasDeclarableVars(state.getVariableManager()))
		return 0.0f;

	if (!isCurrentTopStatementBlock(state))
		return 0.0f;

	return state.getProgramParameters().declarationStatementBaseWeight;
}

void DeclarationStatement::tokenize (GeneratorState& state, TokenStream& str) const
{
	m_variable->tokenizeDeclaration(state, str);

	if (m_expression)
	{
		str << Token::EQUAL;
		m_expression->tokenize(state, str);
	}

	str << Token::SEMICOLON << Token::NEWLINE;
}

void DeclarationStatement::execute (ExecutionContext& execCtx) const
{
	if (m_expression)
	{
		m_expression->evaluate(execCtx);
		execCtx.getValue(m_variable) = m_expression->getValue().value();
	}
}

ConditionalStatement::ConditionalStatement (GeneratorState&)
	: m_condition		(DE_NULL)
	, m_trueStatement	(DE_NULL)
	, m_falseStatement	(DE_NULL)
{
}

ConditionalStatement::~ConditionalStatement (void)
{
	delete m_condition;
	delete m_trueStatement;
	delete m_falseStatement;
}

bool ConditionalStatement::isElseBlockRequired (const GeneratorState& state) const
{
	// If parent is conditional statement with else block and this is the true statement,
	// else block must be generated or otherwise parent "else" will end up parsed as else statement for this if.
	const ConditionalStatement*	curChild	= this;
	int							curStackNdx	= state.getStatementDepth()-2;

	while (curStackNdx >= 0)
	{
		const ConditionalStatement* curParent = dynamic_cast<const ConditionalStatement*>(state.getStatementStackEntry(curStackNdx));

		if (!curParent)
			break; // Not a conditional statement - can end search here.

		if (curChild == curParent->m_trueStatement && curParent->m_falseStatement)
			return true; // Else block is mandatory.

		// Continue search.
		curChild	 = curParent;
		curStackNdx	-= 1;
	}

	return false;
}

Statement* ConditionalStatement::createNextChild (GeneratorState& state)
{
	// If has neither true or false statements, choose randomly whether to create false block.
	if (!m_falseStatement && !m_trueStatement && (isElseBlockRequired(state) || state.getRandom().getBool()))
	{
		// Construct false statement
		state.getVariableManager().pushValueScope(m_conditionalScope);
		m_falseStatement = createStatement(state);

		return m_falseStatement;
	}
	else if (!m_trueStatement)
	{
		if (m_falseStatement)
		{
			// Pop previous value scope.
			state.getVariableManager().popValueScope();
			m_conditionalScope.clear();
		}

		// Construct true statement
		state.getVariableManager().pushValueScope(m_conditionalScope);
		m_trueStatement = createStatement(state);

		return m_trueStatement;
	}
	else
	{
		// Pop conditional scope.
		state.getVariableManager().popValueScope();
		m_conditionalScope.clear();

		// Create condition
		DE_ASSERT(!m_condition);

		ExpressionGenerator generator(state);

		ValueRange range = ValueRange(VariableType::getScalarType(VariableType::TYPE_BOOL));
		range.getMin().asBool() = false;
		range.getMax().asBool() = true;

		m_condition = generator.generate(range, 1);

		return DE_NULL; // Done with this statement
	}
}

namespace
{

bool isBlockStatement (const Statement* statement)
{
	return dynamic_cast<const BlockStatement*>(statement) != DE_NULL;
}

bool isConditionalStatement (const Statement* statement)
{
	return dynamic_cast<const ConditionalStatement*>(statement) != DE_NULL;
}

} // anonymous

void ConditionalStatement::tokenize (GeneratorState& state, TokenStream& str) const
{
	DE_ASSERT(m_condition && m_trueStatement);

	// if (condition)
	str << Token::IF << Token::LEFT_PAREN;
	m_condition->tokenize(state, str);
	str << Token::RIGHT_PAREN << Token::NEWLINE;

	// Statement executed if true
	if (!isBlockStatement(m_trueStatement))
	{
		str << Token::INDENT_INC;
		m_trueStatement->tokenize(state, str);
		str << Token::INDENT_DEC;
	}
	else
		m_trueStatement->tokenize(state, str);

	if (m_falseStatement)
	{
		str << Token::ELSE;

		if (isConditionalStatement(m_falseStatement))
		{
			m_falseStatement->tokenize(state, str);
		}
		else if (isBlockStatement(m_falseStatement))
		{
			str << Token::NEWLINE;
			m_falseStatement->tokenize(state, str);
		}
		else
		{
			str << Token::NEWLINE << Token::INDENT_INC;
			m_falseStatement->tokenize(state, str);
			str << Token::INDENT_DEC;
		}
	}
}

void ConditionalStatement::execute (ExecutionContext& execCtx) const
{
	// Evaluate condition
	m_condition->evaluate(execCtx);

	ExecMaskStorage	maskStorage; // Value might change when we are evaluating true block so we have to take a copy.
	ExecValueAccess	trueMask	= maskStorage.getValue();

	trueMask = m_condition->getValue().value();

	// And mask, execute true statement and pop
	execCtx.andExecutionMask(trueMask);
	m_trueStatement->execute(execCtx);
	execCtx.popExecutionMask();

	if (m_falseStatement)
	{
		// Construct negated mask, execute false statement and pop
		ExecMaskStorage tmp;
		ExecValueAccess	falseMask = tmp.getValue();

		for (int i = 0; i < EXEC_VEC_WIDTH; i++)
			falseMask.asBool(i) = !trueMask.asBool(i);

		execCtx.andExecutionMask(falseMask);
		m_falseStatement->execute(execCtx);
		execCtx.popExecutionMask();
	}
}

float ConditionalStatement::getWeight (const GeneratorState& state)
{
	if (!state.getProgramParameters().useConditionals)
		return 0.0f;

	int availableLevels = state.getShaderParameters().maxStatementDepth - state.getStatementDepth();
	return (availableLevels > 1) ? 1.0f : 0.0f;
}

AssignStatement::AssignStatement (const Variable* variable, Expression* value)
	: m_variable	(variable)
	, m_valueExpr	(value)	// \note Takes ownership of value
{
}

AssignStatement::AssignStatement (GeneratorState& state, const Variable* variable, ConstValueRangeAccess valueRange)
	: m_variable	(variable)
	, m_valueExpr	(DE_NULL)
{
	// Generate random value
	ExpressionGenerator generator(state);
	m_valueExpr = generator.generate(valueRange, 1);
}

AssignStatement::~AssignStatement (void)
{
	delete m_valueExpr;
}

void AssignStatement::tokenize (GeneratorState& state, TokenStream& str) const
{
	str << Token(m_variable->getName()) << Token::EQUAL;
	m_valueExpr->tokenize(state, str);
	str << Token::SEMICOLON << Token::NEWLINE;
}

void AssignStatement::execute (ExecutionContext& execCtx) const
{
	m_valueExpr->evaluate(execCtx);
	assignMasked(execCtx.getValue(m_variable), m_valueExpr->getValue(), execCtx.getExecutionMask());
}

} // rsg
