/*-------------------------------------------------------------------------
 * 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 CommandLine&		cmdLine)
	: m_inflater	(inflater)
	, m_cmdLine		(cmdLine)
{
	// 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_cmdLine.checkTestCaseName(nodePath.c_str()) : m_cmdLine.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
