#ifndef _GLUVARTYPEUTIL_HPP
#define _GLUVARTYPEUTIL_HPP
/*-------------------------------------------------------------------------
 * drawElements Quality Program OpenGL ES Utilities
 * ------------------------------------------------
 *
 * 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 Shader variable type utilities.
 *//*--------------------------------------------------------------------*/

#include "tcuDefs.hpp"
#include "gluVarType.hpp"

#include <vector>
#include <string>
#include <iterator>

namespace glu
{

// Variable path tokenizer

class VarTokenizer
{
public:
	enum Token
	{
		TOKEN_IDENTIFIER = 0,
		TOKEN_LEFT_BRACKET,
		TOKEN_RIGHT_BRACKET,
		TOKEN_PERIOD,
		TOKEN_NUMBER,
		TOKEN_END,

		TOKEN_LAST
	};

					VarTokenizer					(const char* str);
					~VarTokenizer					(void) {}

	Token			getToken						(void) const { return m_token;															}
	std::string		getIdentifier					(void) const { return std::string(m_str+m_tokenStart, m_str+m_tokenStart+m_tokenLen);	}
	int				getNumber						(void) const;
	int				getCurrentTokenStartLocation	(void) const { return m_tokenStart;														}
	int				getCurrentTokenEndLocation		(void) const { return m_tokenStart + m_tokenLen;										}
	void			advance							(void);

private:
	const char*		m_str;

	Token			m_token;
	int				m_tokenStart;
	int				m_tokenLen;
};

// VarType subtype path utilities.

struct VarTypeComponent
{
	enum Type
	{
		STRUCT_MEMBER = 0,
		ARRAY_ELEMENT,
		MATRIX_COLUMN,
		VECTOR_COMPONENT,

		TYPE_LAST
	};

				VarTypeComponent	(Type type_, int index_)	: type(type_), index(index_) {}
				VarTypeComponent	(void)						: type(TYPE_LAST), index(0) {}

	bool		operator==			(const VarTypeComponent& other) const { return type == other.type && index == other.index; }
	bool		operator!=			(const VarTypeComponent& other) const { return type != other.type || index != other.index; }

	Type		type;
	int			index;
};

typedef std::vector<VarTypeComponent> TypeComponentVector;

// TypeComponentVector utilties.

template <typename Iterator>
bool			isValidTypePath		(const VarType& type, Iterator begin, Iterator end);

template <typename Iterator>
VarType			getVarType			(const VarType& type, Iterator begin, Iterator end);

inline bool		isValidTypePath		(const VarType& type, const TypeComponentVector& path) { return isValidTypePath(type, path.begin(), path.end()); }
inline VarType	getVarType			(const VarType& type, const TypeComponentVector& path) { return getVarType(type, path.begin(), path.end()); }

std::string		parseVariableName	(const char* nameWithPath);
void			parseTypePath		(const char* nameWithPath, const VarType& type, TypeComponentVector& path);

// Type path formatter.

struct TypeAccessFormat
{
	TypeAccessFormat (const VarType& type_, const TypeComponentVector& path_) : type(type_), path(path_) {}

	const VarType&					type;
	const TypeComponentVector&		path;
};

std::ostream&		operator<<		(std::ostream& str, const TypeAccessFormat& format);

// Subtype path builder.

class SubTypeAccess
{
public:
								SubTypeAccess		(const VarType& type);

	SubTypeAccess&				member				(int ndx)	{ m_path.push_back(VarTypeComponent(VarTypeComponent::STRUCT_MEMBER,	ndx)); DE_ASSERT(isValid()); return *this; } //!< Access struct element.
	SubTypeAccess&				element				(int ndx)	{ m_path.push_back(VarTypeComponent(VarTypeComponent::ARRAY_ELEMENT,	ndx)); DE_ASSERT(isValid()); return *this; } //!< Access array element.
	SubTypeAccess&				column				(int ndx)	{ m_path.push_back(VarTypeComponent(VarTypeComponent::MATRIX_COLUMN,	ndx)); DE_ASSERT(isValid()); return *this; } //!< Access column.
	SubTypeAccess&				component			(int ndx)	{ m_path.push_back(VarTypeComponent(VarTypeComponent::VECTOR_COMPONENT,	ndx)); DE_ASSERT(isValid()); return *this; } //!< Access component.
	SubTypeAccess&				parent				(void)		{ DE_ASSERT(!m_path.empty()); m_path.pop_back(); return *this; }

	SubTypeAccess				member				(int ndx) const { return SubTypeAccess(*this).member(ndx);		}
	SubTypeAccess				element				(int ndx) const { return SubTypeAccess(*this).element(ndx);		}
	SubTypeAccess				column				(int ndx) const { return SubTypeAccess(*this).column(ndx);		}
	SubTypeAccess				component			(int ndx) const { return SubTypeAccess(*this).component(ndx);	}
	SubTypeAccess				parent				(void) const	{ return SubTypeAccess(*this).parent();			}

