/*
 * ExNihilo 3D Engine
 * 
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Library General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 * Please read AUTHORS file !!!
 * 
 * $Id: ExCModelASC.cpp,v 1.11 2002/11/19 17:09:51 data Exp $
 *
 */

#include "ExCModelASC.h"

ExCModelASC::ExCModelASC(void)
{
Guard(ExCModelASC::ExCModelASC(void))
	m_NumberObject=-1;
	m_ListId=-1;
	ExCModel::ExCModel();
	SetName("ExCModelASC");
	SetType(typeid(this).name());
UnGuard
}

ExCModelASC::ExCModelASC(std::string FileName)
{
Guard(ExCModelASC::ExCModelASC(std::string FileName))
	m_NumberObject=-1;
	m_ListId=-1;
	LoadFile(FileName);
UnGuard
}

ExCModelASC::~ExCModelASC(void)
{
Guard(ExCModelASC::~ExCModelASC(void))
UnGuard
}

void ExCModelASC::Draw(void)
{
Guard(void ExCModelASC::Draw(void))
	glPushMatrix();
		glDisable(GL_LIGHTING);
		ExCModel::Draw();
		glRotatef(-90,1,0,0);
		if(m_ListId==-1){
			BuildList(RENDER_TEXTURES);
			std::cout<<"build asc list"<<std::endl;
		}
		glCallList(m_ListId);
		glEnable(GL_LIGHTING);
	glPopMatrix();
UnGuard
}

bool ExCModelASC::Load(std::string FileName)
{
Guard(bool ExCModelASC::Load(std::string FileName))
	std::ifstream fin;
	std::string buffer;
	char b[256];
	SetName(ExNihilo::ExtracValueFromSring(FileName,"../Data/Modeles/",".asc"));
	fin.open(FileName.data(),std::ios::in);
	if(fin.is_open())
	{
		try
		{
			do
			{
				memset(b,0,255);
				fin.getline(b,256,'\n');
				ProcessLine(b);
			}while(!fin.eof());
			//build mesh tab
			MeshAsc Mesh;
			for(unsigned int i =0;i<m_VecObject.size();++i)//draw all object
			{
				for(unsigned int j =0;j<m_VecObject.at(i).m_VecFace.size();j++)//draw all face
				{
					Mesh.VecAB.SetX(m_VecObject.at(i).m_VecVertex.at(m_VecObject.at(i).m_VecFace.at(j).GetX()).GetX());
					Mesh.VecAB.SetY(m_VecObject.at(i).m_VecVertex.at(m_VecObject.at(i).m_VecFace.at(j).GetX()).GetY());
					Mesh.VecAB.SetZ(m_VecObject.at(i).m_VecVertex.at(m_VecObject.at(i).m_VecFace.at(j).GetX()).GetZ());		
					
					Mesh.VecBC.SetX(m_VecObject.at(i).m_VecVertex.at(m_VecObject.at(i).m_VecFace.at(j).GetY()).GetX());
					Mesh.VecBC.SetY(m_VecObject.at(i).m_VecVertex.at(m_VecObject.at(i).m_VecFace.at(j).GetY()).GetY());
					Mesh.VecBC.SetZ(m_VecObject.at(i).m_VecVertex.at(m_VecObject.at(i).m_VecFace.at(j).GetY()).GetZ());		
					
					Mesh.VecCA.SetX(m_VecObject.at(i).m_VecVertex.at(m_VecObject.at(i).m_VecFace.at(j).GetZ()).GetX());
					Mesh.VecCA.SetY(m_VecObject.at(i).m_VecVertex.at(m_VecObject.at(i).m_VecFace.at(j).GetZ()).GetY());
					Mesh.VecCA.SetZ(m_VecObject.at(i).m_VecVertex.at(m_VecObject.at(i).m_VecFace.at(j).GetZ()).GetZ());		

		   			Mesh.VecTAB.SetX(m_VecObject.at(i).m_VecTexture.at(m_VecObject.at(i).m_VecFace.at(j).GetX()).GetX());
					Mesh.VecTAB.SetY(m_VecObject.at(i).m_VecTexture.at(m_VecObject.at(i).m_VecFace.at(j).GetX()).GetY());

					Mesh.VecTBC.SetX(m_VecObject.at(i).m_VecTexture.at(m_VecObject.at(i).m_VecFace.at(j).GetY()).GetX());
					Mesh.VecTBC.SetY(m_VecObject.at(i).m_VecTexture.at(m_VecObject.at(i).m_VecFace.at(j).GetY()).GetY());

					Mesh.VecTCA.SetX(m_VecObject.at(i).m_VecTexture.at(m_VecObject.at(i).m_VecFace.at(j).GetZ()).GetX());
					Mesh.VecTCA.SetY(m_VecObject.at(i).m_VecTexture.at(m_VecObject.at(i).m_VecFace.at(j).GetZ()).GetY());
					Mesh.m_Material= m_VecObject.at(i).m_Texture;
					m_VecMesh.push_back(Mesh);
				}
			}
			m_VecObject.clear();//now no need object info
			return true;
		}catch(...){throw ExCExpFileReadError();}
	}
	throw   ExCExpFileNotFound();
	return false;
UnGuard
}

