#include "ExCModeLoader.h"


ExCModelLoader::ExCModelLoader(void)
{

}

ExCModelLoader::ExCModelLoader(std::string FileName)
{
	LoadModel(FileName);
}

ExCModelLoader::~ExCModelLoader(void)
{

}

int ExCModelLoader::LoadModel(std::string FileName)
{
Guard(int ExCModelLoader::LoadModel(std::string FileName))
	if(FileName.find(".exm")==(FileName.length()-4))LoadEXM(FileName);;
	if(FileName.find(".md2")==(FileName.length()-4))LoadMD2(FileName);
	if(FileName.find(".md3")==(FileName.length()-4))LoadMD3(FileName);
	if(FileName.find(".asc")==(FileName.length()-4))LoadASC(FileName);
	if(FileName.find(".3ds")==(FileName.length()-4))Load3DS(FileName);
	if(FileName.find(".obj")==(FileName.length()-4))LoadOBJ(FileName);
	if(FileName.find(".ase")==(FileName.length()-4))LoadASE(FileName);
	return m_VecExcModel.size();
UnGuard
}

void ExCModelLoader::LoadMD3(std::string strFileName)
{
Guard(void ExCModelLoader::LoadMD3(std::string strFileName))
UnGuard
}

void ExCModelLoader::LoadASC(std::string strFileName)
{
Guard(void ExCModelLoader::LoadASC(std::string strFileName))
UnGuard
}

void ExCModelLoader::Load3DS(std::string strFileName)
{
Guard(void ExCModelLoader::Load3DS(std::string strFileName))
UnGuard
}

void ExCModelLoader::LoadOBJ(std::string strFileName)
{
Guard(void ExCModelLoader::LoadOBJ(std::string strFileName))
UnGuard
}

void ExCModelLoader::LoadASE(std::string strFileName)
{
Guard(void ExCModelLoader::LoadASE(std::string strFileName))
UnGuard
}

void ExCModelLoader::LoadEXM(std::string strFileName)
{
Guard(void ExCModelLoader::LoadEXM(std::string strFileName))
	std::cout<<"Loading EXM Model"<<std::endl;
	ExCModelEXM TmpModel;
	m_VecExcModel.push_back(TmpModel);
UnGuard
}

