/*
 * 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: ExManagerEntity.cpp,v 1.9 2002/12/03 22:40:03 data Exp $
 *
 */

#include "ExManagerEntity.h"

bool ExManagerEntity::m_flag = false; 
ExManagerEntity* ExManagerEntity::m_instance = NULL; 

ExManagerEntity* ExManagerEntity::CreateSingleton(void){
Guard(ExManagerEntity* ExManagerEntity::CreateSingleton(void))
	if(!m_flag)
	{
		m_flag = true; // We are creating the error log now, so set flag to true
		m_instance = new ExManagerEntity; // Create the error log
	}else
	{
		std::cout<<"Error singleton already created"<<std::endl;
	}
	return m_instance; 
UnGuard
}

ExManagerEntity::ExManagerEntity(void)
{
}

ExManagerEntity::~ExManagerEntity(void)
{
}

void ExManagerEntity::Reset(void)
{
	ExManagerObject<ExCEntity *>::Reset();
}

void ExManagerEntity::Init(void)
{
Guard(void ExManagerEntity::Init(void))
	ExManagerObject<ExCEntity *>::Init();
UnGuard
}

EntityType ExManagerEntity::GetEntityType(std::string FileName)
{
	std::string buffstring;
	buffstring=ExNihilo::ExtracStringValueFromFile(FileName,"<Type>","<#Type>");
	if(strcmpi(buffstring.data(),"ExCEntity")==0)return ENTITY;
	if(strcmpi(buffstring.data(),"ExCGroupEntity")==0)return ENTITY_GROUP;
	return ENTITY_UNKNOWN;
}

void ExManagerEntity::Draw(void)
{
	//Draw here only if PVS is not active
	for(m_ItMap=m_Map->begin();m_ItMap!=m_Map->end();m_ItMap++)
	{
		m_ItMap->second->Draw();
	}
}


