/*-------------------------------------------------------------------------
 * 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:
			// initializer is always created if value isn't null.
			createInitializer = value;
			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