	bool						isValid				(void) const	{ return isValidTypePath(m_type, m_path);		}
	VarType						getType				(void) const	{ return getVarType(m_type, m_path);			}
	const TypeComponentVector&	getPath				(void) const	{ return m_path;								}

	bool						empty				(void) const { return m_path.empty(); }

	bool						operator==			(const SubTypeAccess& other) const { return m_path == other.m_path && m_type == other.m_type; }
	bool						operator!=			(const SubTypeAccess& other) const { return m_path != other.m_path || m_type != other.m_type; }

private:
	VarType						m_type;
	TypeComponentVector			m_path;
};

// Subtype iterator.

// \note VarType must be live during iterator usage.
template <class IsExpanded>
class SubTypeIterator : public std::iterator<std::forward_iterator_tag, VarType>
{
public:
	static SubTypeIterator<IsExpanded>	begin				(const VarType* type) { return SubTypeIterator(type);						}
	static SubTypeIterator<IsExpanded>	end					(const VarType* type) { DE_UNREF(type); return SubTypeIterator(DE_NULL);	}

	bool								operator==			(const SubTypeIterator<IsExpanded>& other) const { return m_type == other.m_type && m_path == other.m_path; }
	bool								operator!=			(const SubTypeIterator<IsExpanded>& other) const { return m_type != other.m_type || m_path != other.m_path; }

	SubTypeIterator<IsExpanded>&		operator++			(void);
	SubTypeIterator<IsExpanded>			operator++			(int)	{ SubTypeIterator<IsExpanded> copy(*this); ++(*this); return copy; }

	void								toStream			(std::ostream& str) const { str << TypeAccessFormat(*m_type, m_path); }
	VarType								getType				(void) const { return getVarType(*m_type, m_path.begin(), m_path.end()); }
	const TypeComponentVector&			getPath				(void) const { return m_path; }

	VarType								operator*			(void) const { return getType(); }

private:
										SubTypeIterator		(const VarType* type);

	void								removeTraversed		(void);
	void								findNext			(void);