void ExManagerEntity::Load(std::string FileName)
{
Guard(void ExManagerEntity::Load(std::string FileName))
	ExCEntity *Entity;
	switch(GetEntityType(FileName))
	{
	case ENTITY:	Entity= new ExCEntity;break;
	case ENTITY_GROUP:
		//Entity = new ExCGroupEntity;
		LoadGroupe(FileName);
		return;
		break;
	case ENTITY_UNKNOWN:std::cout<<"Bad file type"<<std::endl;return;
	}
	
	Entity->SetManagerGizmo(ManagerGizmo);
	
	Entity->SetManagerMesh(ManagerMesh);
	
	Entity->SetManagerModel(ManagerModel);
	
	Entity->SetManagerId(ManagerId);
	
	Entity->SetFileName(FileName);
	
	if(Entity->LoadFile(FileName))Add(Entity);
UnGuard
}
void ExManagerEntity::LoadGroupe(std::string FileName)
{
Guard(void ExManagerEntity::LoadGroupe(std::string FileName))
	Groupe Gr;
	ExCEntity	TmpEntity,*TmpEntity2;
	Gr.PropGroupe.SetFileName(FileName);
	std::ifstream fin;
	std::string buffstring;
	char b[256];
	fin.open(FileName.data(),std::ios::in);
	if(fin.is_open())
	{
		try
		{
			//----Read Type
			
			memset(b,0,255);fin.getline(b,256,'\n');
			//----Read File property
			memset(b,0,255);fin.getline(b,256,'\n');
			Gr.PropGroupe.m_FileProperty=ExNihilo::ExtracValueFromSring(b,"<ObjectProperty>","<#ObjectProperty>");
			//----Read File MEsh
			memset(b,0,255);fin.getline(b,256,'\n');
			Gr.PropGroupe.m_FileMesh=ExNihilo::ExtracValueFromSring(b,"<ObjectGraphic>","<#ObjectGraphic>");
			//----Read File Gizmo
			memset(b,0,255);fin.getline(b,256,'\n');
			Gr.PropGroupe.m_FileGizmo=ExNihilo::ExtracValueFromSring(b,"<CollisionGizmo>","<#CollisionGizmo>");
			//read property later in other file
			//----Read File Name
			memset(b,0,255);fin.getline(b,256,'\n');
			Gr.PropGroupe.SetName(ExNihilo::ExtracValueFromSring(b,"<ObjectName>","<#ObjectName>"));
			//---- Read Position
			memset(b,0,255);fin.getline(b,256,'\n');
			buffstring=ExNihilo::ExtracValueFromSring(b,"<Position>","<#Position>");
			Gr.PropGroupe.m_Position.SetValue(ExNihilo::ExtractFloatValueFromSring(buffstring,"<X>","<#X>"),
				ExNihilo::ExtractFloatValueFromSring(buffstring,"<Y>","<#Y>"),
				ExNihilo::ExtractFloatValueFromSring(buffstring,"<Z>","<#Z>"));
			//---- Read Angle
			memset(b,0,255);fin.getline(b,256,'\n');
			buffstring=ExNihilo::ExtracValueFromSring(b,"<Angle>","<#Angle>");
			Gr.PropGroupe.m_Angle.SetValue(ExNihilo::ExtractFloatValueFromSring(buffstring,"<X>","<#X>"),
				ExNihilo::ExtractFloatValueFromSring(buffstring,"<Y>","<#Y>"),
				ExNihilo::ExtractFloatValueFromSring(buffstring,"<Z>","<#Z>"));
			//---- Read scale
			memset(b,0,255);fin.getline(b,256,'\n');
			buffstring=ExNihilo::ExtracValueFromSring(b,"<Scale>","<#Scale>");
			Gr.PropGroupe.m_Scale.SetValue(ExNihilo::ExtractFloatValueFromSring(buffstring,"<X>","<#X>"),
				ExNihilo::ExtractFloatValueFromSring(buffstring,"<Y>","<#Y>"),
				ExNihilo::ExtractFloatValueFromSring(buffstring,"<Z>","<#Z>"));
			//read number entity
			memset(b,0,255);fin.getline(b,256,'\n');
			Gr.m_NumberEntity=ExNihilo::ExtractIntValueFromSring(b,"<NumberEntity>","<#NumberEntity>");
			//read entity
			for(int i=0;i<Gr.m_NumberEntity;i++)
			{
				
				TmpEntity2= new ExCEntity;

				TmpEntity2->m_HasGroupe=true;
				TmpEntity2->m_GroupeName=TmpEntity.GetName();
				TmpEntity2->SetManagerGizmo(ManagerGizmo);

				TmpEntity2->SetManagerMesh(ManagerMesh);

				TmpEntity2->SetManagerModel(ManagerModel);

				TmpEntity2->SetManagerId(ManagerId);

				TmpEntity2->SetFileName(FileName);

				TmpEntity2->LoadFile(&fin);

				TmpEntity2->SetPosition(TmpEntity2->GetPosition()+Gr.PropGroupe.GetPosition());
				TmpEntity2->m_Angle=TmpEntity2->m_Angle+Gr.PropGroupe.m_Angle;
				TmpEntity2->m_Scale=TmpEntity2->m_Scale+Gr.PropGroupe.m_Scale;


				Add(TmpEntity2);
				Gr.m_VecEntity.push_back(TmpEntity2);
			}

			fin.close();
		}
		catch(ExCExpStringNotFound)
		{
			std::cout<<"ExCExpStringNotFound"<<std::endl;
		}
		catch(...)
		{
			std::cout<<"ExCExpFileReadError"<<std::endl;
			throw ExCExpFileReadError();
		}
	}else throw   ExCExpFileNotFound();
	m_VecGroupe.push_back(Gr);
UnGuard
}






ExCAction ExManagerEntity::InputCommand(ExCCommand Command)
{
Guard(ExCAction ExManagerEntity::InputCommand(ExCCommand Command))
		return NOTHING;
UnGuard
}

