/*
 * 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: ExManagerLoad.cpp,v 1.23 2002/11/24 11:58:58 data Exp $
 *
 */

#include "ExManagerLoad.h"

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

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

ExManagerLoad::ExManagerLoad(void)
{
Guard(ExManagerLoad::ExManagerLoad(void))
	m_Draw=false;
	m_Loading=false;
	SetAskForCommand(false);
UnGuard
}

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

void ExManagerLoad::Reset(void)
{
Guard(void ExManagerLoad::Reset(void))
	ExManagerObject<ExCLoadingAnimation>::Reset();
	Init();
UnGuard
}

void ExManagerLoad::Init(void)
{
Guard(ExManagerLoad::Init(void))
	ExManagerObject<ExCLoadingAnimation>::Init();
	m_Loading=false;
	m_EntityFilePath="../Data/Entity/"; 
UnGuard
}

void ExManagerLoad::Load(std::string FileName)
{
Guard(ExManagerLoad::Load(std::string FileName))
//TO DO here add path for loading file directory
	ExCAction Action;
	try
	{
		switch(GetFileType(FileName)) 
		{
		case FILE_CONSOL:
			ManagerConsole->LoadStringActionFile(FileName.data());
			break;
		case FILE_SET:
			LoadSetOfFile(FileName);
			break;
		case FILE_SOUND:
			ManagerSound->LoadSound(FileName);
			break;
		case FILE_MODEL:
			ManagerModel->Load(FileName);
			break;
		case FILE_MAP:
			ManagerMap->Load(FileName);
			break;
		case FILE_PARTICUL:
			ManagerParticuleSystem->Load(FileName);
			break;
		case FILE_WINDOW:
			ManagerObjectWindow->Load(FileName);
			break;
		case FILE_INTERFACE:
			ManagerInterface->Load(FileName);
			break;
		case FILE_TEXTURE:
			ManagerTexture->Load(FileName);
			break;
		case FILE_COMMAND:
			Action.m_Action=LOAD_EXEC_CONFIG_FILE;
			Action.m_Param=" "+FileName;
			FluxAction->Push(Action);
			break;
		case FILE_MESH:
			ManagerMesh->Load(FileName);
			break;
		case FILE_LOADING_ANIMATION:
			LoadAnimationFile(FileName);
			break;
		case FILE_ANIMATION:
			ManagerAnimation->Load(FileName);
			break;
		case FILE_ENTITY:
			ManagerEntity->Load(m_EntityFilePath+FileName);
			break;
		}
	}
	catch(ExCExpFileNotFound)
	{
		*Consol<<"ExManagerLoad::ExCeption =>"<<FileName<<" File not found"<<std::endl;
	}
	catch(ExCExpFileReadError)
	{
		*Consol<<"ExManagerLoad::ExCeption =>"<<FileName<<" Read file error"<<std::endl;
	}
	catch(...)
	{
		*Consol<<"ExManagerLoad::ExCeption =>"<<FileName<<" Unknow exception"<<std::endl;
	}
UnGuard
}

void ExManagerLoad::LoadAnimationFile(std::string FileName)
{
Guard(ExManagerLoad::LoadAnimationFile(std::string FileName))
	m_CurrentLoadingAniamtion = new ExCLoadingAnimation();
	m_CurrentLoadingAniamtion->SetManagerTexture(ManagerTexture);
	m_CurrentLoadingAniamtion->Load(FileName);
	m_CurrentLoadingAniamtion->SetName(FileName);
	//ExManagerObject<ExCLoadingAnimation>::Add(Animation);
	//SetCurrentObject(Animation.GetName());
	UnGuard
}


void ExManagerLoad::DrawInAnimation(void)
{
Guard(void ExManagerLoad::DrawInAnimation(void))
	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);	//Clear screen
	ManagerCamera->Draw();
	if(m_Draw)m_CurrentLoadingAniamtion->Draw();
	glFlush();
	glutSwapBuffers();
UnGuard
}


void ExManagerLoad::Draw(void)
{
Guard(void ExManagerLoad::Draw(void))
	if(m_Draw)m_CurrentLoadingAniamtion->Draw();
	if(m_Loading)
	{
		Load(m_VecFileToLoad.at(m_CurrentFileLoading));
		m_CurrentLoadingAniamtion->Next();
		if(m_CurrentFileLoading==m_VecFileToLoad.size()-1)
		{
			m_VecFileToLoad.clear();
			m_CurrentLoadingAniamtion->Last();
			m_Loading=false;	
		}else
		{
			m_CurrentFileLoading++;
		}
	}
UnGuard
}


