#include "CAseModel.h"
#include "../GLDef.h"
#include <fstream>

std::string NactiText(ifstream is)
{
	/*char temp[255];
	bool konec=0;
	while(!konec)
	{
		is >> temp;
	}*/
	return 0;
}

// Pokud najde vrati T, pokud nenajde a je konec souboru(end.) tak F.
void Najdi(ifstream &is, std::string text)
{
	char temp[255];
	is >> temp;
	while( strcmp(temp, text.c_str()) )
	{
		is >> temp;
	}
}

//////////////////////////////////////////////////////////////////////////
// Construktor - 
//////////////////////////////////////////////////////////////////////////
C_ASEMODEL_0::C_ASEMODEL_0()
{
	_SetError("begin");
	_bVBO = 0;
	_renMode = GL_TRIANGLES;

	pRender = C_ASEMODEL_0::_RenderObject;
}

//////////////////////////////////////////////////////////////////////////
// Des. - 
//////////////////////////////////////////////////////////////////////////
C_ASEMODEL_0::~C_ASEMODEL_0()
{

}

C_ASEMODEL_0::_SetError(std::string name_er)
{
	_sError = name_er;
}

int ReadInt(ifstream &is)
{
	int i;
	is.read((char*)&i, sizeof(i));
	return i;
}
float ReadFloat(ifstream &is)
{
	float f;
	is.read((char*)&f, sizeof(f));
	return f;
}
char ReadChar(ifstream &is)
{
	char c;
	is.read((char*)&c, sizeof(c));
	return c;
}

//////////////////////////////////////////////////////////////////////////
// LoadModel - 
//////////////////////////////////////////////////////////////////////////
bool C_ASEMODEL_0::LoadModelBinar(std::string name)
{
	ifstream is(name.c_str(), ios::binary);
	int iHeader = 0xF1A6B51A;

	if(ReadInt(is) != 0xF1A6B51A) return FALSE;
	char version = ReadChar(is);
	if(version == 1) _LoadVersion1(is);
	else return FALSE;

	is.close();
	return TRUE;
}

bool C_ASEMODEL_0::_LoadVersion1(ifstream &is)
{
	_num_object = ReadInt(is);
	for(register i=0; i<_num_object; i++)
	{
		T_OBJECT_0 objTemp;
		objTemp.name = "binar";
		// Nacist vertexy
		objTemp.iNumVertex = ReadInt(is)*3; // pocet face
		for(register j=0; j<objTemp.iNumVertex; j++)
		{
			float x = ReadFloat(is);
			float y = ReadFloat(is);
			float z = ReadFloat(is);
			objTemp.vertex.push_back( CVector3(x, y, z) );
		}

		// Nacist texturove coordinaty
		int num_texCoord = ReadInt(is)*3;  // nacte pocet texturovych kordinatu

		for(register k=0; k<num_texCoord; k++)
		{
			float x = ReadFloat(is);
			float y = ReadFloat(is);
			objTemp.texture.push_back( CVector3(x, y, 0) );
		}
		int num_normals = ReadInt(is);
		for(register l=0; l<num_normals*3; l++)
		{
			float x = ReadFloat(is);
			float y = ReadFloat(is);
			float z = ReadFloat(is);
			objTemp.normal.push_back( CVector3(x, y, z) );
		}
		_vObject.push_back(objTemp);
		// Nacist normaly pro facy
	}
	
	return TRUE;
}

void C_ASEMODEL_0::LoadModel(std::string name)
{
	std::string prip = W_GetPripona(name);
	if(prip == "txt")
	{
		if(!LoadModelText(name)) cError.ErrorMsg(0,true,false,"Error","Model error");
	}else
	if(prip == "wfo")
	{
		if(!LoadModelBinar(name)) cError.ErrorMsg(0,true,false,"Error","Model error");
	}
}

