/**
* FX Storage
* @version: 12-28-2004
* @author Joseph 'Pcjoe' Florencio
*/

#include "fxsys.h"

/*
* Constructor
*/
CFXData::CFXData()
{	setType(FXDATA_NONE);
}

/*
* Parse 3 float (vector, color)
*/
bool CFXData::parse3Float( TiXmlNode* pData, char format[3] )
{	vec3_t vecVector;

	// Set name
	setName(g_ParseMain.getAttribute(pData, "name"));

	// HACK HACK: strings dont want to convert char to std::string, so i'll hack my way around it
	char szTemp[2];
	szTemp[1] = '\0';
	for(int i = 0; i < 3; i++)
	{	szTemp[0] = format[i];
		// save vector xyz
		vecVector[i] = float(atof(g_ParseMain.getAttribute(pData, szTemp).c_str()));
	}

	// Set vector
	setVectorValue(vecVector);
	return true;
}

/*
* parse Vector
*/
bool CFXData::parseVector( TiXmlNode* pData )
{	return parse3Float(pData, "xyz");
}

/*
* parse Angle
*/
bool CFXData::parseAngle( TiXmlNode* pData )
{	return parse3Float(pData, "ypr");
}

/*
* parse Color
*/
bool CFXData::parseColor( TiXmlNode* pData )
{	return parse3Float(pData, "rgb");
}

/*
* parse Option
*/
bool CFXData::parseOption( TiXmlNode* pData )
{	// copy attribute
	TiXmlElement *pElem = pData->ToElement();
	if(pElem && pElem->FirstAttribute())
	{	setName(pElem->FirstAttribute()->Name());
		setStringValue(pElem->FirstAttribute()->Value());
		return true;
	}
	return false;
}
/*
* parse Array
*/
bool CFXData::parseArray( TiXmlNode* pData )
{	CFXData fxData;
	TiXmlNode* pArray;

	// Get name & set
	std::string strName = g_ParseMain.getAttribute(pData, "name");
	if(strName == "")
	{	return false;
	}
	setName(strName);

	// Iterate through array and add fx options
	IterateXML(pArray, pData)
	{	if(fxData.setData(pArray))
		{	addArray(fxData);
		}
	}
	return true;
}


/*
* DEBUG: Print Data
*/
void CFXData::printData( std::string strPrefix )
{	std::string strPrint;

	if(getType() == FXDATA_SINGLE)
	{	strPrint += strPrefix + getName() + " = ";
		strPrint += getStringValue() + "\n";
	}
	else if(getType() == FXDATA_VECTOR)
	{	strPrint += strPrefix + getName() + " = ";
		char szPrint[64];
		sprintf(szPrint,"%f, %f, %f\n", m_vecValue.x, m_vecValue.y, m_vecValue.z);
		strPrint += szPrint;
	}
	else if(getType() == FXDATA_ARRAY)
	{	// Print array name
		strPrint += strPrefix + getName() + ":\n";
		ConsolePrint(strPrint.c_str());

		// Tab in prefix
		std::string strTab = "\t\t";
		strPrefix = strTab + strPrefix;
		
		// Print array members
		for(unsigned int i = 0; i < m_Array.size(); i++)
		{	m_Array[i].printData(strPrefix);
		}
		return;
	}
	ConsolePrint(strPrint.c_str());
}


/*
* Set Data
*/
bool CFXData::setData( TiXmlNode* pData )
{	// Make sure this node has attributes
	TiXmlElement *pElem = pData->ToElement();
	if(pElem && pElem->FirstAttribute())
	{	
		// Get Name
		std::string strNodeName = pElem->Value();

		// Option
		if(strNodeName==FXDATA_OPTION_S)
		{	if(!parseOption(pData))
			{	return false;
			}
			setType(FXDATA_SINGLE);
		}
		// Vector
		else if(strNodeName==FXDATA_VECTOR_S)
		{	if(!parseVector(pData))
			{	return false;
			}
			setType(FXDATA_VECTOR);
		}
		// Angle
		else if(strNodeName==FXDATA_VECTOR_S)
		{	if(!parseAngle(pData))
			{	return false;
			}
			setType(FXDATA_VECTOR);
		}
		// Color
		else if(strNodeName==FXDATA_COLOR_S)
		{	if(!parseColor(pData))
			{	return false;
			}
			setType(FXDATA_VECTOR);
		}
		// Array (range)
		else if(strNodeName==FXDATA_ARRAY_S)
		{	if(!parseArray(pData))
			{	return false;
			}
			setType(FXDATA_ARRAY);
		}
		// Not a valid type
		else
		{	return false;
		}
	}
	return true;
}


/*
* Get Array Size
*/
int CFXData::getArraySize( void )
{	if(getType()!=FXDATA_ARRAY)
	{	return 0;
	}
	return ((signed)m_Array.size());
}

/*
* Get Array At Index
*/
CFXData *CFXData::getArrayAtIndex( int iIndex )
{	if(iIndex < 0 || iIndex >= getArraySize())
	{	return NULL;
	}
	return (&m_Array[iIndex]);
}

/*
* save Options List
*/
void CFXStorage::saveOptions( CFXStorage *pStorage )
{	if(!pStorage)
	{	return;
	}

	std::map<std::string,CFXData>::iterator iterCopy;
	ForEachIn(iterCopy, pStorage->m_Options)
	{	addOption(iterCopy->first, iterCopy->second);
	}
}

/*
* Add Option
*/
void CFXStorage::addOption( std::string strName, CFXData fxData )
{	m_Options[strName] = fxData;
}