	const VarType*						m_type;
	TypeComponentVector					m_path;
};

struct IsBasicType			{ bool operator() (const VarType& type) const { return type.isBasicType(); } };
struct IsScalarType			{ bool operator() (const VarType& type) const { return type.isBasicType() && isDataTypeScalar(type.getBasicType()); } };
struct IsVectorOrScalarType	{ bool operator() (const VarType& type) const { return type.isBasicType() && isDataTypeScalarOrVector(type.getBasicType()); } };

typedef SubTypeIterator<IsBasicType>			BasicTypeIterator;
typedef SubTypeIterator<IsVectorOrScalarType>	VectorTypeIterator;
typedef SubTypeIterator<IsScalarType>			ScalarTypeIterator;

template <class IsExpanded>
std::ostream& operator<< (std::ostream& str, const SubTypeIterator<IsExpanded>& iter)
{
	iter.toStream(str);
	return str;
}

template <class IsExpanded>
SubTypeIterator<IsExpanded>::SubTypeIterator (const VarType* type)
	: m_type(type)
{
	if (m_type)
		findNext();
}

template <class IsExpanded>
SubTypeIterator<IsExpanded>& SubTypeIterator<IsExpanded>::operator++ (void)
{
	if (!m_path.empty())
	{
		// Remove traversed nodes.
		removeTraversed();

		if (!m_path.empty())
			findNext();
		else
			m_type = DE_NULL; // Unset type to signal end.
	}
	else
	{
		// First type was already expanded.
		DE_ASSERT(IsExpanded()(getVarType(*m_type, m_path)));
		m_type = DE_NULL;
	}

	return *this;
}

template <class IsExpanded>
void SubTypeIterator<IsExpanded>::removeTraversed (void)
{
	DE_ASSERT(m_type && !m_path.empty());

	// Pop traversed nodes.
	while (!m_path.empty())
	{
		VarTypeComponent&	curComp		= m_path.back();
		VarType				parentType	= getVarType(*m_type, m_path.begin(), m_path.end()-1);

		if (curComp.type == VarTypeComponent::MATRIX_COLUMN)
		{
			DE_ASSERT(isDataTypeMatrix(parentType.getBasicType()));
			if (curComp.index+1 < getDataTypeMatrixNumColumns(parentType.getBasicType()))
				break;
		}
		else if (curComp.type == VarTypeComponent::VECTOR_COMPONENT)
		{
			DE_ASSERT(isDataTypeVector(parentType.getBasicType()));
			if (curComp.index+1 < getDataTypeScalarSize(parentType.getBasicType()))
				break;
		}
		else if (curComp.type == VarTypeComponent::ARRAY_ELEMENT)
		{
			DE_ASSERT(parentType.isArrayType());
			if (curComp.index+1 < parentType.getArraySize())
				break;
		}
		else if (curComp.type == VarTypeComponent::STRUCT_MEMBER)
		{
			DE_ASSERT(parentType.isStructType());
			if (curComp.index+1 < parentType.getStructPtr()->getNumMembers())
				break;
		}

		m_path.pop_back();
	}
}

template <class IsExpanded>
void SubTypeIterator<IsExpanded>::findNext (void)
{
	if (!m_path.empty())
	{
		// Increment child counter in current level.
		VarTypeComponent& curComp = m_path.back();
		curComp.index += 1;
	}

	for (;;)
	{
		VarType curType = getVarType(*m_type, m_path);

		if (IsExpanded()(curType))
			break;

		// Recurse into child type.
		if (curType.isBasicType())
		{
			DataType basicType = curType.getBasicType();

			if (isDataTypeMatrix(basicType))
				m_path.push_back(VarTypeComponent(VarTypeComponent::MATRIX_COLUMN, 0));
			else if (isDataTypeVector(basicType))
				m_path.push_back(VarTypeComponent(VarTypeComponent::VECTOR_COMPONENT, 0));
			else
				DE_ASSERT(false); // Can't expand scalars - IsExpanded() is buggy.
		}
		else if (curType.isArrayType())
			m_path.push_back(VarTypeComponent(VarTypeComponent::ARRAY_ELEMENT, 0));
		else if (curType.isStructType())
			m_path.push_back(VarTypeComponent(VarTypeComponent::STRUCT_MEMBER, 0));
		else
			DE_ASSERT(false);
	}
}

template <typename Iterator>
bool isValidTypePath (const VarType& type, Iterator begin, Iterator end)
{
	const VarType*	curType		= &type;
	Iterator		pathIter	= begin;

	// Process struct member and array element parts of path.
	while (pathIter != end)
	{
		if (pathIter->type == VarTypeComponent::STRUCT_MEMBER)
		{
			if (!curType->isStructType() || !de::inBounds(pathIter->index, 0, curType->getStructPtr()->getNumMembers()))
				return false;

			curType = &curType->getStructPtr()->getMember(pathIter->index).getType();
		}
		else if (pathIter->type == VarTypeComponent::ARRAY_ELEMENT)
		{
			if (!curType->isArrayType() || (curType->getArraySize() != VarType::UNSIZED_ARRAY && !de::inBounds(pathIter->index, 0, curType->getArraySize())))
				return false;

			curType = &curType->getElementType();
		}
		else
			break;

		++pathIter;
	}

	if (pathIter != end)
	{
		DE_ASSERT(pathIter->type == VarTypeComponent::MATRIX_COLUMN || pathIter->type == VarTypeComponent::VECTOR_COMPONENT);

		// Current type should be basic type.
		if (!curType->isBasicType())
			return false;

		DataType basicType = curType->getBasicType();

		if (pathIter->type == VarTypeComponent::MATRIX_COLUMN)
		{
			if (!isDataTypeMatrix(basicType))
				return false;

			basicType = getDataTypeFloatVec(getDataTypeMatrixNumRows(basicType));
			++pathIter;
		}

		if (pathIter != end && pathIter->type == VarTypeComponent::VECTOR_COMPONENT)
		{
			if (!isDataTypeVector(basicType))
				return false;

			basicType = getDataTypeScalarType(basicType);
			++pathIter;
		}
	}

	return pathIter == end;
}

template <typename Iterator>
VarType getVarType (const VarType& type, Iterator begin, Iterator end)
{
	TCU_CHECK(isValidTypePath(type, begin, end));

	const VarType*	curType		= &type;
	Iterator		pathIter	= begin;

	// Process struct member and array element parts of path.
	while (pathIter != end)
	{
		if (pathIter->type == VarTypeComponent::STRUCT_MEMBER)
			curType = &curType->getStructPtr()->getMember(pathIter->index).getType();
		else if (pathIter->type == VarTypeComponent::ARRAY_ELEMENT)
			curType = &curType->getElementType();
		else
			break;

		++pathIter;
	}

	if (pathIter != end)
	{
		DataType	basicType	= curType->getBasicType();
		Precision	precision	= curType->getPrecision();

		if (pathIter->type == VarTypeComponent::MATRIX_COLUMN)
		{
			basicType = getDataTypeFloatVec(getDataTypeMatrixNumRows(basicType));
			++pathIter;
		}

		if (pathIter != end && pathIter->type == VarTypeComponent::VECTOR_COMPONENT)
		{
			basicType = getDataTypeScalarType(basicType);
			++pathIter;
		}

		DE_ASSERT(pathIter == end);
		return VarType(basicType, precision);
	}
	else
		return VarType(*curType);
}

} // glu

#endif // _GLUVARTYPEUTIL_HPP