ExCAction ExManagerEntity::InputAction(ExCAction Action)
{
Guard(ExCAction ExManagerEntity::InputAction(ExCAction Action))
	switch(Action.m_Action)
	{
	case MANAGER_ENTITY_RELOAD:
		Reload();
		break;
	case MANAGER_ENTITY_SET_CURRENT_OBJECT_BY_ID:
		SetCurrentObject(atoi(Action.m_Param.data()));
		break;
	case MANAGER_ENTITY_SET_CURRENT_OBJECT_BY_NAME:
		SetCurrentObject(Action.m_Param);
		break;
	case ENTITY_HIDE:
		GetCurrentObject()->SetVisibleState(false);
		break;
	case ENTITY_SHOW:
		GetCurrentObject()->SetVisibleState(true);
		break;
	case MANAGER_ENTITY_RESET:
		Reset();
		break;
	default:
		*Consol<<"Can not file action in ENTITY_ACTION_MAP"<<std::endl;
        break;
	}
	if(Action.m_NextAction){return *Action.m_NextAction;}
	else{return NOTHING;}
UnGuard
}

ExCEntity * ExManagerEntity::GetObject(ExNihilo::ExId id)
{
Guard(ExCEntity *ExManagerEntity::GetObject(ExNihilo::ExId id))
	for(m_ItMap=m_Map->begin();m_ItMap!=m_Map->end();m_ItMap++)
	{
		if(m_ItMap->second->GetId()==id)return m_ItMap->second;
	}
	return NULL;
UnGuard
}