/*
* DEBUG: Print
*/
void CFXStorage::printData( void )
{	std::map<std::string,CFXData>::iterator iterOptions;

	// Print Name
	ConsolePrint("Name - ");
	ConsolePrint(getName().c_str());
	ConsolePrint("\n");

	// Print Options
	ForEachIn(iterOptions, m_Options)
	{	iterOptions->second.printData("* ");
	}

	// space out
	ConsolePrint("\n");
}

/*
* Get FX Data
*/
CFXData *CFXStorage::getFXData( std::string strName )
{	std::map<std::string,CFXData>::iterator iterOptions;
	ForEachIn(iterOptions, m_Options)
	{	if(iterOptions->first == strName)
		{	return (&iterOptions->second);
		}
	}
	return NULL;
}

float CFXStorage::getFXDataFloat( std::string strName )
{	CFXData *pData = getFXData(strName);
	if(!pData)
	{	return 0;
	}
	if(pData->getType() != FXDATA_SINGLE)
	{	return 0;
	}
	return atof(pData->getStringValue().c_str());
}

int CFXStorage::getFXDataInt( std::string strName )
{	return int(getFXDataFloat(strName));
}

std::string CFXStorage::getFXDataString( std::string strName )
{	CFXData *pData = getFXData(strName);
	if(!pData)
	{	return std::string("");
	}
	if(pData->getType() != FXDATA_SINGLE)
	{	return std::string("");
	}
	return pData->getStringValue();
}

vec3_t CFXStorage::getFXDataVector( std::string strName )
{	CFXData *pData = getFXData(strName);
	if(!pData)
	{	return vec3_t(0,0,0);
	}
	if(pData->getType() != FXDATA_VECTOR)
	{	return vec3_t(0,0,0);
	}
	return pData->getVectorValue();
}

/*
* Range
*/
void CFXStorage::getFXDataFloatRange( float *flRange, std::string strName )
{	CFXData *pData = getFXData(strName);
	if(!pData)
	{	return;
	}
	// No range, just copy value
	if(pData->getType() == FXDATA_SINGLE)
	{	flRange[0] = flRange[1] = atof(pData->getStringValue().c_str());
	}
	// Range
	else if(pData->getType() == FXDATA_ARRAY)
	{	// Range only has two entries
		if(pData->getArraySize() != 2)
		{	return;
		}
		CFXData *pS = pData->getArrayAtIndex(0);
		CFXData *pE = pData->getArrayAtIndex(1);
		if((pS->getType() != FXDATA_SINGLE) || (pE->getType() != FXDATA_SINGLE))
		{	return;
		}
		// Regular order
		if(pE->getName() == "start")
		{	flRange[0] = atof(pS->getStringValue().c_str());
			flRange[1] = atof(pE->getStringValue().c_str());
		}
		// reverse
		else
		{	flRange[1] = atof(pS->getStringValue().c_str());
			flRange[0] = atof(pE->getStringValue().c_str());
		}
	}
}

void CFXStorage::getFXDataColorRange( float *flColorA, float *flColorB, std::string strName )
{	CFXData *pData = getFXData(strName);
	vec3_t vecValueA;
	vec3_t vecValueB;
	int i;
	if(!pData)
	{	return;
	}
	// No range, just copy value
	if(pData->getType() == FXDATA_VECTOR)
	{	vecValueA = pData->getVectorValue();
		for(i=0;i<3;i++)
		{	flColorA[i] = vecValueA[i];
			flColorB[i] = vecValueA[i];
		}
	}
	// Range
	else if(pData->getType() == FXDATA_ARRAY)
	{	// Range only has two entries
		if(pData->getArraySize() != 2)
		{	return;
		}
		CFXData *pS = pData->getArrayAtIndex(0);
		CFXData *pE = pData->getArrayAtIndex(1);
		if((pS->getType() != FXDATA_VECTOR) || (pE->getType() != FXDATA_VECTOR))
		{	return;
		}
		vecValueA = pS->getVectorValue();
		vecValueB = pE->getVectorValue();
		// Regular order
		if(pS->getName() == "min" || pS->getName() == "start")
		{	for(i=0;i<3;i++)
			{	flColorA[i] = vecValueA[i];
				flColorB[i] = vecValueB[i];
			}
		}
		// reverse
		else
		{	for(i=0;i<3;i++)
			{	flColorB[i] = vecValueA[i];
				flColorA[i] = vecValueB[i];
			}
		}
	}
}

void CFXStorage::getFXDataVectorRange( vec3_t *vecRange, std::string strName )
{	CFXData *pData = getFXData(strName);
	if(!pData)
	{	return;
	}
	// No range, just copy value
	if(pData->getType() == FXDATA_VECTOR)
	{	VectorCopy(pData->getVectorValue(),vecRange[0]);
		VectorCopy(pData->getVectorValue(),vecRange[1]);
	}
	// Range
	else if(pData->getType() == FXDATA_ARRAY)
	{	// Range only has two entries
		if(pData->getArraySize() != 2)
		{	return;
		}
		CFXData *pS = pData->getArrayAtIndex(0);
		CFXData *pE = pData->getArrayAtIndex(1);
		if((pS->getType() != FXDATA_VECTOR) || (pE->getType() != FXDATA_VECTOR))
		{	return;
		}
		// Regular order
		if(pS->getName() == "min" || pS->getName() == "start")
		{	VectorCopy(pS->getVectorValue(), vecRange[0]);
			VectorCopy(pE->getVectorValue(), vecRange[1]);
		}
		// reverse
		else
		{	VectorCopy(pS->getVectorValue(), vecRange[1]);
			VectorCopy(pE->getVectorValue(), vecRange[0]);
		}
	}
}