#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,

		VTCTYPE_LAST
	};

				VarTypeComponent	(Type type_, int index_)	: type(type_), index(index_) {}
				VarTypeComponent	(void)						: type(VTCTYPE_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:
	using iterator_category = std::forward_iterator_tag;
	using value_type = VarType;
	using difference_type = std::ptrdiff_t;
	using pointer = VarType*;
	using reference = VarType&;

	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
