/*-------------------------------------------------------------------------
 * 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)
	, m_groupNumber		(0)
{
	// Init traverse state and "seek" to first reportable node.
	NodeIter iter(&rootNode);
	iter.setState(NodeIter::NISTATE_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::NISTATE_ENTER ||
				  iter.getState() == NodeIter::NISTATE_LEAVE);

		return iter.getState() == NodeIter::NISTATE_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::NISTATE_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::NISTATE_ENTER);
				return; // Yield enter event
			}

			case NodeIter::NISTATE_ENTER:
			{
				if (isLeaf)
				{
					iter.setState(NodeIter::NISTATE_LEAVE);
					return; // Yield leave event
				}
				else
				{
					iter.setState(NodeIter::NISTATE_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::NISTATE_TRAVERSE_CHILDREN:
			{
				int numChildren = (int)iter.children.size();
				if (++iter.curChildNdx < numChildren)
				{
					// Push child to stack.
					TestNode* childNode = iter.children[iter.curChildNdx];

					// Check whether this is a bottom-level group (child is executable)
					// and whether that group should be filtered out.
					if ( isTestNodeTypeExecutable(childNode->getNodeType()) )
					{
						const std::string testName = m_nodePath + "." + childNode->getName();
						if(!m_caseListFilter.checkCaseFraction(m_groupNumber, testName))
							break;
					}
					m_sessionStack.push_back(NodeIter(childNode));
				}
				else
				{
					iter.setState(NodeIter::NISTATE_LEAVE);
					if (node->getNodeType() != NODETYPE_ROOT)
						return; // Yield leave event
				}

				break;
			}

			case NodeIter::NISTATE_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_groupNumber++;
				}

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

			default:
				DE_ASSERT(false);
				return;
		}
	}

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

} // tcu
