/*-------------------------------------------------------------------------
 * drawElements Quality Program Test Executor
 * ------------------------------------------
 *
 * 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.
 *//*--------------------------------------------------------------------*/

#include "xeTestCase.hpp"

using std::vector;

namespace xe
{

const char* getTestCaseTypeName (TestCaseType caseType)
{
	switch (caseType)
	{
		case TESTCASETYPE_SELF_VALIDATE:	return "SelfValidate";
		case TESTCASETYPE_CAPABILITY:		return "Capability";
		case TESTCASETYPE_ACCURACY:			return "Accuracy";
		case TESTCASETYPE_PERFORMANCE:		return "Performance";
		default:
			DE_ASSERT(false);
			return DE_NULL;
	}
}

static inline int getFirstComponentLength (const char* path)
{
	int compLen = 0;
	while (path[compLen] != 0 && path[compLen] != '.')
		compLen++;
	return compLen;
}

static bool compareNameToPathComponent (const char* name, const char* path, int compLen)
{
	for (int pos = 0; pos < compLen; pos++)
	{
		if (name[pos] != path[pos])
			return false;
	}

	if (name[compLen] != 0)
		return false;

	return true;
}

static void splitPath (const char* path, std::vector<std::string>& components)
{
	std::string	pathStr		(path);
	int			compStart	= 0;

	for (int pos = 0; pos < (int)pathStr.length(); pos++)
	{
		if (pathStr[pos] == '.')
		{
			components.push_back(pathStr.substr(compStart, pos-compStart));
			compStart = pos+1;
		}
	}

	DE_ASSERT(compStart < (int)pathStr.length());
	components.push_back(pathStr.substr(compStart));
}

// TestNode

TestNode::TestNode (TestGroup* parent, TestNodeType nodeType, const char* name, const char* desc)
	: m_parent		(parent)
	, m_nodeType	(nodeType)
	, m_name		(name)
	, m_description	(desc)
{
	if (m_parent)
	{
		// Verify that the name is unique.
		if (parent->m_childNames.find(name) != parent->m_childNames.end())
			throw Error(std::string("Duplicate node '") + name + "' in '" + parent->getFullPath());

		m_parent->m_children.push_back(this);
		m_parent->m_childNames.insert(name);
	}
}

void TestNode::getFullPath (std::string& dst) const
{
	dst.clear();

	int				nameLen	= 0;
	const TestNode*	curNode	= this;

	for (;;)
	{
		nameLen += (int)curNode->m_name.length();

		DE_ASSERT(curNode->m_parent);
		if (curNode->m_parent->getNodeType() != TESTNODETYPE_ROOT)
		{
			nameLen += 1;
			curNode  = curNode->m_parent;
		}
		else
			break;
	}

	dst.resize(nameLen);

	curNode = this;
	int pos = nameLen;

	for (;;)
	{
		std::copy(curNode->m_name.begin(), curNode->m_name.end(), dst.begin()+(pos-curNode->m_name.length()));
		pos -= (int)curNode->m_name.length();

		DE_ASSERT(curNode->m_parent);
		if (curNode->m_parent->getNodeType() != TESTNODETYPE_ROOT)
		{
			dst[--pos] = '.';
			curNode = curNode->m_parent;
		}
		else
			break;
	}
}

const TestNode* TestNode::find (const char* path) const
{
	if (m_nodeType == TESTNODETYPE_ROOT)
	{
		// Don't need to consider current node.
		return static_cast<const TestGroup*>(this)->findChildNode(path);
	}
	else
	{
		// Check if first component matches this node.
		int compLen = getFirstComponentLength(path);
		XE_CHECK(compLen > 0);

		if (compareNameToPathComponent(getName(), path, compLen))
		{
			if (path[compLen] == 0)
				return this;
			else if (getNodeType() == TESTNODETYPE_GROUP)
				return static_cast<const TestGroup*>(this)->findChildNode(path + compLen + 1);
			else
				return DE_NULL;
		}
		else
			return DE_NULL;
	}
}

TestNode* TestNode::find (const char* path)
{
	return const_cast<TestNode*>(const_cast<const TestNode*>(this)->find(path));
}

// TestGroup

TestGroup::TestGroup (TestGroup* parent, TestNodeType nodeType, const char* name, const char* description)
	: TestNode(parent, nodeType, name, description)
{
	DE_ASSERT(nodeType == TESTNODETYPE_GROUP || nodeType == TESTNODETYPE_ROOT);
	DE_ASSERT(!parent == (nodeType == TESTNODETYPE_ROOT));
}

TestGroup::~TestGroup (void)
{
	for (std::vector<TestNode*>::iterator i = m_children.begin(); i != m_children.end(); i++)
		delete *i;
}

TestGroup* TestGroup::createGroup (const char* name, const char* description)
{
	return new TestGroup(this, TESTNODETYPE_GROUP, name, description);
}

TestCase* TestGroup::createCase (TestCaseType caseType, const char* name, const char* description)
{
	return TestCase::createAsChild(this, caseType, name, description);
}

const TestNode* TestGroup::findChildNode (const char* path) const
{
	int compLen = getFirstComponentLength(path);
	XE_CHECK(compLen > 0);

	// Try to find matching children.
	const TestNode* matchingNode = DE_NULL;
	for (vector<TestNode*>::const_iterator iter = m_children.begin(); iter != m_children.end(); iter++)
	{
		if (compareNameToPathComponent((*iter)->getName(), path, compLen))
		{
			matchingNode = *iter;
			break;
		}
	}

	if (matchingNode)
	{
		if (path[compLen] == 0)
			return matchingNode; // Last element in path, return matching node.
		else if (matchingNode->getNodeType() == TESTNODETYPE_GROUP)
			return static_cast<const TestGroup*>(matchingNode)->findChildNode(path + compLen + 1);
		else
			return DE_NULL;
	}
	else
		return DE_NULL;
}

// TestRoot

TestRoot::TestRoot (void)
	: TestGroup(DE_NULL, TESTNODETYPE_ROOT, "", "")
{
}

// TestCase

TestCase* TestCase::createAsChild(TestGroup* parent, TestCaseType caseType, const char *name, const char *description)
{
	return new TestCase(parent, caseType, name, description);
}

TestCase::TestCase (TestGroup* parent, TestCaseType caseType, const char* name, const char* description)
	: TestNode		(parent, TESTNODETYPE_TEST_CASE, name, description)
	, m_caseType	(caseType)
{
}

TestCase::~TestCase (void)
{
}

// TestHierarchyBuilder helpers

void addChildGroupsToMap (std::map<std::string, TestGroup*>& groupMap, TestGroup* group)
{
	for (int ndx = 0; ndx < group->getNumChildren(); ndx++)
	{
		TestNode* node = group->getChild(ndx);
		if (node->getNodeType() == TESTNODETYPE_GROUP)
		{
			TestGroup*	childGroup	= static_cast<TestGroup*>(node);
			std::string	fullPath;
			childGroup->getFullPath(fullPath);

			groupMap.insert(std::make_pair(fullPath, childGroup));
			addChildGroupsToMap(groupMap, childGroup);
		}
	}
}

// TestHierarchyBuilder

TestHierarchyBuilder::TestHierarchyBuilder (TestRoot* root)
	: m_root(root)
{
	addChildGroupsToMap(m_groupMap, root);
}

TestHierarchyBuilder::~TestHierarchyBuilder (void)
{
}

TestCase* TestHierarchyBuilder::createCase (const char* path, TestCaseType caseType)
{
	// \todo [2012-09-05 pyry] This can be done with less string manipulations.
	std::vector<std::string> components;
	splitPath(path, components);
	DE_ASSERT(!components.empty());

	// Create all parents if necessary.
	TestGroup*	curGroup		= m_root;
	std::string	curGroupPath;
	for (int ndx = 0; ndx < (int)components.size()-1; ndx++)
	{
		if (!curGroupPath.empty())
			curGroupPath += ".";
		curGroupPath += components[ndx];

		std::map<std::string, TestGroup*>::const_iterator groupPos = m_groupMap.find(curGroupPath);
		if (groupPos == m_groupMap.end())
		{
			TestGroup* newGroup = curGroup->createGroup(components[ndx].c_str(), "" /* description */);
			m_groupMap.insert(std::make_pair(curGroupPath, newGroup));
			curGroup = newGroup;
		}
		else
			curGroup = groupPos->second;
	}

	return curGroup->createCase(caseType, components.back().c_str(), "" /* description */);
}

// TestSet helpers

static void addNodeAndParents (std::set<const TestNode*>& nodeSet, const TestNode* node)
{
	while (node != DE_NULL)
	{
		nodeSet.insert(node);
		node = node->getParent();
	}
}

static void addChildren (std::set<const TestNode*>& nodeSet, const TestGroup* group)
{
	for (int ndx = 0; ndx < group->getNumChildren(); ndx++)
	{
		const TestNode* child = group->getChild(ndx);
		nodeSet.insert(child);

		if (child->getNodeType() == TESTNODETYPE_GROUP)
			addChildren(nodeSet, static_cast<const TestGroup*>(child));
	}
}

static void removeChildren (std::set<const TestNode*>& nodeSet, const TestGroup* group)
{
	for (int ndx = 0; ndx < group->getNumChildren(); ndx++)
	{
		const TestNode* child = group->getChild(ndx);
		nodeSet.erase(child);

		if (child->getNodeType() == TESTNODETYPE_GROUP)
			removeChildren(nodeSet, static_cast<const TestGroup*>(child));
	}
}

static bool hasChildrenInSet (const std::set<const TestNode*>& nodeSet, const TestGroup* group)
{
	for (int ndx = 0; ndx < group->getNumChildren(); ndx++)
	{
		if (nodeSet.find(group->getChild(ndx)) != nodeSet.end())
			return true;
	}
	return false;
}

static void removeEmptyGroups (std::set<const TestNode*>& nodeSet, const TestGroup* group)
{
	if (!hasChildrenInSet(nodeSet, group))
	{
		nodeSet.erase(group);
		if (group->getParent() != DE_NULL)
			removeEmptyGroups(nodeSet, group->getParent());
	}
}

// TestSet

void TestSet::add (const TestNode* node)
{
	if (node->getNodeType() == TESTNODETYPE_TEST_CASE)
		addCase(static_cast<const TestCase*>(node));
	else
	{
		XE_CHECK(node->getNodeType() == TESTNODETYPE_GROUP ||
				  node->getNodeType() == TESTNODETYPE_ROOT);
		addGroup(static_cast<const TestGroup*>(node));
	}
}

void TestSet::addCase (const TestCase* testCase)
{
	addNodeAndParents(m_set, testCase);
}

void TestSet::addGroup (const TestGroup* testGroup)
{
	addNodeAndParents(m_set, testGroup);
	addChildren(m_set, testGroup);
}

void TestSet::remove (const TestNode* node)
{
	if (node->getNodeType() == TESTNODETYPE_TEST_CASE)
		removeCase(static_cast<const TestCase*>(node));
	else
	{
		XE_CHECK(node->getNodeType() == TESTNODETYPE_GROUP ||
				  node->getNodeType() == TESTNODETYPE_ROOT);
		removeGroup(static_cast<const TestGroup*>(node));
	}
}

void TestSet::removeCase (const TestCase* testCase)
{
	if (m_set.find(testCase) != m_set.end())
	{
		m_set.erase(testCase);
		removeEmptyGroups(m_set, testCase->getParent());
	}
}

void TestSet::removeGroup (const TestGroup* testGroup)
{
	if (m_set.find(testGroup) != m_set.end())
	{
		m_set.erase(testGroup);
		removeChildren(m_set, testGroup);
		if (testGroup->getParent() != DE_NULL)
			removeEmptyGroups(m_set, testGroup->getParent());
	}
}

// ConstTestNodeIterator

ConstTestNodeIterator::ConstTestNodeIterator (const TestNode* root)
	: m_root(root)
{
}

ConstTestNodeIterator ConstTestNodeIterator::begin (const TestNode* root)
{
	ConstTestNodeIterator iter(root);
	iter.m_iterStack.push_back(GroupState(DE_NULL));
	return iter;
}

ConstTestNodeIterator ConstTestNodeIterator::end (const TestNode* root)
{
	DE_UNREF(root);
	return ConstTestNodeIterator(root);
}

ConstTestNodeIterator& ConstTestNodeIterator::operator++ (void)
{
	DE_ASSERT(!m_iterStack.empty());

	const TestNode*	curNode			= **this;
	TestNodeType	curNodeType		= curNode->getNodeType();

	if ((curNodeType == TESTNODETYPE_GROUP || curNodeType == TESTNODETYPE_ROOT) &&
		static_cast<const TestGroup*>(curNode)->getNumChildren() > 0)
	{
		m_iterStack.push_back(GroupState(static_cast<const TestGroup*>(curNode)));
	}
	else
	{
		for (;;)
		{
			const TestGroup*	group		= m_iterStack.back().group;
			int&				childNdx	= m_iterStack.back().childNdx;
			int					numChildren	= group ? group->getNumChildren() : 1;

			childNdx += 1;
			if (childNdx == numChildren)
			{
				m_iterStack.pop_back();
				if (m_iterStack.empty())
					break;
			}
			else
				break;
		}
	}

	return *this;
}

ConstTestNodeIterator ConstTestNodeIterator::operator++ (int)
{
	ConstTestNodeIterator copy(*this);
	++(*this);
	return copy;
}

const TestNode* ConstTestNodeIterator::operator* (void) const
{
	DE_ASSERT(!m_iterStack.empty());
	if (m_iterStack.size() == 1)
	{
		DE_ASSERT(m_iterStack[0].group == DE_NULL && m_iterStack[0].childNdx == 0);
		return m_root;
	}
	else
		return m_iterStack.back().group->getChild(m_iterStack.back().childNdx);
}

bool ConstTestNodeIterator::operator!= (const ConstTestNodeIterator& other) const
{
	return m_root != other.m_root || m_iterStack != other.m_iterStack;
}

} // xe
