/*-------------------------------------------------------------------------
 * drawElements Quality Program Tester Core
 * ----------------------------------------
 *
 * 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 Test case hierarchy iterator.
 *//*--------------------------------------------------------------------*/

#include "tcuTestHierarchyIterator.hpp"
#include "tcuCommandLine.hpp"

namespace tcu
{

using std::string;
using std::vector;

// TestHierarchyInflater

TestHierarchyInflater::TestHierarchyInflater (void)
{
}

TestHierarchyInflater::~TestHierarchyInflater (void)
{
}

// DefaultHierarchyInflater

DefaultHierarchyInflater::DefaultHierarchyInflater (TestContext& testCtx)
	: m_testCtx(testCtx)
{
}

DefaultHierarchyInflater::~DefaultHierarchyInflater (void)
{
}

void DefaultHierarchyInflater::enterTestPackage (TestPackage* testPackage, vector<TestNode*>& children)
{
	{
		Archive* const	pkgArchive	= testPackage->getArchive();

		if (pkgArchive)
			m_testCtx.setCurrentArchive(*pkgArchive);
		else
			m_testCtx.setCurrentArchive(m_testCtx.getRootArchive());
	}

	testPackage->init();
	testPackage->getChildren(children);
}

void DefaultHierarchyInflater::leaveTestPackage (TestPackage* testPackage)
{
	m_testCtx.setCurrentArchive(m_testCtx.getRootArchive());
	testPackage->deinit();
}

void DefaultHierarchyInflater::enterGroupNode (TestCaseGroup* testGroup, vector<TestNode*>& children)
{
	testGroup->init();
	testGroup->getChildren(children);
}

void DefaultHierarchyInflater::leaveGroupNode (TestCaseGroup* testGroup)
{
	testGroup->deinit();
}

// TestHierarchyIterator

TestHierarchyIterator::TestHierarchyIterator (TestPackageRoot&			rootNode,
											  TestHierarchyInflater&	inflater,
											  const CaseListFilter&		caseListFilter)
	: m_inflater		(inflater)
	, m_caseListFilter	(caseListFilter)
{
	// Init traverse state and "seek" to first reportable node.
	NodeIter iter(&rootNode);
	iter.setState(NodeIter::STATE_ENTER); // Root is never reported
	m_sessionStack.push_back(iter);
	next();
}

TestHierarchyIterator::~TestHierarchyIterator (void)
{
	// Tear down inflated nodes in m_sessionStack
	for (vector<NodeIter>::reverse_iterator iter = m_sessionStack.rbegin(); iter != m_sessionStack.rend(); ++iter)
	{
		TestNode* const		node		= iter->node;
		const TestNodeType	nodeType	= node->getNodeType();

		switch (nodeType)
		{
			case NODETYPE_ROOT:		/* root is not de-initialized */								break;
			case NODETYPE_PACKAGE:	m_inflater.leaveTestPackage(static_cast<TestPackage*>(node));	break;
			case NODETYPE_GROUP:	m_inflater.leaveGroupNode(static_cast<TestCaseGroup*>(node));	break;
			default:
				break;
		}
	}
}

TestHierarchyIterator::State TestHierarchyIterator::getState (void) const
{
	if (!m_sessionStack.empty())
	{
		const NodeIter&	iter	= m_sessionStack.back();

		DE_ASSERT(iter.getState() == NodeIter::STATE_ENTER ||
				  iter.getState() == NodeIter::STATE_LEAVE);

		return iter.getState() == NodeIter::STATE_ENTER ? STATE_ENTER_NODE : STATE_LEAVE_NODE;
	}
	else
		return STATE_FINISHED;
}

TestNode* TestHierarchyIterator::getNode (void) const
{
	DE_ASSERT(getState() != STATE_FINISHED);
	return m_sessionStack.back().node;
}

const std::string& TestHierarchyIterator::getNodePath (void) const
{
	DE_ASSERT(getState() != STATE_FINISHED);
	return m_nodePath;
}

std::string TestHierarchyIterator::buildNodePath (const vector<NodeIter>& nodeStack)
{
	string nodePath;
	for (size_t ndx = 1; ndx < nodeStack.size(); ndx++)
	{
		const NodeIter& iter = nodeStack[ndx];
		if (ndx > 1) // ignore root package
			nodePath += ".";
		nodePath += iter.node->getName();
	}
	return nodePath;
}

void TestHierarchyIterator::next (void)
{
	while (!m_sessionStack.empty())
	{
		NodeIter&			iter		= m_sessionStack.back();
		TestNode* const		node		= iter.node;
		const bool			isLeaf		= isTestNodeTypeExecutable(node->getNodeType());

		switch (iter.getState())
		{
			case NodeIter::STATE_INIT:
			{
				const std::string nodePath = buildNodePath(m_sessionStack);

				// Return to parent if name doesn't match filter.
				if (!(isLeaf ? m_caseListFilter.checkTestCaseName(nodePath.c_str()) : m_caseListFilter.checkTestGroupName(nodePath.c_str())))
				{
					m_sessionStack.pop_back();
					break;
				}

				m_nodePath = nodePath;
				iter.setState(NodeIter::STATE_ENTER);
				return; // Yield enter event
			}

			case NodeIter::STATE_ENTER:
			{
				if (isLeaf)
				{
					iter.setState(NodeIter::STATE_LEAVE);
					return; // Yield leave event
				}
				else
				{
					iter.setState(NodeIter::STATE_TRAVERSE_CHILDREN);
					iter.children.clear();

					switch (node->getNodeType())
					{
						case NODETYPE_ROOT:		static_cast<TestPackageRoot*>(node)->getChildren(iter.children);				break;
						case NODETYPE_PACKAGE:	m_inflater.enterTestPackage(static_cast<TestPackage*>(node), iter.children);	break;
						case NODETYPE_GROUP:	m_inflater.enterGroupNode(static_cast<TestCaseGroup*>(node), iter.children);	break;
						default:
							DE_ASSERT(false);
					}
				}

				break;
			}

			case NodeIter::STATE_TRAVERSE_CHILDREN:
			{
				int numChildren = (int)iter.children.size();
				if (++iter.curChildNdx < numChildren)
				{
					// Push child to stack.
					TestNode* childNode = iter.children[iter.curChildNdx];
					m_sessionStack.push_back(NodeIter(childNode));
				}
				else
				{
					iter.setState(NodeIter::STATE_LEAVE);
					if (node->getNodeType() != NODETYPE_ROOT)
						return; // Yield leave event
				}

				break;
			}

			case NodeIter::STATE_LEAVE:
			{
				// Leave node.
				if (!isLeaf)
				{
					switch (node->getNodeType())
					{
						case NODETYPE_ROOT:		/* root is not de-initialized */								break;
						case NODETYPE_PACKAGE:	m_inflater.leaveTestPackage(static_cast<TestPackage*>(node));	break;
						case NODETYPE_GROUP:	m_inflater.leaveGroupNode(static_cast<TestCaseGroup*>(node));	break;
						default:
							DE_ASSERT(false);
					}
				}

				m_sessionStack.pop_back();
				m_nodePath = buildNodePath(m_sessionStack);
				break;
			}

			default:
				DE_ASSERT(false);
				return;
		}
	}

	DE_ASSERT(m_sessionStack.empty() && getState() == STATE_FINISHED);
}

} // tcu