void ExCModelLoader::LoadMD2(std::string strFileName)
{
Guard(void ExCModelLoader::LoadMD2(std::string strFileName))
	std::cout<<"Loading MD2 Model"<<std::endl;
	ExCModelEXM TmpModel;

	//std::vector< std::pair<ExCVec3D , ExCVec3D > >	TmpModel.m_VecTriangle;
	//std::vector<ExCVec3D>		TmpModel.m_VecVertex;

	int i,j;
	FILE *filePtr;                          // file pointer
    int fileLen;                            // length of model file
    char *buffer;                           // file buffer

    MD2_modelHeader_t *modelHeader;             // model header
	MD2_frame_t *frame;                              // frame data
	MD2_stIndex_t *stPtr;                       // texture data
	MD2_mesh_t *bufIndexPtr;          // index variables
	
	
	std::string Skin;
	Skin=ExNihilo::ExtracValueFromSring(strFileName,"../Data/Modeles/",".md2")+".pcx";
	TmpModel.m_VecTextures.push_back(Skin);
	TmpModel.m_VecTextures.push_back("fire.bmp");

    filePtr = fopen(strFileName.data(), "rb");
    if (filePtr == NULL) 
	{
		throw ExCExpFileNotFound();
	}

	 // find length of file
     fseek(filePtr, 0, SEEK_END);
     fileLen = ftell(filePtr);
     fseek(filePtr, 0, SEEK_SET);
     
     // read entire file into buffer
     buffer = new char [fileLen+1];
     fread(buffer, sizeof(char), fileLen, filePtr);

	 modelHeader = (MD2_modelHeader_t*)buffer; 

/*	 std::ofstream logscale;
	 std::ofstream logfp;
	 std::ofstream logtranslate;
	 std::ofstream logfile;
	 std::ofstream logHeader;
	 std::ofstream logTextureCoord;
	 
	 logscale.open("logscale.txt",std::ios::out);
	 logfp.open("logfp.txt",std::ios::out);
	 logtranslate.open("logtranslate.txt",std::ios::out);
	 logfile.open("logfile.txt",std::ios::out);
	 logHeader.open("logHeader.txt",std::ios::out);
	 logTextureCoord.open("logTextureCoord.txt",std::ios::out);
*/
	std::cout<<"This is used to identify the file: "<<modelHeader->ident<<std::endl;
	std::cout<<"The version number of the file (Musbe 8):"<<modelHeader->version<<std::endl;
	std::cout<<"The skin width in pixels:"<<modelHeader->skinwidth<<std::endl;
	std::cout<<"The skin heighin pixels:"<<modelHeader->skinheight<<std::endl;
	std::cout<<"The size in bytes the frames are:"<<modelHeader->framesize<<std::endl;
	std::cout<<"The number of skins associated with the model:"<<modelHeader->numSkins<<std::endl;
	std::cout<<"The number of vertices (constan for each frame):"<<modelHeader->numXYZ<<std::endl;
	std::cout<<"The number of texture coordinates:"<<modelHeader->numST<<std::endl;
	std::cout<<"The number of faces (polygons):"<<modelHeader->numTris<<std::endl;
	std::cout<<"The number of gl commands:"<<modelHeader->numGLcmds<<std::endl;
	std::cout<<"The number of animation frames:"<<modelHeader->numFrames<<std::endl;
	std::cout<<"The offset in the file for the skin data:"<<modelHeader->offsetSkins<<std::endl;
	std::cout<<"The offset in the file for the texture data:"<<modelHeader->offsetST<<std::endl;
	std::cout<<"The offset in the file for the face data:"<<modelHeader->offsetTris<<std::endl;
	std::cout<<"The offset in the file for the frames data:"<<modelHeader->offsetFrames<<std::endl;
	std::cout<<"The offset in the file for the gl commands data:"<<modelHeader->offsetGLcmds<<std::endl;
	std::cout<<"The end of the file offset:"<<modelHeader->offsetEnd<<std::endl;
	
	//-----------------------------------------------
	//read all skin
	//-----------------------------------------------
	std::cout<<"read all skin"<<std::endl;
	char mybuff[65];
	std::string BuffSkin;
    fseek(filePtr,modelHeader->offsetSkins, SEEK_SET);
	for(i = 0;i<modelHeader->numSkins;++i)
	{
		fread(&mybuff,sizeof(char),64, filePtr);
		BuffSkin=mybuff;
		//std::cout<<BuffSkin<<std::endl;
		//m_VecSkin.push_back(BuffSkin);
	}
	//-----------------------------------------------
	//read vertex  data 
	//-----------------------------------------------
	std::cout<<"read vertex  data "<<std::endl;
	 ExCVec3D Vec3D;
	 for (j = 0; j < modelHeader->numFrames; j++)
     {
          frame = (MD2_frame_t*)&buffer[modelHeader->offsetFrames+ modelHeader->framesize * j];
          for (i = 0; i < modelHeader->numXYZ; i++)
          {
				Vec3D.SetX(frame->scale[0] * frame->fp[i].v[0] + frame->translate[0]);
				Vec3D.SetY(frame->scale[1] * frame->fp[i].v[1] + frame->translate[1]);
				Vec3D.SetZ(frame->scale[2] * frame->fp[i].v[2] + frame->translate[2]);
				Vec3D=Vec3D/3;
				TmpModel.m_VecVertex.push_back(Vec3D);

	/*			logscale<<"X:"<<frame->scale[0]<<" Y:"<<frame->scale[1]<<" Z:"<<frame->scale[2]<<std::endl;
				logfp<<"X:"<<frame->fp[i].v[0]<<" Y:"<<frame->fp[i].v[1]<<" Z:"<<frame->fp[i].v[2]<<std::endl;
				logtranslate<<"X:"<<frame->translate[0]<<" Y:"<<frame->translate[1]<<" Z:"<<frame->translate[2]<<std::endl;
				logfile<<"vec :"<<i<<" "<<Vec3D<<std::endl;*/
          }
		  //logfile<<"------------------------------------------------------------------"<<std::endl;
     }
	//-----------------------------------------------
	//read triangles data 
	//-----------------------------------------------
	 std::cout<<"read triangles data "<<std::endl;
	fseek(filePtr,modelHeader->offsetTris, SEEK_SET);
	short AB,BC,CA,TAB,TBC,TCA;
	ExCVec3D VertexNum,TexturNum;
	/*std::ofstream logTri;
	logTri.open("logTri.txt",std::ios::out);
	*/
	    
     // point to triangle indexes in buffer
    bufIndexPtr = (MD2_mesh_t*)&buffer[modelHeader->offsetTris]; 
	// create a mesh (triangle) list
     for (j = 0; j < modelHeader->numFrames; j++)         
     {
          // for all triangles in each frame
          for(i = 0; i < modelHeader->numTris; i++)
          {
               AB = bufIndexPtr[i].meshIndex[0];
               BC = bufIndexPtr[i].meshIndex[1];
               CA = bufIndexPtr[i].meshIndex[2];
               TAB = bufIndexPtr[i].stIndex[0];
               TBC = bufIndexPtr[i].stIndex[1];
               TCA = bufIndexPtr[i].stIndex[2];
			
			VertexNum.SetValue(AB,BC,CA);
			TexturNum.SetValue(TAB,TBC,TCA);
			std::pair<ExCVec3D,ExCVec3D> tmp(VertexNum,TexturNum);
			TmpModel.m_VecTriangle.push_back(tmp);
		//	logTri<<"AB:"<<AB<<" BC:"<<BC<<" CA:"<<CA<<std::endl;
		//	logTri<<"TAB:"<<TAB<<" TBC:"<<TBC<<" TCA:"<<TCA<<std::endl;
          }
     }
	//-----------------------------------------------
	//read texture coord  data 
	//-----------------------------------------------
	std::cout<<"read texture coord  data "<<std::endl;
	std::vector<ExCVec2D>		*VecTexture;
	VecTexture= new std::vector<ExCVec2D>;	
	stPtr = (MD2_stIndex_t*)&buffer[modelHeader->offsetST];
	for (i = 0; i < modelHeader->numST; i++)
	{
		VecTexture->push_back(ExCVec2D(((float)stPtr[i].s / (float)modelHeader->skinwidth),((float)stPtr[i].t / (float)modelHeader->skinheight)));
	}
	//------------------------------
	//Build Texture Array
	//------------------------------
	std::cout<<"Build Texture Array"<<std::endl;
	TmpModel.TabTextures= new float[modelHeader->numTris*6];
	for(i = 0; i < modelHeader->numTris; i++)
	{
		TmpModel.TabTextures[0+i*6]=VecTexture->at(TmpModel.m_VecTriangle.at(i).second.GetY()).GetX();
		TmpModel.TabTextures[1+i*6]=VecTexture->at(TmpModel.m_VecTriangle.at(i).second.GetY()).GetY();
		TmpModel.TabTextures[2+i*6]=VecTexture->at(TmpModel.m_VecTriangle.at(i).second.GetX()).GetX();
		TmpModel.TabTextures[3+i*6]=VecTexture->at(TmpModel.m_VecTriangle.at(i).second.GetX()).GetY();
		TmpModel.TabTextures[4+i*6]=VecTexture->at(TmpModel.m_VecTriangle.at(i).second.GetZ()).GetX();
		TmpModel.TabTextures[5+i*6]=VecTexture->at(TmpModel.m_VecTriangle.at(i).second.GetZ()).GetY();
	}
	TmpModel.m_numTriangles=modelHeader->numTris;
/*	//------------------------------
	//Build Vertex Array
	//------------------------------
	std::cout<<"Build Vertex Array size:"<<modelHeader->numFrames*modelHeader->numXYZ*3<<std::endl;
	ExCVec3D VecAB,VecBC,VecCA;
	TmpModel.TabVertices= new float[modelHeader->numFrames*modelHeader->numTris*9];


	//int k=modelHeader->numXYZ*108;
	int FrameToDraw;
	std::cout<<"Number Frame:"<<modelHeader->numFrames<<std::endl;
	for(int k = 0; k < modelHeader->numFrames; k++)
	{
		FrameToDraw=modelHeader->numXYZ*k;
		//std::cout<<"Fisrt indices of frame To Draw:"<<FrameToDraw<<std::endl;
		//std::cout<<"Frame*k:"<<k*modelHeader->numFrames<<std::endl;
		//std::cout<<"First:"<<(0+i*9)+modelHeader->numTris*9*k<<std::endl;
		for(i = 0; i < modelHeader->numTris; i++)
		{
			//----------------
			//Vertex coord
			//----------------
			VecAB.SetX(TmpModel.m_VecVertex.at(TmpModel.m_VecTriangle.at(i).first.GetX()+FrameToDraw).GetX());
			VecAB.SetY(TmpModel.m_VecVertex.at(TmpModel.m_VecTriangle.at(i).first.GetX()+FrameToDraw).GetY());
			VecAB.SetZ(TmpModel.m_VecVertex.at(TmpModel.m_VecTriangle.at(i).first.GetX()+FrameToDraw).GetZ());		

			VecBC.SetX(TmpModel.m_VecVertex.at(TmpModel.m_VecTriangle.at(i).first.GetY()+FrameToDraw).GetX());
			VecBC.SetY(TmpModel.m_VecVertex.at(TmpModel.m_VecTriangle.at(i).first.GetY()+FrameToDraw).GetY());
			VecBC.SetZ(TmpModel.m_VecVertex.at(TmpModel.m_VecTriangle.at(i).first.GetY()+FrameToDraw).GetZ());

			VecCA.SetX(TmpModel.m_VecVertex.at(TmpModel.m_VecTriangle.at(i).first.GetZ()+FrameToDraw).GetX());
			VecCA.SetY(TmpModel.m_VecVertex.at(TmpModel.m_VecTriangle.at(i).first.GetZ()+FrameToDraw).GetY());
			VecCA.SetZ(TmpModel.m_VecVertex.at(TmpModel.m_VecTriangle.at(i).first.GetZ()+FrameToDraw).GetZ());
			//--------------
			//Build array with new vertex data
			//--------------
				//std::cout<<"First:"<<(0+i*9)+k*modelHeader->numFrames<<std::endl;
				TmpModel.TabVertices[(0+i*9)+modelHeader->numTris*9*k]=VecBC.GetX();
				TmpModel.TabVertices[(1+i*9)+modelHeader->numTris*9*k]=VecBC.GetY();
				TmpModel.TabVertices[(2+i*9)+modelHeader->numTris*9*k]=VecBC.GetZ();
				TmpModel.TabVertices[(3+i*9)+modelHeader->numTris*9*k]=VecAB.GetX();
				TmpModel.TabVertices[(4+i*9)+modelHeader->numTris*9*k]=VecAB.GetY();
				TmpModel.TabVertices[(5+i*9)+modelHeader->numTris*9*k]=VecAB.GetZ();
				TmpModel.TabVertices[(6+i*9)+modelHeader->numTris*9*k]=VecCA.GetX();
				TmpModel.TabVertices[(7+i*9)+modelHeader->numTris*9*k]=VecCA.GetY();
				TmpModel.TabVertices[(8+i*9)+modelHeader->numTris*9*k]=VecCA.GetZ();
				//std::cout<<"Last:"<<(8+i*9)+k*modelHeader->numFrames<<std::endl;

				TmpModel.TabVertices[0+i*9]=VecBC.GetX();
				TmpModel.TabVertices[1+i*9]=VecBC.GetY();
				TmpModel.TabVertices[2+i*9]=VecBC.GetZ();
				TmpModel.TabVertices[3+i*9]=VecAB.GetX();
				TmpModel.TabVertices[4+i*9]=VecAB.GetY();
				TmpModel.TabVertices[5+i*9]=VecAB.GetZ();
				TmpModel.TabVertices[6+i*9]=VecCA.GetX();
				TmpModel.TabVertices[7+i*9]=VecCA.GetY();
				TmpModel.TabVertices[8+i*9]=VecCA.GetZ();
		}
		//std::cout<<"Last:"<<(8+i*9)+modelHeader->numTris*9*k<<std::endl;
	}
*/
	delete VecTexture;
	delete buffer;

	m_VecExcModel.push_back(TmpModel);
UnGuard
}


