/*-------------------------------------------------------------------------
 * 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 Variable manager.
 *//*--------------------------------------------------------------------*/

#include "rsgVariableManager.hpp"

#include <algorithm>
#include <map>
#include <set>

using std::map;
using std::set;
using std::vector;

namespace rsg
{

class SubValueRangeIterator
{
public:
    SubValueRangeIterator(const ConstValueRangeAccess &valueRange);
    ~SubValueRangeIterator(void)
    {
    }

    bool hasItem(void) const;
    ConstValueRangeAccess getItem(void) const;
    void next(void);

private:
    vector<ConstValueRangeAccess> m_stack;
};

SubValueRangeIterator::SubValueRangeIterator(const ConstValueRangeAccess &valueRange)
{
    m_stack.push_back(valueRange);
}

inline bool SubValueRangeIterator::hasItem(void) const
{
    return !m_stack.empty();
}

inline ConstValueRangeAccess SubValueRangeIterator::getItem(void) const
{
    return m_stack[m_stack.size() - 1];
}

void SubValueRangeIterator::next(void)
{
    ConstValueRangeAccess curItem = getItem();
    m_stack.pop_back(); // Remove current

    switch (curItem.getType().getBaseType())
    {
    case VariableType::TYPE_ARRAY:
    {
        int numElements = curItem.getType().getNumElements();
        for (int ndx = 0; ndx < numElements; ndx++)
            m_stack.push_back(curItem.member(ndx));
        break;
    }

    case VariableType::TYPE_STRUCT:
    {
        int numMembers = (int)curItem.getType().getMembers().size();
        for (int ndx = 0; ndx < numMembers; ndx++)
            m_stack.push_back(curItem.member(ndx));
        break;
    }

    default:
        break; // \todo [2011-02-03 pyry] Swizzle control?
    }
}

ValueEntry::ValueEntry(const Variable *variable) : m_variable(variable), m_valueRange(variable->getType())
{
}

VariableScope::VariableScope(void)
{
}

VariableScope::~VariableScope(void)
{
    for (vector<Variable *>::iterator i = m_declaredVariables.begin(); i != m_declaredVariables.end(); i++)
        delete *i;

    for (vector<Variable *>::iterator i = m_liveVariables.begin(); i != m_liveVariables.end(); i++)
        delete *i;
}

Variable *VariableScope::allocate(const VariableType &type, Variable::Storage storage, const char *name)
{
    Variable *variable = new Variable(type, storage, name);
    try
    {
        m_liveVariables.push_back(variable);
        return variable;
    }
    catch (const std::exception &)
    {
        delete variable;
        throw;
    }
}

void VariableScope::declare(Variable *variable)
{
    m_declaredVariables.push_back(variable);
    removeLive(variable);
}

void VariableScope::removeLive(const Variable *variable)
{
    vector<Variable *>::iterator pos = std::find(m_liveVariables.begin(), m_liveVariables.end(), variable);
    DE_ASSERT(pos != m_liveVariables.end());

    // \todo [pyry] Not so efficient
    m_liveVariables.erase(pos);
}

ValueScope::ValueScope(void)
{
}

ValueScope::~ValueScope(void)
{
    clear();
}

void ValueScope::clear(void)
{
    for (vector<ValueEntry *>::iterator i = m_entries.begin(); i != m_entries.end(); i++)
        delete *i;
    m_entries.clear();
}

ValueEntry *ValueScope::allocate(const Variable *variable)
{
    ValueEntry *entry = new ValueEntry(variable);
    try
    {
        m_entries.push_back(entry);
        return entry;
    }
    catch (const std::exception &)
    {
        delete entry;
        throw;
    }
}

class CompareEntryVariable
{
public:
    CompareEntryVariable(const Variable *variable) : m_variable(variable)
    {
    }