void ExCModelASC::ProcessLine(std::string Line)
{
Guard(void ExCModelASC::ProcessLine(std::string Line))
	if(Line.find("Ambient light color:")!=std::string::npos){//first line of file
		m_AmbiantLight.SetValue(atof(ExNihilo::ExtracValueFromSring(Line,"Red="," ").data()),atof(ExNihilo::ExtracValueFromSring(Line,"Green="," ").data()),atof(ExNihilo::ExtracValueFromSring(Line,"Blue="," ").data()));
	}else if(Line.find("Named object: ")!=std::string::npos){//new object
		m_NumberObject++;
		ObjAsc obj;
        obj.m_ObjectName=ExNihilo::ExtracValueFromSring(Line,"Named object: \"","\"");
        m_VecObject.push_back(obj);
	}else if(Line.find("Face ")!=std::string::npos){//read face info
		m_VecObject.at(m_NumberObject).m_VecFace.push_back(ExCVec3D(atof(ExNihilo::ExtracValueFromSring(Line,"A:"," ").data()),atof(ExNihilo::ExtracValueFromSring(Line,"B:"," ").data()),atof(ExNihilo::ExtracValueFromSring(Line,"C:"," ").data())));
	}else if(Line.find("Material: ")!=std::string::npos){//read material
		m_VecObject.at(m_NumberObject).m_Texture=ExNihilo::ExtracValueFromSring(Line,"Material: \"","\"");
		ManagerTexture->Add(m_VecObject.at(m_NumberObject).m_Texture);
	}else if(Line.find("Smoothing: ")!=std::string::npos){//read smothing
		m_VecObject.at(m_NumberObject).m_Smoothing=atof(ExNihilo::ExtracValueFromSring(Line,"Smoothing: ","\n").data());
	}else if(Line.find("Vertex ")!=std::string::npos){//Vertex data
		if(Line.find("Vertex list:")!=std::string::npos){return;}//do nothing
    	m_VecObject.at(m_NumberObject).m_VecVertex.push_back(ExCVec3D(atof(ExNihilo::ExtracValueFromSring(Line,"X:"," ").data()),atof(ExNihilo::ExtracValueFromSring(Line,"Y:"," ").data()),atof(ExNihilo::ExtracValueFromSring(Line,"Z:"," ").data())));
		if(Line.find("U:")!=std::string::npos){m_VecObject.at(m_NumberObject).m_VecTexture.push_back(ExCVec2D(atof(ExNihilo::ExtracValueFromSring(Line,"U:"," ").data()),atof(ExNihilo::ExtracValueFromSring(Line,"V:"," ").data())));}
	}
UnGuard
}

void ExCModelASC::BuildList(int Rendu)
{
Guard(void ExCModelASC::BuildList(int Rendu))
   	glDeleteLists(m_ListId,1);	//delete old list
	m_ListId=glGenLists(1);	//Ask for a new free list
	glNewList(m_ListId,GL_COMPILE);
		glPushAttrib(GL_ALL_ATTRIB_BITS);
			glEnable(GL_TEXTURE_2D);
			for(unsigned int i=0;i<m_VecMesh.size();i++)
			{
				ManagerTexture->SetCurrentObject(m_VecMesh.at(i).m_Material);
				glBegin(GL_TRIANGLES);
					glTexCoord2fv(m_VecMesh.at(i).VecTAB.m_Vector);glVertex3fv(m_VecMesh.at(i).VecAB.m_Vector);
					glTexCoord2fv(m_VecMesh.at(i).VecTBC.m_Vector);glVertex3fv(m_VecMesh.at(i).VecBC.m_Vector);
					glTexCoord2fv(m_VecMesh.at(i).VecTCA.m_Vector);glVertex3fv(m_VecMesh.at(i).VecCA.m_Vector);    
				glEnd();
			}
		glPopAttrib();
	glEndList();
	//delete object data because data are now in list
	m_VecMesh.clear();
	m_VecObject.clear();
UnGuard
}