/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you 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.
 */



// Class header file.
#include "VariablesStack.hpp"



#include <algorithm>



#include <xalanc/PlatformSupport/XalanMessageLoader.hpp>



#include "ElemVariable.hpp"
#include "StylesheetExecutionContext.hpp"



namespace XALAN_CPP_NAMESPACE {



VariablesStack::VariablesStack(MemoryManager& theManager) :
    m_stack(theManager),
    m_globalStackFrameIndex(~0u),
    m_globalStackFrameMarked(false),
    m_currentStackFrameIndex(0),
    m_guardStack(theManager),
    m_elementFrameStack(theManager)
{
    m_stack.reserve(eDefaultStackSize);
}



VariablesStack::~VariablesStack()
{
}



void
VariablesStack::reset()
{
    while(m_stack.empty() == false)
    {
        pop();
    }

    m_stack.clear();
    m_guardStack.clear();
    m_elementFrameStack.clear();

    m_globalStackFrameMarked = false;
    m_globalStackFrameIndex = ~0u;
}



bool
VariablesStack::elementFrameAlreadyPushed(const ElemTemplateElement*    elem) const
{
    const VariableStackStackType::size_type     nElems = m_stack.size();
    assert(nElems > 0);

    // There is guaranteed to be a context marker at
    // the bottom of the stack, so i should stop at
    // 1.
    for(VariableStackStackType::size_type i = nElems - 1; i > 0; --i)
    {
        const StackEntry&   theEntry = m_stack[i];

        if(theEntry.getType() == StackEntry::eElementFrameMarker)
        {
            if(theEntry.getElement() == elem)
            {
                return true;
            }
        }
    }

    return false;
}



void
VariablesStack::pushContextMarker()
{
    push(StackEntry());
}



void
VariablesStack::popContextMarker()
{
    VariableStackStackType::iterator    i = m_stack.end();

    for(; ;)
    {
        assert(i != m_stack.begin());

        const StackEntry&           theEntry = *--i;
        assert(theEntry == back());

        const StackEntry::eType     type = theEntry.getType();
        assert(type < StackEntry::eNextValue && type >= 0);

        pop();

        if (type == StackEntry::eContextMarker)
        {
            break;
        }
    }

    // This introduced a regression into 1.7, because of all the
    // external fiddling with the stack frame index.  We need to
    // re-write that code so no external meddling is necessary,
    // so we can track the stack frame index properly.  In particular,
    // this is an issue with xsl:apply-templates, because a context
    // marker is pushed before its select attribute is evaluated, even
    // though the select expression really should be evaluated in
    // the previous stack context.
//  m_currentStackFrameIndex = size_type(m_stack.size());
}



void
VariablesStack::push(const StackEntry&  theEntry)
{
    assert(theEntry.getType() < StackEntry::eNextValue && theEntry.getType() >= 0);

    if(m_currentStackFrameIndex == m_stack.size())
    {
        ++m_currentStackFrameIndex;
    }

    m_stack.push_back(theEntry);

    // Increment the global stack frame index as long as we're pushing variables, and
    // it already hasn't been marked.  This is a temporary work-around for problems
    // with evaluating top-level variables as they're pushed, rather than as they're
    // used.
    if (m_globalStackFrameMarked == false && theEntry.getType() == StackEntry::eVariable)
    {
        m_globalStackFrameIndex = m_currentStackFrameIndex;
    }
}



void
VariablesStack::pop()
{
    assert(m_stack.empty() == false);

    if(m_currentStackFrameIndex == m_stack.size())
    {
        --m_currentStackFrameIndex;
    }

    m_stack.pop_back();
}



void
VariablesStack::PushParamFunctor::operator()(const VariablesStack::ParamsVectorType::value_type&    theEntry) const
{
    assert(theEntry.m_qname != 0);

    if (theEntry.m_value.null() == false)
    {
        m_variablesStack.push(VariablesStack::StackEntry(theEntry.m_qname, theEntry.m_value, true));
    }
    else
    {
        assert(theEntry.m_variable != 0);

        m_variablesStack.push(VariablesStack::StackEntry(theEntry.m_qname, theEntry.m_variable, true));
    }
}



VariablesStack::CommitPushParams::CommitPushParams(VariablesStack&  theVariablesStack) :
    m_variablesStack(&theVariablesStack),
    m_stackSize(theVariablesStack.getStackSize())
{
}



VariablesStack::CommitPushParams::~CommitPushParams()
{
    if (m_variablesStack != 0)
    {
        while(m_variablesStack->getStackSize() > m_stackSize)
        {
            m_variablesStack->pop();
        }
    }
}



void
VariablesStack::pushParams(const ParamsVectorType&  theParams)
{
    // This object will push the params and pop them
    // if we don't call it's commit() member function.  So
    // if an exception is thrown while transferring the
    // parameters, the stack stays in a consistent state.
    CommitPushParams    thePusher(*this);

    using std::for_each;

    for_each(theParams.begin(), theParams.end(), PushParamFunctor(*this));

    thePusher.commit();
}



void
VariablesStack::pushVariable(
            const XalanQName&           name,
            const ElemVariable*         var,
            const ElemTemplateElement*  e)
{
    if(elementFrameAlreadyPushed(e) == false)
    {
        pushElementFrame(e);
    }

    push(StackEntry(&name, var));
}



void
VariablesStack::pushVariable(
            const XalanQName&           name,
            const XObjectPtr&           val,
            const ElemTemplateElement*  e)
{
    if(elementFrameAlreadyPushed(e) == false)
    {
        XalanDOMString theBuffer(m_stack.getMemoryManager());

        throw InvalidStackContextException(theBuffer);
    }

    push(StackEntry(&name, val));
}



void
VariablesStack::start()
{
}



void
VariablesStack::resetParams()
{
    const size_type     nElems = getCurrentStackFrameIndex();
    assert(nElems > 0);

    // There is guaranteed to be a context marker at
    // the bottom of the stack, so i should stop at
    // 1.
    for(size_type i = nElems - 1; i > 0; --i)
    {
        StackEntry&     theEntry = m_stack[i];

        if(theEntry.getType() == StackEntry::eContextMarker)
        {
            break;
        }
        else
        {
            theEntry.deactivate();
        }
    }
}



void
VariablesStack::markGlobalStackFrame()
{
    m_globalStackFrameIndex = size_type(m_stack.size());

    m_globalStackFrameMarked = true;

    pushContextMarker();
}



void
VariablesStack::unmarkGlobalStackFrame()
{
    popContextMarker();

    m_globalStackFrameIndex = ~0u;

    m_globalStackFrameMarked = false;
}



const XObjectPtr
VariablesStack::findXObject(
            const XalanQName&               name,
            StylesheetExecutionContext&     executionContext,
            bool                            fIsParam,
            bool                            fSearchGlobalSpace,
            bool&                           fNameFound)
{
    typedef VariableStackStackType::size_type   size_type;

    // findEntry() returns an index into the stack.  We should
    // _never_ take the address of anything in the stack, since
    // the address could change at unexpected times.
    const size_type     theEntryIndex =
        findEntry(name, fIsParam, fSearchGlobalSpace);

    if (theEntryIndex == m_stack.size())
    {
        fNameFound = false;

        return XObjectPtr();
    }
    else
    {
        assert(theEntryIndex < m_stack.size());

        fNameFound = true;

        assert(m_stack[theEntryIndex].getType() == StackEntry::eVariable ||
               m_stack[theEntryIndex].getType() == StackEntry::eParam ||
               m_stack[theEntryIndex].getType() == StackEntry::eActiveParam);

        const XObjectPtr&   theValue = m_stack[theEntryIndex].getValue();

        if (theValue.null() == false)
        {
            return theValue;
        }
        else
        {
            const ElemVariable* const   var = m_stack[theEntryIndex].getVariable();

            XObjectPtr                  theNewValue;

            if (var != 0)
            {
                XalanNode* const    doc = executionContext.getRootDocument();
                assert(doc != 0);

                using std::find;

                // See if the ElemVariable instance is already being evaluated...
                if (find(m_guardStack.begin(), m_guardStack.end(), var) != m_guardStack.end())
                {
                    const StylesheetExecutionContext::GetCachedString   theGuard(executionContext);

                    executionContext.problem(
                        StylesheetExecutionContext::eXSLTProcessor,
                        StylesheetExecutionContext::eError,
                        XalanMessageLoader::getMessage(
                            theGuard.get(),
                            XalanMessages::CircularVariableDefWasDetected),
                        var->getLocator(),
                        doc);
                }

                m_guardStack.push_back(var);

#if !defined(XALAN_RECURSIVE_STYLESHEET_EXECUTION)
                executionContext.pushContextMarker();
#else
                // We need to set up a stack frame for the variable's execution...
                typedef StylesheetExecutionContext::PushAndPopContextMarker PushAndPopContextMarker;

                const PushAndPopContextMarker   theContextMarkerPushPop(executionContext);
#endif

                theNewValue = var->getValue(executionContext, doc);
                assert(theNewValue.null() == false);

#if !defined(XALAN_RECURSIVE_STYLESHEET_EXECUTION)
                executionContext.popContextMarker();
#endif

                assert(m_guardStack.empty() == false);

                m_guardStack.pop_back();

                m_stack[theEntryIndex].setValue(theNewValue);
                m_stack[theEntryIndex].activate();
            }

            return theNewValue;
        }
    }
}



VariablesStack::size_type
VariablesStack::findEntry(
            const XalanQName&   qname,
            bool                fIsParam,
            bool                fSearchGlobalSpace)
{
    size_type   theEntryIndex = size_type(m_stack.size());

    const size_type     nElems = getCurrentStackFrameIndex();

    // There is guaranteed to be a context marker at
    // the bottom of the stack, so i should stop at
    // 1.
    for(size_type i = nElems - 1; i > 0; --i)
    {
        StackEntry&                 theEntry = m_stack[i];

        const StackEntry::eType     theType = theEntry.getType();

        if(theType == StackEntry::eVariable ||
           theType == StackEntry::eActiveParam)
        {
            assert(theEntry.getName() != 0);

            if(theEntry.getName()->equals(qname))
            {
                theEntryIndex = i;

                break;
            }
        }
        else if (theType == StackEntry::eParam)
        {
            if (fIsParam == true)
            {
                if(theEntry.getName()->equals(qname))
                {
                    theEntry.activate();

                    theEntryIndex = i;

                    break;
                }
            }
        }
        else if(theType == StackEntry::eContextMarker)
        {
            break;
        }
    }

    if(theEntryIndex == m_stack.size() && fIsParam == false && true == fSearchGlobalSpace && m_globalStackFrameIndex > 1)
    {
        // Look in the global space
        for(size_type i = m_globalStackFrameIndex - 1; i > 0; i--)
        {
            StackEntry&     theEntry = m_stack[i];

            const StackEntry::eType     theType = theEntry.getType();

            if(theType == StackEntry::eVariable)
            {
                assert(theEntry.getName() != 0);

                if(theEntry.getName()->equals(qname))
                {
                    theEntryIndex = i;

                    break;
                }
            }
            else if(theType == StackEntry::eContextMarker)
            {
                break;
            }
        }
    }

    return theEntryIndex;
}



void
VariablesStack::pushElementFrame(const ElemTemplateElement* elem)
{
    push(StackEntry(elem));

#if !defined(NDEBUG)
    m_elementFrameStack.push_back(elem);
#endif
}



class EnsurePop
{
public:

    EnsurePop(VariablesStack&   theVariablesStack) :
        m_variablesStack(theVariablesStack)
    {
    }

    ~EnsurePop()
    {
        m_variablesStack.pop();
    }

private:

    VariablesStack&     m_variablesStack;
};



void
VariablesStack::popElementFrame()
{
    const VariableStackStackType::size_type     nElems = m_stack.size();
    assert(nElems > 0);

    // There is guaranteed to be a context marker at
    // the bottom of the stack, so i should stop at
    // 1.
    for(VariableStackStackType::size_type i = nElems - 1; i > 0; --i)
    {
        const StackEntry&   theEntry = m_stack[i];

        // Guarantee that it will be popped when we're done.
        const EnsurePop     theEnsurePop(*this);

        if(theEntry.getType() == StackEntry::eContextMarker)
        {
            XalanDOMString theBuffer(m_stack.getMemoryManager());

            throw InvalidStackContextException(theBuffer);
        }
        else if (theEntry.getType() == StackEntry::eElementFrameMarker)
        {
#if !defined(NDEBUG)
            const ElemTemplateElement* const    theElement =
                theEntry.getElement();

            if (m_elementFrameStack.empty() == true)
            {
                XalanDOMString theBuffer(m_stack.getMemoryManager());

                throw InvalidStackContextException(theBuffer);
            }

            const ElemTemplateElement* const    theStackBack =
                m_elementFrameStack.back();

            m_elementFrameStack.pop_back();

            if (theElement != theStackBack)
            {
                XalanDOMString theBuffer(m_stack.getMemoryManager());

                throw InvalidStackContextException(theBuffer);
            }
#endif

            break;
        }
    }
}



VariablesStack::StackEntry::StackEntry() :
    m_type(eContextMarker),
    m_qname(0),
    m_value(),
    m_variable(0),
    m_element(0)
{
}



VariablesStack::StackEntry::StackEntry(
            const XalanQName*   name,
            const XObjectPtr&   val,
            bool                isParam) :
    m_type(isParam == true ? eParam : eVariable),
    m_qname(name),
    m_value(val),
    m_variable(0),
    m_element(0)
{
}



VariablesStack::StackEntry::StackEntry(
            const XalanQName*       name,
            const ElemVariable*     var,
            bool                    isParam) :
    m_type(isParam == true ? eParam : eVariable),
    m_qname(name),
    m_value(),
    m_variable(var),
    m_element(0)
{
}



VariablesStack::StackEntry::StackEntry(const ElemTemplateElement*   elem) :
    m_type(eElementFrameMarker),
    m_qname(0),
    m_value(),
    m_variable(0),
    m_element(elem)
{
}



VariablesStack::StackEntry::StackEntry(const StackEntry&    theSource) :
    m_type(theSource.m_type),
    m_qname(theSource.m_qname),
    m_value(theSource.m_value),
    m_variable(theSource.m_variable),
    m_element(theSource.m_element)
{
}



VariablesStack::StackEntry::~StackEntry()
{
}



VariablesStack::StackEntry&
VariablesStack::StackEntry::operator=(const StackEntry&     theRHS)
{
    if (this != &theRHS)
    {
        m_type = theRHS.m_type;

        m_qname = theRHS.m_qname;

        m_value = theRHS.m_value;

        m_variable = theRHS.m_variable;

        m_element = theRHS.m_element;
    }

    return *this;
}



// Equality for StackEntry instances is probably bogus,
// so it might be worthwhile to just get rid of this.
bool
VariablesStack::StackEntry::operator==(const StackEntry&    theRHS) const
{
    bool    fResult = false;

    if (m_type == theRHS.m_type)
    {
        if (m_type == eContextMarker)
        {
            if (&theRHS == this)
            {
                fResult = true;
            }
        }
        else if (m_type == eVariable || m_type == eParam || m_type == eActiveParam)
        {
            // We only need to compare the variable related members...
            if (m_value == theRHS.m_value ||
                m_variable == theRHS.m_variable)
            {
                fResult = true;
            }
        }
        else if (m_type == eElementFrameMarker)
        {
            if (m_element == theRHS.m_element)
            {
                fResult = true;
            }
        }
        else
        {
            assert(0);
        }
    }

    return fResult;
}



void
VariablesStack::StackEntry::activate()
{
    if (m_type == eParam)
    {
        m_type = eActiveParam;
    }
}



void
VariablesStack::StackEntry::deactivate()
{
    if (m_type == eActiveParam)
    {
        m_type = eParam;
    }
}


const XalanDOMChar  VariablesStack::InvalidStackContextException::m_type[] = 
{   
    XalanUnicode::charLetter_I,
    XalanUnicode::charLetter_n,
    XalanUnicode::charLetter_v,
    XalanUnicode::charLetter_a,
    XalanUnicode::charLetter_l,
    XalanUnicode::charLetter_i,
    XalanUnicode::charLetter_d,
    XalanUnicode::charLetter_S,
    XalanUnicode::charLetter_t,
    XalanUnicode::charLetter_a,
    XalanUnicode::charLetter_c,
    XalanUnicode::charLetter_k,
    XalanUnicode::charLetter_C,
    XalanUnicode::charLetter_o,
    XalanUnicode::charLetter_n,
    XalanUnicode::charLetter_t,
    XalanUnicode::charLetter_e,
    XalanUnicode::charLetter_x,
    XalanUnicode::charLetter_t,
    XalanUnicode::charLetter_E,
    XalanUnicode::charLetter_x,
    XalanUnicode::charLetter_c,
    XalanUnicode::charLetter_e,
    XalanUnicode::charLetter_p,
    XalanUnicode::charLetter_t,
    XalanUnicode::charLetter_i,
    XalanUnicode::charLetter_o,
    XalanUnicode::charLetter_n,
    0
};



VariablesStack::InvalidStackContextException::InvalidStackContextException(XalanDOMString& theResult) :
    XSLTProcessorException(
        theResult.getMemoryManager(),
        XalanMessageLoader::getMessage(
            theResult,
            XalanMessages::InvalidStackContext))
{
}



VariablesStack::InvalidStackContextException::~InvalidStackContextException()
{
}



}