FileType ExManagerLoad::GetFileType(std::string FileName)
{
Guard(FileType ExManagerLoad::GetFileType(std::string FileName))
	std::string Buffext=ExNihilo::GetFileExtension(FileName);

	if(strcmpi(Buffext.data(),"csl")==0)
	{
		return FILE_CONSOL;		
	}
	if(strcmpi(Buffext.data(),"comd")==0)
	{
		return FILE_COMMAND;
	}
	if(strcmpi(Buffext.data(),"wav")==0
		||strcmpi(Buffext.data(),"mp3")==0
		||strcmpi(Buffext.data(),"mid")==0)
	{
		return FILE_SOUND;
	}
	if(strcmpi(Buffext.data(),"asc")==0
		||strcmpi(Buffext.data(),"ase")==0
		||strcmpi(Buffext.data(),"3ds")==0
		||strcmpi(Buffext.data(),"md2")==0
		||strcmpi(Buffext.data(),"md3")==0
		||strcmpi(Buffext.data(),"exm")==0
		||strcmpi(Buffext.data(),"obj")==0)
	{
		return FILE_MODEL;
	}
	if(strcmpi(Buffext.data(),"map")==0
		||strcmpi(Buffext.data(),"bsp")==0
		||strcmpi(Buffext.data(),"hgmp")==0
		||strcmpi(Buffext.data(),"skyb")==0)
	{
		return FILE_MAP;
	}
	if(strcmpi(Buffext.data(),"int")==0)
	{
		return	 FILE_INTERFACE;
	}
	if(strcmpi(Buffext.data(),"set")==0)
	{
		return FILE_SET;
	}
	if(strcmpi(Buffext.data(),"exec")==0)
	{
		return FILE_COMMAND;
	}
	if(strcmpi(Buffext.data(),"part")==0)
	{
		return FILE_PARTICUL;
	}
	if(strcmpi(Buffext.data(),"exw")==0)
	{
		return FILE_WINDOW;
	}
	if(strcmpi(Buffext.data(),"lanim")==0)
	{
		return FILE_LOADING_ANIMATION;
	}
	if(strcmpi(Buffext.data(),"anim")==0)
	{
		return FILE_ANIMATION;
	}
	if(strcmpi(Buffext.data(),"exme")==0)
	{
		return FILE_MESH;
	}
	if(strcmpi(Buffext.data(),"bmp")==0
		||strcmpi(Buffext.data(),"tga")==0
		||strcmpi(Buffext.data(),"pcx")==0
		||strcmpi(Buffext.data(),"jpg")==0
		||strcmpi(Buffext.data(),"rgb")==0
		||strcmpi(Buffext.data(),"raw")==0
		||strcmpi(Buffext.data(),"dds")==0
		||strcmpi(Buffext.data(),"ppm")==0)
	{
		return FILE_TEXTURE;
	}
	if(strcmpi(Buffext.data(),"ent")==0)
	{
		return FILE_ENTITY;
	}
	*Consol<<"ExManagerLoad::ExCeption =>"<<FileName<<" Bad file extension"<<std::endl;	
	DisplayFileType();
	return FILE_UNKNOWN_TYPE;
UnGuard
}




ExCAction ExManagerLoad::InputCommand(ExCCommand Command)
{
Guard(ExCAction ExManagerLoad::InputCommand(ExCCommand Command))
	if(Command.m_Command>10000&&Command.m_Command<30000)
	{
		if(!m_Loading)m_Draw=false;
		SetAskForCommand(false);
		//return START_BLACK_TO_FADE;
	}
	if(Command.m_Command>40001&&Command.m_Command<40006)
	{
		if(!m_Loading)m_Draw=false;
		SetAskForCommand(false);
		//return START_BLACK_TO_FADE;
	}
	return NOTHING;
UnGuard
}

ExCAction ExManagerLoad::InputAction(ExCAction Action)
{
Guard(ExCAction ExManagerLoad::InputAction(ExCAction Action))
	switch(Action.m_Action)
	{
	case LOAD_PART_CONFIG_FILE:
		ManagerParticuleSystem->Load(Action.m_Param);
		break;
	case LOAD_SET_OF_FILE:
		LoadSetOfFile(Action.m_Param);
		break;
	case LOAD_FILE:
		Load(Action.m_Param);
		break;
	case NEXT_ANIMATION_FRAME:
		m_CurrentLoadingAniamtion->Next();
		DrawInAnimation();
		break;
	case PREV_ANIMATION_FRAME:
		m_CurrentLoadingAniamtion->Previous();
		DrawInAnimation();
		break;
	case LAST_ANIMATION_FRAME:
		m_CurrentLoadingAniamtion->Last();
		DrawInAnimation();
		break;
	case FIRST_ANIMATION_FRAME:
		m_CurrentLoadingAniamtion->First();
		DrawInAnimation();
		break;
	case ENABLE_LOADING_ANIMATION:
		SetStatus(true);
		SetAskForCommand(true);
		m_Loading=false;
		m_Draw=true;
		m_CurrentFileLoading=0;
		DrawInAnimation();
		break;
	case DISABLE_LOADING_ANIMATION:
		SetAskForCommand(false);
		m_Loading=false;
		m_Draw=false;
		m_CurrentFileLoading=0;
		break;
	default:
		*Consol<<"Can not file action in LOAD_ACTION_MAP"<<std::endl;
		break;
	}
	if(Action.m_NextAction){return *Action.m_NextAction;}
	else{return NOTHING;}
UnGuard
}

