/*-------------------------------------------------------------------------
 * 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);
}

} // namespace

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;
}

} // namespace

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;
}

} // namespace

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());
}

} // namespace rsg