void  ExManagerEntity::Reload(void)
{
Guard(void  ExManagerEntity::Reload(void))
	for(m_ItMap=m_Map->begin();m_ItMap!=m_Map->end();m_ItMap++)
	{
		if(!m_ItMap->second->m_HasGroupe)
		{
			m_ItMap->second->LoadFile(m_ItMap->second->GetFileName());
		}
	}		
	try
	{
		//chaque groupe
		for(unsigned int  i=0;i<m_VecGroupe.size();i++)
		{
			Groupe oldgr=m_VecGroupe.at(i);
			//reload groupe
			std::ifstream fin;
			std::string buffstring;
			int m_NumberEntity;
			char b[256];
			fin.open(m_VecGroupe.at(i).PropGroupe.GetFileName().data(),std::ios::in);
			if(fin.is_open())
			{
				
				memset(b,0,255);fin.getline(b,256,'\n');//----Read Type
				memset(b,0,255);fin.getline(b,256,'\n');//----Read File property
				m_VecGroupe.at(i).PropGroupe.m_FileProperty=ExNihilo::ExtracValueFromSring(b,"<ObjectProperty>","<#ObjectProperty>");
				memset(b,0,255);fin.getline(b,256,'\n');//----Read File MEsh
				m_VecGroupe.at(i).PropGroupe.m_FileMesh=ExNihilo::ExtracValueFromSring(b,"<ObjectGraphic>","<#ObjectGraphic>");
				memset(b,0,255);fin.getline(b,256,'\n');//----Read File Gizmo
				m_VecGroupe.at(i).PropGroupe.m_FileGizmo=ExNihilo::ExtracValueFromSring(b,"<CollisionGizmo>","<#CollisionGizmo>");
				memset(b,0,255);fin.getline(b,256,'\n');//----Read File Name
				m_VecGroupe.at(i).PropGroupe.SetName(ExNihilo::ExtracValueFromSring(b,"<ObjectName>","<#ObjectName>"));
				memset(b,0,255);fin.getline(b,256,'\n');//---- Read Position
				buffstring=ExNihilo::ExtracValueFromSring(b,"<Position>","<#Position>");
				m_VecGroupe.at(i).PropGroupe.m_Position.SetValue(ExNihilo::ExtractFloatValueFromSring(buffstring,"<X>","<#X>"),
					ExNihilo::ExtractFloatValueFromSring(buffstring,"<Y>","<#Y>"),
					ExNihilo::ExtractFloatValueFromSring(buffstring,"<Z>","<#Z>"));
				memset(b,0,255);fin.getline(b,256,'\n');//---- Read Angle
				buffstring=ExNihilo::ExtracValueFromSring(b,"<Angle>","<#Angle>");
				m_VecGroupe.at(i).PropGroupe.m_Angle.SetValue(ExNihilo::ExtractFloatValueFromSring(buffstring,"<X>","<#X>"),
					ExNihilo::ExtractFloatValueFromSring(buffstring,"<Y>","<#Y>"),
					ExNihilo::ExtractFloatValueFromSring(buffstring,"<Z>","<#Z>"));
				memset(b,0,255);fin.getline(b,256,'\n');//---- Read scale
				buffstring=ExNihilo::ExtracValueFromSring(b,"<Scale>","<#Scale>");
				m_VecGroupe.at(i).PropGroupe.m_Scale.SetValue(ExNihilo::ExtractFloatValueFromSring(buffstring,"<X>","<#X>"),
					ExNihilo::ExtractFloatValueFromSring(buffstring,"<Y>","<#Y>"),
					ExNihilo::ExtractFloatValueFromSring(buffstring,"<Z>","<#Z>"));
				memset(b,0,255);fin.getline(b,256,'\n');//read number entity
				m_NumberEntity=ExNihilo::ExtractIntValueFromSring(b,"<NumberEntity>","<#NumberEntity>");
			}else throw   ExCExpFileNotFound();
			std::cout<<"Reload group pro ok"<<std::endl;			
			//chaque entite est rechargée
			for(unsigned int j=0;j<m_VecGroupe.at(i).m_VecEntity.size();j++)
			{
				
				for(int k=0;k<m_NumberEntity;k++)
				{
					/*m_VecGroupe.at(i).m_VecEntity.at(k)->LoadFile(&fin);
					m_VecGroupe.at(i).m_VecEntity.at(k)->SetPosition(m_VecGroupe.at(i).m_VecEntity.at(k)->GetPosition()+m_VecGroupe.at(i).PropGroupe.GetPosition());
					m_VecGroupe.at(i).m_VecEntity.at(k)->m_Angle=m_VecGroupe.at(i).m_VecEntity.at(k)->m_Angle+m_VecGroupe.at(i).PropGroupe.m_Angle;
					m_VecGroupe.at(i).m_VecEntity.at(k)->m_Scale=m_VecGroupe.at(i).m_VecEntity.at(k)->m_Scale+m_VecGroupe.at(i).PropGroupe.m_Scale;
					*/
					m_VecGroupe.at(i).m_VecEntity.at(k)->SetPosition(m_VecGroupe.at(i).m_VecEntity.at(k)->GetPosition()+m_VecGroupe.at(i).PropGroupe.GetPosition()-oldgr.PropGroupe.GetPosition());
					m_VecGroupe.at(i).m_VecEntity.at(k)->m_Angle=m_VecGroupe.at(i).m_VecEntity.at(k)->m_Angle+m_VecGroupe.at(i).PropGroupe.m_Angle-oldgr.PropGroupe.m_Angle;
					m_VecGroupe.at(i).m_VecEntity.at(k)->m_Scale=m_VecGroupe.at(i).m_VecEntity.at(k)->m_Scale+m_VecGroupe.at(i).PropGroupe.m_Scale-oldgr.PropGroupe.m_Scale;

				}
			}
			fin.close();
		}
	}
	catch(ExCExpStringNotFound){std::cout<<"ExCExpStringNotFound"<<std::endl;}
	catch(...){	std::cout<<"ExCExpFileReadError"<<std::endl;throw ExCExpFileReadError();}
	
	
UnGuard
}

ExCEntity* ExManagerEntity::GetCurrentObject(void)
{
Guard(ExCEntity* ExManagerEntity::GetCurrentObject(void))
		return GetObject(m_CurrentObjectId);
UnGuard
}