/*
 * Copyright 1999-2004 The Apache Software Foundation.
 *
 * 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.
 */



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



#include <algorithm>



#include <xalanc/PlatformSupport/XalanMessageLoader.hpp>



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



XALAN_CPP_NAMESPACE_BEGIN



VariablesStack::VariablesStack() :
	m_stack(),
	m_globalStackFrameIndex(~0u),
	m_globalStackFrameMarked(false),
	m_currentStackFrameIndex(0),
	m_guardStack(),
	m_elementFrameStack()
{
	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);

	XALAN_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)
	{
		throw InvalidStackContextException();
	}

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

				XALAN_USING_STD(find)

				// See if the ElemVariable instance is already being evaluated...
				if (find(m_guardStack.begin(), m_guardStack.end(), var) != m_guardStack.end())
				{
					executionContext.error(
						XalanMessageLoader::getMessage(XalanMessages::CircularVariableDefWasDetected),
						doc,
						var->getLocator());
				}

				m_guardStack.push_back(var);

				// We need to set up a stack frame for the variable's execution...
				typedef StylesheetExecutionContext::PushAndPopContextMarker	PushAndPopContextMarker;

				const PushAndPopContextMarker	theContextMarkerPushPop(executionContext);

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

				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)
		{
			throw InvalidStackContextException();
		}
		else if (theEntry.getType() == StackEntry::eElementFrameMarker)
		{
#if !defined(NDEBUG)
			const ElemTemplateElement* const	theElement =
				theEntry.getElement();

			if (m_elementFrameStack.empty() == true)
			{
				throw InvalidStackContextException();
			}

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

			m_elementFrameStack.pop_back();

			if (theElement != theStackBack)
			{
				throw InvalidStackContextException();
			}
#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;
	}
}



VariablesStack::InvalidStackContextException::InvalidStackContextException() :
	XSLTProcessorException(XalanMessageLoader::getMessage(XalanMessages::InvalidStackContext),
						   TranscodeFromLocalCodePage("InvalidStackContextException"))
{
}



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



XALAN_CPP_NAMESPACE_END