void ExManagerLoad::LoadSetOfFile(std::string FileName)
{
Guard(void ExManagerLoad::LoadSetOfFile(std::string FileName))
	SetStatus(true);
	SetAskForCommand(true);
	m_Loading=true;
	m_Draw=true;
	m_CurrentFileLoading=0;
	char			buffer[255];
	#ifdef UNIX_SRC
		sprintf(buffer, PREFIX "/ExNihilo/Data/%s", FileName.data());
	#else
		sprintf(buffer, "../Data/%s", FileName.data());
	#endif
	std::ifstream fin;
	std::string buffstring;
	char b[256];
	fin.open(buffer,std::ios::in);
	if(fin.is_open())
	{
		try
		{
			//----Read all file
			do
			{
				memset(b,0,255);
				fin.getline(b,256,'\n');
				try
				{
					m_VecFileToLoad.push_back(ExNihilo::ExtracValueFromSring(b,"<file>","<#file>"));
				}catch(ExCExpStringNotFound){}
			}while(!fin.eof());
			fin.close();
		}catch(...){throw ExCExpFileReadError();}
	}else throw   ExCExpFileNotFound();
	
UnGuard
}

void ExManagerLoad::DisplayFileType(void)
{
Guard(void ExManagerLoad::DisplayFileType(void))
	*Consol<<"*------------------------------------------------------------------------------------------------*"<<std::endl;
	*Consol<<"|                                Extension file supported by Exnihilo                            |"<<std::endl;
	*Consol<<"|------------------------------------------------------------------------------------------------|"<<std::endl;
	*Consol<<"|Description                 | Extension |  Status  |  Comment                                   |"<<std::endl;
	*Consol<<"|------------------------------------------------------------------------------------------------|"<<std::endl;				
	*Consol<<"|Console configuration file  |  .csl     | Aviable  | Asign consol command to action             |"<<std::endl;
	*Consol<<"|Command configuration file  |  .comd    | Aviable  | Asign input (keyboard,mouse,...)to action  |"<<std::endl;
	*Consol<<"|Window files                |  .ExW     | Aviable  | Load a window from a ressource file        |"<<std::endl;
	*Consol<<"|------------------------------------------------------|-----------------------------------------|"<<std::endl;				
	*Consol<<"|ExNihilo map file           |  .map     | Aviable  | Create map file with AscToMap converter    |"<<std::endl;
	*Consol<<"|Quake map file              |  .bsp     |          |                                            |"<<std::endl;
	*Consol<<"|------------------------------------------------------------------------------------------------|"<<std::endl;				
	*Consol<<"|ASC model  file             |  .asc     | Aviable  | Create a 3d model and export him to *.asc  |"<<std::endl;
	*Consol<<"|MD2 (quake 2) model  file   |  .md2     | Aviable  |                                            |"<<std::endl;
	*Consol<<"|MD3 (quake 3) model  file   |  .md3     |          |                                            |"<<std::endl;
	*Consol<<"|ASE model  file             |  .ase     |          |                                            |"<<std::endl;
	*Consol<<"|3d studio max model  file   |  .3ds     | Aviable  |                                            |"<<std::endl;
	*Consol<<"|OBJ model  file             |  .obj     |          |                                            |"<<std::endl;
	*Consol<<"|------------------------------------------------------------------------------------------------|"<<std::endl;				
	*Consol<<"|Wave sound file             |  .wav     |          |                                            |"<<std::endl;
	*Consol<<"|Midi sound file             |  .mid     |          |                                            |"<<std::endl;
	*Consol<<"|Mp3 sound file              |  .mp3     |          |                                            |"<<std::endl;
	*Consol<<"|------------------------------------------------------------------------------------------------|"<<std::endl;
	*Consol<<"|Particule system  file      |  .part    | Aviable  |  Use SDK partiucle to create *.part file   |"<<std::endl;
	*Consol<<"|Interface file              |  .int     | Aviable  |  Use SDK partiucle to create *.int file    |"<<std::endl;
	*Consol<<"|------------------------------------------------------------------------------------------------|"<<std::endl;				
	*Consol<<"|Groupe of file              |  .set     | Aviable  |                                            |"<<std::endl;
	*Consol<<"|Groupe of action            |  .exec    | Aviable  |                                            |"<<std::endl;
	*Consol<<"*------------------------------------------------------------------------------------------------*"<<std::endl;
UnGuard
}