    bool operator==(const ValueEntry *entry) const
    {
        return entry->getVariable() == m_variable;
    }

private:
    const Variable *m_variable;
};

bool operator==(const ValueEntry *entry, const CompareEntryVariable &cmp)
{
    return cmp == entry;
}

ValueEntry *ValueScope::findEntry(const Variable *variable) const
{
    vector<ValueEntry *>::const_iterator pos =
        std::find(m_entries.begin(), m_entries.end(), CompareEntryVariable(variable));
    return pos != m_entries.end() ? *pos : DE_NULL;
}

void ValueScope::setValue(const Variable *variable, ConstValueRangeAccess value)
{
    ValueEntry *entry = findEntry(variable);
    DE_ASSERT(entry);

    ValueRangeAccess dst = entry->getValueRange();
    dst.getMin()         = value.getMin().value();
    dst.getMax()         = value.getMax().value();
}

void ValueScope::removeValue(const Variable *variable)
{
    vector<ValueEntry *>::iterator pos = std::find(m_entries.begin(), m_entries.end(), CompareEntryVariable(variable));
    if (pos != m_entries.end())
    {
        ValueEntry *entry = *pos;
        m_entries.erase(pos);
        delete entry;
    }
}

VariableManager::VariableManager(NameAllocator &nameAllocator)
    : m_numAllocatedScalars(0)
    , m_numAllocatedShaderInScalars(0)
    , m_numAllocatedShaderInVariables(0)
    , m_numAllocatedUniformScalars(0)
    , m_nameAllocator(nameAllocator)
{
}

VariableManager::~VariableManager(void)
{
}

Variable *VariableManager::allocate(const VariableType &type)
{
    return allocate(type, Variable::STORAGE_LOCAL, m_nameAllocator.allocate().c_str());
}

Variable *VariableManager::allocate(const VariableType &type, Variable::Storage storage, const char *name)
{
    VariableScope &varScope = getCurVariableScope();
    ValueScope &valueScope  = getCurValueScope();
    int numScalars          = type.getScalarSize();

    // Allocate in current scope
    Variable *variable = varScope.allocate(type, Variable::STORAGE_LOCAL, name);

    // Allocate value entry
    ValueEntry *valueEntry = valueScope.allocate(variable);

    // Add to cache
    m_entryCache.push_back(valueEntry);

    m_numAllocatedScalars += numScalars;

    // Set actual storage - affects uniform/shader in allocations.
    setStorage(variable, storage);

    return variable;
}

void VariableManager::setStorage(Variable *variable, Variable::Storage storage)
{
    int numScalars = variable->getType().getScalarSize();

    // Decrement old.
    if (variable->getStorage() == Variable::STORAGE_SHADER_IN)
    {
        m_numAllocatedShaderInScalars -= numScalars;
        m_numAllocatedShaderInVariables -= 1;
    }
    else if (variable->getStorage() == Variable::STORAGE_UNIFORM)
        m_numAllocatedUniformScalars -= numScalars;

    // Add new.
    if (storage == Variable::STORAGE_SHADER_IN)
    {
        m_numAllocatedShaderInScalars += numScalars;
        m_numAllocatedShaderInVariables += 1;
    }
    else if (storage == Variable::STORAGE_UNIFORM)
        m_numAllocatedUniformScalars += numScalars;

    variable->setStorage(storage);
}

bool VariableManager::canDeclareInCurrentScope(const Variable *variable) const
{
    const vector<Variable *> &curLiveVars = getCurVariableScope().getLiveVariables();
    return std::find(curLiveVars.begin(), curLiveVars.end(), variable) != curLiveVars.end();
}

const vector<Variable *> &VariableManager::getLiveVariables(void) const
{
    return getCurVariableScope().getLiveVariables();
}

void VariableManager::declareVariable(Variable *variable)
{
    // Remove from cache if exists in there.
    std::vector<const ValueEntry *>::iterator pos =
        std::find(m_entryCache.begin(), m_entryCache.end(), CompareEntryVariable(variable));
    if (pos != m_entryCache.end())
        m_entryCache.erase(pos);

    DE_ASSERT(std::find(m_entryCache.begin(), m_entryCache.end(), CompareEntryVariable(variable)) ==
              m_entryCache.end());

    // Remove from scope stack.
    for (vector<ValueScope *>::const_iterator stackIter = m_valueScopeStack.begin();
         stackIter != m_valueScopeStack.end(); stackIter++)
    {
        ValueScope *scope = *stackIter;
        scope->removeValue(variable);
    }

    // Declare in current scope.
    getCurVariableScope().declare(variable);
}

const ValueEntry *VariableManager::getValue(const Variable *variable) const
{
    vector<const ValueEntry *>::const_iterator pos =
        std::find(m_entryCache.begin(), m_entryCache.end(), CompareEntryVariable(variable));
    return pos != m_entryCache.end() ? *pos : DE_NULL;
}

void VariableManager::removeValueFromCurrentScope(const Variable *variable)
{
    // Remove from cache
    std::vector<const ValueEntry *>::iterator pos =
        std::find(m_entryCache.begin(), m_entryCache.end(), CompareEntryVariable(variable));
    DE_ASSERT(pos != m_entryCache.end());
    m_entryCache.erase(pos);

    // Remove from current scope \note May not exist in there.
    getCurValueScope().removeValue(variable);
}

const ValueEntry *VariableManager::getParentValue(const Variable *variable) const
{
    if (m_valueScopeStack.size() < 2)
        return DE_NULL; // Only single value scope

    for (vector<ValueScope *>::const_reverse_iterator i = m_valueScopeStack.rbegin() + 1; i != m_valueScopeStack.rend();
         i++)
    {
        const ValueScope *scope = *i;
        ValueEntry *entry       = scope->findEntry(variable);

        if (entry)
            return entry;
    }

    return DE_NULL; // Not found in stack
}

void VariableManager::setValue(const Variable *variable, ConstValueRangeAccess value)
{
    ValueScope &curScope = getCurValueScope();

    if (!curScope.findEntry(variable))
    {
        // New value, allocate and update cache.
        ValueEntry *newEntry = curScope.allocate(variable);
        std::vector<const ValueEntry *>::iterator cachePos =
            std::find(m_entryCache.begin(), m_entryCache.end(), CompareEntryVariable(variable));

        if (cachePos != m_entryCache.end())
            *cachePos = newEntry;
        else
            m_entryCache.push_back(newEntry);
    }

    curScope.setValue(variable, value);
}

void VariableManager::reserve(ReservedScalars &store, int numScalars)
{
    DE_ASSERT(store.numScalars == 0);
    store.numScalars = numScalars;
    m_numAllocatedScalars += numScalars;
}

void VariableManager::release(ReservedScalars &store)
{
    m_numAllocatedScalars -= store.numScalars;
    store.numScalars = 0;
}

void VariableManager::pushVariableScope(VariableScope &scope)
{
    // Expects emtpy scope
    DE_ASSERT(scope.getDeclaredVariables().size() == 0);
    DE_ASSERT(scope.getLiveVariables().size() == 0);

    m_variableScopeStack.push_back(&scope);
}

void VariableManager::popVariableScope(void)
{
    VariableScope &curScope = getCurVariableScope();

    // Migrate live variables to parent scope.
    // Variables allocated in child scopes can be declared in any parent scope but not the other way around.
    if (m_variableScopeStack.size() > 1)
    {
        VariableScope &parentScope        = *m_variableScopeStack[m_variableScopeStack.size() - 2];
        vector<Variable *> &curLiveVars   = curScope.getLiveVariables();
        vector<Variable *> &parenLiveVars = parentScope.getLiveVariables();

        while (!curLiveVars.empty())
        {
            Variable *liveVar = curLiveVars.back();
            parenLiveVars.push_back(liveVar);
            curLiveVars.pop_back();
        }
    }

    // All variables should be either migrated to parent or declared (in case of root scope).
    DE_ASSERT(curScope.getLiveVariables().size() == 0);

    m_variableScopeStack.pop_back();
}

void VariableManager::pushValueScope(ValueScope &scope)
{
    // Value scope should be empty
    DE_ASSERT(scope.getValues().size() == 0);

    m_valueScopeStack.push_back(&scope);
}

void VariableManager::popValueScope(void)
{
    ValueScope &oldScope = getCurValueScope();

    // Pop scope and clear cache.
    m_valueScopeStack.pop_back();
    m_entryCache.clear();

    // Re-build entry cache.
    if (!m_valueScopeStack.empty())
    {
        ValueScope &newTopScope = getCurValueScope();

        // Speed up computing intersections.
        map<const Variable *, const ValueEntry *> oldValues;
        const vector<ValueEntry *> &oldEntries = oldScope.getValues();

        for (vector<ValueEntry *>::const_iterator valueIter = oldEntries.begin(); valueIter != oldEntries.end();
             valueIter++)
            oldValues[(*valueIter)->getVariable()] = *valueIter;

        set<const Variable *> addedVars;

        // Re-build based on current stack.
        for (vector<ValueScope *>::reverse_iterator scopeIter = m_valueScopeStack.rbegin();
             scopeIter != m_valueScopeStack.rend(); scopeIter++)
        {
            const ValueScope *scope                  = *scopeIter;
            const vector<ValueEntry *> &valueEntries = scope->getValues();

            for (vector<ValueEntry *>::const_iterator valueIter = valueEntries.begin(); valueIter != valueEntries.end();
                 valueIter++)
            {
                const ValueEntry *entry = *valueIter;
                const Variable *var     = entry->getVariable();

                if (addedVars.find(var) != addedVars.end())
                    continue; // Already in cache, set deeper in scope stack.

                DE_ASSERT(std::find(m_entryCache.begin(), m_entryCache.end(), CompareEntryVariable(var)) ==
                          m_entryCache.end());

                if (oldValues.find(var) != oldValues.end())
                {
                    const ValueEntry *oldEntry = oldValues[var];

                    // Build new intersected value and store into current scope.
                    ValueRange intersectedValue(var->getType());
                    DE_ASSERT(oldEntry->getValueRange().intersects(entry->getValueRange())); // Must intersect
                    ValueRange::computeIntersection(intersectedValue, entry->getValueRange(),
                                                    oldEntry->getValueRange());

                    if (!newTopScope.findEntry(var))
                        newTopScope.allocate(var);

                    newTopScope.setValue(var, intersectedValue.asAccess());

                    // Add entry from top scope to cache.
                    m_entryCache.push_back(newTopScope.findEntry(var));
                }
                else
                    m_entryCache.push_back(entry); // Just add to cache.

                addedVars.insert(var); // Record as cached variable.
            }
        }

        // Copy entries from popped scope that don't yet exist in the stack.
        for (vector<ValueEntry *>::const_iterator valueIter = oldEntries.begin(); valueIter != oldEntries.end();
             valueIter++)
        {
            const ValueEntry *oldEntry = *valueIter;
            const Variable *var        = oldEntry->getVariable();

            if (addedVars.find(var) == addedVars.end())
                setValue(var, oldEntry->getValueRange());
        }
    }
}

} // namespace rsg