//////////////////////////////////////////////////////////////////////////
// LoadModel - 
//////////////////////////////////////////////////////////////////////////
bool C_ASEMODEL_0::LoadModelText(std::string name)
{
	ifstream is;
	char temp[255];
	float version;
	int iTemp=0;
	is.open( name.c_str() );
	if(!is) return FALSE;
	
	is >> temp;
	if( !strcmp(temp, "W_Format_object") )
	{
		is >> version;
	}else
	{
		_SetError("No file format");
		return FALSE;
	}

	Najdi(is, "NUM_OBJECT");
	is >> _num_object;	
	for(register i=0; i<_num_object; i++)
	{
		Najdi(is, "OBJECT");
		T_OBJECT_0 objTemp;
		is >> objTemp.name;
		// Nacist vertexy
		Najdi(is, "NUM_FACE");
		is >> iTemp;
		objTemp.iNumVertex = iTemp*3;
		for(register j=0; j<objTemp.iNumVertex; j++)
		{
			float x, y, z;
			is >> x;
			is >> y;
			is >> z;
			//CVector3 vecTemp(x, y, z);
			objTemp.vertex.push_back( CVector3(x, y, z) );
		}
		// Nacist texturove coordinaty
		Najdi(is, "NUM_FACETEXCOORD");
		is >> iTemp;
		for(register k=0; k<objTemp.iNumVertex; k++)
		{
			float x, y;
			is >> x;
			is >> y;
			objTemp.texture.push_back( CVector3(x, y, 0) );
		}
		Najdi(is, "NUM_NORMALS");
		is >> iTemp;
		for(register l=0; l<objTemp.iNumVertex; l++)
		{
			float x, y, z;
			is >> x >> y >> z;
			objTemp.normal.push_back( CVector3(x, y, z) );
			/*is >> x >> y >> z;
			objTemp.normal.push_back( CVector3(x, y, z) );
			is >> x >> y >> z;
			objTemp.normal.push_back( CVector3(x, y, z) );*/
		}
		_vObject.push_back(objTemp);
		// Nacist normaly pro facy
	}
	
	is.close();
	return TRUE;
}

void C_ASEMODEL_0::Render()
{
	(this->*pRender)();
}

void C_ASEMODEL_0::_RenderObject()
{
	std::vector<T_OBJECT_0>::iterator iter = _vObject.begin();
	glColor3ub(255, 255, 255);
	glEnable(GL_TEXTURE_2D);
	/*bool bLight = (bool)glIsEnabled(GL_LIGHTING);
	if(!bLight) glEnable(GL_LIGHTING);*/
	
	for(; iter != _vObject.end(); iter++)
	{
		int citac=0;
		for(register k=0; k<iter->iNumVertex; k+=3)
		{
			CVector3 a = iter->vertex[k];
			CVector3 b = iter->vertex[k+1];
			CVector3 c = iter->vertex[k+2];

			CVector3 e = iter->texture[k];
			CVector3 f = iter->texture[k+1];
			CVector3 g = iter->texture[k+2];
	
			CVector3 n1 = iter->normal[k];
			CVector3 n2 = iter->normal[k+1];
			CVector3 n3 = iter->normal[k+2];

			glBegin(_renMode);
				glNormal3f(n1.x, n1.y, n1.z);
				glTexCoord2f(e.x, e.y); glVertex3f(a.x, a.y, a.z);
				glNormal3f(n2.x, n2.y, n2.z);
				glTexCoord2f(f.x, f.y); glVertex3f(b.x, b.y, b.z);
				glNormal3f(n3.x, n3.y, n3.z);
				glTexCoord2f(g.x, g.y); glVertex3f(c.x, c.y, c.z);
			glEnd();
		}
	}
	//if(!bLight) glDisable(GL_LIGHTING);
	glDisable(GL_TEXTURE_2D);	
}

void C_ASEMODEL_0::_RenderVA()
{
	glEnableClientState( GL_VERTEX_ARRAY );
	//glEnableClientState( GL_TEXTURE_COORD_ARRAY );
//	glEnableClientState( GL_NORMAL_ARRAY );

//	glNormalPointer(GL_FLOAT, 0,_faceNormal);
	//glTexCoordPointer(2, GL_FLOAT, 0, _coord_ver);
	glVertexPointer(3, GL_FLOAT, 0, &_vObject[0].vertex);
	glDrawArrays(_renMode, 0, _vObject[0].iNumVertex);
	
//	glDisableClientState( GL_NORMAL_ARRAY );
	//glDisableClientState( GL_TEXTURE_COORD_ARRAY );
	glDisableClientState( GL_VERTEX_ARRAY );
}

//////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////
void C_ASEMODEL_0::Translate(float x, float y, float z)
{
	std::vector<T_OBJECT_0>::iterator iter = _vObject.begin();
	for(; iter != _vObject.end(); iter++)
	{
		for(register k=0; k<iter->iNumVertex; k+=3)
		{
			CVector3 *a = &iter->vertex[k];
			CVector3 *b = &iter->vertex[k+1];
			CVector3 *c = &iter->vertex[k+2];

			a->x /= x;
			a->y /= y;
			a->z /= z;
			b->x /= x;
			b->y /= y;
			b->z /= z;
			c->x /= x;
			c->y /= y;
			c->z /= z;
		}
	}
}