/*-------------------------------------------------------------------------
 * 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.
 *//*--------------------------------------------------------------------*/

#include "gluVarType.hpp"
#include "deStringUtil.hpp"
#include "deArrayUtil.hpp"

namespace glu
{

VarType::VarType (void)
	: m_type(TYPE_LAST)
{
}

VarType::VarType (const VarType& other)
	: m_type(TYPE_LAST)
{
	*this = other;
}

VarType::VarType (DataType basicType, Precision precision)
	: m_type(TYPE_BASIC)
{
	m_data.basic.type		= basicType;
	m_data.basic.precision	= precision;
}

VarType::VarType (const VarType& elementType, int arraySize)
	: m_type(TYPE_ARRAY)
{
	DE_ASSERT(arraySize >= 0 || arraySize == UNSIZED_ARRAY);
	m_data.array.size			= arraySize;
	m_data.array.elementType	= new VarType(elementType);
}

VarType::VarType (const StructType* structPtr)
	: m_type(TYPE_STRUCT)
{
	m_data.structPtr = structPtr;
}

VarType::~VarType (void)
{
	if (m_type == TYPE_ARRAY)
		delete m_data.array.elementType;
}

VarType& VarType::operator= (const VarType& other)
{
	if (this == &other)
		return *this; // Self-assignment.

	if (m_type == TYPE_ARRAY)
		delete m_data.array.elementType;

	m_type	= other.m_type;
	m_data	= Data();

	if (m_type == TYPE_ARRAY)
	{
		m_data.array.elementType	= new VarType(*other.m_data.array.elementType);
		m_data.array.size			= other.m_data.array.size;
	}
	else
		m_data = other.m_data;

	return *this;
}

int VarType::getScalarSize (void) const
{
	switch (m_type)
	{
		case TYPE_BASIC:	return glu::getDataTypeScalarSize(m_data.basic.type);
		case TYPE_ARRAY:	return m_data.array.elementType->getScalarSize()*m_data.array.size;

		case TYPE_STRUCT:
		{
			int size = 0;
			for (StructType::ConstIterator iter = m_data.structPtr->begin(); iter != m_data.structPtr->end(); iter++)
				size += iter->getType().getScalarSize();
			return size;
		}

		default:
			DE_ASSERT(false);
			return 0;
	}
}

bool VarType::operator== (const VarType& other) const
{
	if (m_type != other.m_type)
		return false;

	switch (m_type)
	{
		case TYPE_BASIC:
			return	m_data.basic.type == other.m_data.basic.type &&
					m_data.basic.precision == other.m_data.basic.precision;

		case TYPE_ARRAY:
			return	*m_data.array.elementType == *other.m_data.array.elementType &&
					m_data.array.size == other.m_data.array.size;

		case TYPE_STRUCT:
			return m_data.structPtr == other.m_data.structPtr;

		default:
			DE_ASSERT(false);
			return 0;
	}
}

bool VarType::operator!= (const VarType& other) const
{
	return !(*this == other);
}

// StructMember implementation

bool StructMember::operator== (const StructMember& other) const
{
	return (m_name == other.m_name) && (m_type == other.m_type);
}

bool StructMember::operator!= (const StructMember& other) const
{
	return !(*this == other);
}

// StructType implementation.

void StructType::addMember (const char* name, const VarType& type)
{
	m_members.push_back(StructMember(name, type));
}

bool StructType::operator== (const StructType& other) const
{
	return (m_typeName == other.m_typeName) && (m_members == other.m_members);
}

bool StructType::operator!= (const StructType& other) const
{
	return !(*this == other);
}

const char* getStorageName (Storage storage)
{
	static const char* const s_names[] = { "in", "out", "const", "uniform", "buffer", "patch in", "patch out" };

	return de::getSizedArrayElement<STORAGE_LAST>(s_names, storage);
}

const char* getInterpolationName (Interpolation interpolation)
{
	static const char* const s_names[] = { "smooth", "flat", "centroid" };

	return de::getSizedArrayElement<INTERPOLATION_LAST>(s_names, interpolation);
}

const char* getFormatLayoutName (FormatLayout layout)
{
	static const char* s_names[] =
	{
		"rgba32f",			// FORMATLAYOUT_RGBA32F
		"rgba16f",			// FORMATLAYOUT_RGBA16F
		"r32f",				// FORMATLAYOUT_R32F
		"rgba8",			// FORMATLAYOUT_RGBA8
		"rgba8_snorm",		// FORMATLAYOUT_RGBA8_SNORM
		"rgba32i",			// FORMATLAYOUT_RGBA32I
		"rgba16i",			// FORMATLAYOUT_RGBA16I
		"rgba8i",			// FORMATLAYOUT_RGBA8I
		"r32i",				// FORMATLAYOUT_R32I
		"rgba32ui",			// FORMATLAYOUT_RGBA32UI
		"rgba16ui",			// FORMATLAYOUT_RGBA16UI
		"rgba8ui",			// FORMATLAYOUT_RGBA8UI
		"r32ui",			// FORMATLAYOUT_R32UI
	};

	return de::getSizedArrayElement<FORMATLAYOUT_LAST>(s_names, layout);
}

const char* getMemoryAccessQualifierName (MemoryAccessQualifier qualifier)
{
	switch (qualifier)
	{
		case MEMORYACCESSQUALIFIER_COHERENT_BIT:	return "coherent";
		case MEMORYACCESSQUALIFIER_VOLATILE_BIT:	return "volatile";
		case MEMORYACCESSQUALIFIER_RESTRICT_BIT:	return "restrict";
		case MEMORYACCESSQUALIFIER_READONLY_BIT:	return "readonly";
		case MEMORYACCESSQUALIFIER_WRITEONLY_BIT:	return "writeonly";
		default:
			DE_ASSERT(false);
			return DE_NULL;
	}
}

const char* getMatrixOrderName (MatrixOrder qualifier)
{
	static const char* s_names[] =
	{
		"column_major",	// MATRIXORDER_COLUMN_MAJOR
		"row_major",	// MATRIXORDER_ROW_MAJOR
	};

	return de::getSizedArrayElement<MATRIXORDER_LAST>(s_names, qualifier);
}

// Layout Implementation

Layout::Layout (int location_, int binding_, int offset_, FormatLayout format_, MatrixOrder matrixOrder_)
	: location			(location_)
	, binding			(binding_)
	, offset			(offset_)
	, format			(format_)
	, matrixOrder		(matrixOrder_)
{
}

bool Layout::operator== (const Layout& other) const
{
	return	location == other.location &&
			binding == other.binding &&
			offset == other.offset &&
			format == other.format &&
			matrixOrder == other.matrixOrder;
}

bool Layout::operator!= (const Layout& other) const
{
	return !(*this == other);
}

// VariableDeclaration Implementation

VariableDeclaration::VariableDeclaration (const VarType& varType_, const std::string& name_, Storage storage_, Interpolation interpolation_, const Layout& layout_, deUint32 memoryAccessQualifierBits_)
	: layout						(layout_)
	, interpolation					(interpolation_)
	, storage						(storage_)
	, varType						(varType_)
	, memoryAccessQualifierBits		(memoryAccessQualifierBits_)
	, name							(name_)
{
}

bool VariableDeclaration::operator== (const VariableDeclaration& other) const
{
	return	layout == other.layout &&
			interpolation == other.interpolation &&
			storage == other.storage &&
			varType == other.varType &&
			memoryAccessQualifierBits == other.memoryAccessQualifierBits &&
			name == other.name;
}

bool VariableDeclaration::operator!= (const VariableDeclaration& other) const
{
	return !(*this == other);
}

// InterfaceBlock Implementation

InterfaceBlock::InterfaceBlock (void)
	: layout						(Layout())
	, storage						(glu::STORAGE_LAST)
	, memoryAccessQualifierFlags	(0)
{
}

// Declaration utilties.

std::ostream& operator<< (std::ostream& str, const Layout& layout)
{
	std::vector<std::string> layoutDeclarationList;

	if (layout.location != -1)
		layoutDeclarationList.push_back("location=" + de::toString(layout.location));

	if (layout.binding != -1)
		layoutDeclarationList.push_back("binding=" + de::toString(layout.binding));

	if (layout.offset != -1)
		layoutDeclarationList.push_back("offset=" + de::toString(layout.offset));

	if (layout.format != FORMATLAYOUT_LAST)
		layoutDeclarationList.push_back(getFormatLayoutName(layout.format));

	if (layout.matrixOrder != MATRIXORDER_LAST)
		layoutDeclarationList.push_back(getMatrixOrderName(layout.matrixOrder));

	if (!layoutDeclarationList.empty())
	{
		str << "layout(" << layoutDeclarationList[0];

		for (int layoutNdx = 1; layoutNdx < (int)layoutDeclarationList.size(); ++layoutNdx)
			str << ", " << layoutDeclarationList[layoutNdx];

		str << ")";
	}

	return str;
}

std::ostream& operator<< (std::ostream& str, const VariableDeclaration& decl)
{
	if (decl.layout != Layout())
		str << decl.layout << " ";

	for (int bitNdx = 0; (1 << bitNdx) & MEMORYACCESSQUALIFIER_MASK; ++bitNdx)
		if (decl.memoryAccessQualifierBits & (1 << bitNdx))
			str << getMemoryAccessQualifierName((glu::MemoryAccessQualifier)(1 << bitNdx)) << " ";

	if (decl.interpolation != INTERPOLATION_LAST)
		str << getInterpolationName(decl.interpolation) << " ";

	if (decl.storage != STORAGE_LAST)
		str << getStorageName(decl.storage) << " ";

	str << declare(decl.varType, decl.name);

	return str;
}

namespace decl
{

std::ostream& operator<< (std::ostream& str, const Indent& indent)
{
	for (int i = 0; i < indent.level; i++)
		str << "\t";
	return str;
}

std::ostream& operator<< (std::ostream& str, const DeclareVariable& decl)
{
	const VarType&		type	= decl.varType;
	const VarType*		curType	= &type;
	std::vector<int>	arraySizes;

	// Handle arrays.
	while (curType->isArrayType())
	{
		arraySizes.push_back(curType->getArraySize());
		curType = &curType->getElementType();
	}

	if (curType->isBasicType())
	{
		if (curType->getPrecision() != PRECISION_LAST)
			str << glu::getPrecisionName(curType->getPrecision()) << " ";
		str << glu::getDataTypeName(curType->getBasicType());
	}
	else if (curType->isStructType())
	{
		const StructType* structPtr = curType->getStructPtr();

		if (structPtr->hasTypeName())
			str << structPtr->getTypeName();
		else
			str << declare(structPtr, decl.indentLevel); // Generate inline declaration.
	}
	else
		DE_ASSERT(false);

	str << " " << decl.name;

	// Print array sizes.
	for (std::vector<int>::const_iterator sizeIter = arraySizes.begin(); sizeIter != arraySizes.end(); sizeIter++)
	{
		const int arrSize = *sizeIter;
		if (arrSize == VarType::UNSIZED_ARRAY)
			str << "[]";
		else
			str << "[" << arrSize << "]";
	}

	return str;
}

std::ostream& operator<< (std::ostream& str, const DeclareStructTypePtr& decl)
{
	str << "struct";

	// Type name is optional.
	if (decl.structPtr->hasTypeName())
		str << " " << decl.structPtr->getTypeName();

	str << "\n" << indent(decl.indentLevel) << "{\n";

	for (StructType::ConstIterator memberIter = decl.structPtr->begin(); memberIter != decl.structPtr->end(); memberIter++)
	{
		str << indent(decl.indentLevel+1);
		str << declare(memberIter->getType(), memberIter->getName(), decl.indentLevel+1) << ";\n";
	}

	str << indent(decl.indentLevel) << "}";

	return str;
}

std::ostream& operator<< (std::ostream& str, const DeclareStructType& decl)
{
	return str << declare(&decl.structType, decl.indentLevel);
}

} // decl
} // glu
