/************************************************************************/
/* Ex Nihlo Engine by Hermanns Christophe								*/
/************************************************************************/
/* 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 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.											*/
/*																		*/
/* If you use a important part of this code please send me a mail		*/
/* I just want to see where my code go thks :)							*/
/************************************************************************/

/************************************************************************/
/* Contact                                                              */  
/************************************************************************/
/* ExNihilo Website :www.ploksoftware.org                               */
/*                                                                      */
/* Hermanns Christophe ExNihilo creator and main programmer             */
/*                                                                      */
/* Mail             : Data@ploksoftware.org								*/
/* ICQ              : 8030901											*/
/* MSN Messenger    : Data_7@hotmail.com								*/
/*                                                                      */
/*                                                                      */
/************************************************************************/

/************************************************************************/
/* File Description             										*/
/************************************************************************/
/* File Name   :ExManagerObject.h										*/
/*																		*/
/* Start Date  :03/20/2002												*/
/*																		*/
/* Last Update :06/20/2003                                              */
/*																		*/
/* File Description :													*/
/*                                                                      */
/* For update of this file check : www.ploksoftware.org                 */
/************************************************************************/

#ifndef __EXMANAGEROBJECT_H__
#define __EXMANAGEROBJECT_H__
//------------------------------------------------------------------------
//Includes
//------------------------------------------------------------------------
#include "ExDefine.h"
#include "ExNihiloNameSpace.h"
#include "ExNihiloExecption.h"
//------------------------------------------------------------------------
#include "Object/ExCObject.h"
//------------------------------------------------------------------------
#include "Math/ExMath.h"
//------------------------------------------------------------------------
#include "Manager/ExManager.h"
#include "Manager/ExManagerId.h"
//------------------------------------------------------------------------
template <class TypeA> 
class ExManagerObject : public ExManager
{
protected:
//------------------------------------------------------------------------
// Variable
//------------------------------------------------------------------------
	typename std::map<  ExNihilo::ExId   , TypeA , std::less <ExNihilo::ExId  >  >			*m_Map;
	typename std::map<  ExNihilo::ExId   , TypeA , std::less <ExNihilo::ExId  >  >::iterator	m_ItMap;
	
	ExManagerId					        *ManagerId;
	ExNihilo::ExId						m_CurrentObjectId;
//------------------------------------------------------------------------
// Methode
//------------------------------------------------------------------------
	//std::map< ExNihilo::ExId   , TypeA , std::less <ExNihilo::ExId  >  >::iterator GetIterator(ExNihilo::ExId id);
	//std::map< ExNihilo::ExId   , TypeA , std::less <ExNihilo::ExId  >  >::iterator GetIterator(std::string  Name);
public :
//------------------------------------------------------------------------
// Constructor // Destructor
//------------------------------------------------------------------------
	ExManagerObject();
	~ExManagerObject();
//------------------------------------------------------------------------
// Methode
//------------------------------------------------------------------------
	inline void SetManagerId(ExManagerId *Id){ManagerId	= Id;}
//------------------------------------------------------------------------
	void Reset(void);
	void Init(void);
	void Init(std::string FileName);
	void Reload(void);
	void List(void);
	virtual void Draw(void){};
//------------------------------------------------------------------------
	bool Add(TypeA object);
	bool Add(std::string FileName);
	bool Load(std::string FileName);
//------------------------------------------------------------------------
	bool Remove(ExNihilo::ExId id);
	bool Remove(std::string  Name);
	bool RemoveCurrentObject(void);
//------------------------------------------------------------------------
	TypeA * GetObject(ExNihilo::ExId id);
	TypeA * GetObject(std::string  Name);
	TypeA * GetCurrentObject(void);
	TypeA * GetFirstObject(void);
	TypeA * GetLastObject(void);
	ExNihilo::ExId GetFirstObjectId(void);
	ExNihilo::ExId GetLasstObjectId(void);
//------------------------------------------------------------------------
	bool SetCurrentObject(ExNihilo::ExId id);
	bool SetCurrentObject(std::string  Name);
	ExNihilo::ExId  NextObject(void);
	ExNihilo::ExId  PreviousObject(void);
//------------------------------------------------------------------------
	inline unsigned int GetNumberObject(void){return m_Map->size();}
};
//------------------------------------------------------------------------
// Constructor // Destructor
//------------------------------------------------------------------------
template<class TypeA>
ExManagerObject<TypeA>::ExManagerObject(void)
{
Guard(ExManagerObject<TypeA>::ExManagerObject(void))

UnGuard
}

template<class TypeA>
ExManagerObject<TypeA>::~ExManagerObject(void)
{
Guard(ExManagerObject<TypeA>::~ExManagerObject(void))
UnGuard
}

//------------------------------------------------------------------------
template<class TypeA>
void  ExManagerObject<TypeA>::Reset(void)
{
Guard(void  ExManagerObject<TypeA>::Reset(void))
	m_CurrentObjectId=-1;
	m_Map->clear();
UnGuard
}

template<class TypeA>
void  ExManagerObject<TypeA>::Init(void)
{
Guard(void  ExManagerObject<TypeA>::Init(void))
	m_CurrentObjectId=-1;
	m_Map=new std::map< ExNihilo::ExId  , TypeA , std::less <ExNihilo::ExId  >  >;
UnGuard
}

template<class TypeA>
void  ExManagerObject<TypeA>::Init(std::string FileName)
{
Guard(void  ExManagerObject<TypeA>::Init(std::string FileName))
UnGuard
}

template<class TypeA>
void  ExManagerObject<TypeA>::Reload(void)
{
Guard(void  ExManagerObject<TypeA>::Reload(void))
UnGuard
}


template<class TypeA>
void  ExManagerObject<TypeA>::List(void)
{
Guard(void  ExManagerObject<TypeA>::List(void))
	*Consol<<"---------------List of Object Type :"<<typeid(&m_ItMap->second).name()<<"--------------"<<std::endl;
	for(m_ItMap=m_Map->begin();m_ItMap!=m_Map->end();m_ItMap++)
	{
		*Consol<<" Id:"<<m_ItMap->second.GetId()<<" Name :"<<m_ItMap->second.GetName()<<std::endl;
	}	
	*Consol<<"-----------------------------------------------------------------"<<std::endl;
	*Consol<<" Number Total of Object : "<<m_Map->size()<<std::endl;
	*Consol<<" Current Object Id : "<<m_CurrentObjectId<<std::endl;
	*Consol<<"-----------------------------------------------------------------"<<std::endl;

UnGuard
}
//----------------------------------------------------------------------------------
template<class TypeA>
bool  ExManagerObject<TypeA>::Add(TypeA object)
{
Guard(bool  ExManagerObject<TypeA>::Add(TypeA object))
	try
	{
		//Ask ManagerId for Aviable Id and Avialbe name
		//object.SetIdName(ManagerId->GetNewIdName(object.GetName()));
		
		std::pair<ExNihilo::ExId,TypeA>  obj;
		obj.first=ManagerId->RecordObject(object);
		obj.second=object;
		m_Map->insert(obj);
		return true;
	}
	catch(ExCExpRecordObject)
	{
		*Consol<<"ExManagerObject:: Exception record object"<<std::endl;
		std::cout<<"ExManagerObject:: Exception record object"<<std::endl;
		return false;
	}
	catch(...)
	{
		*Consol<<"ExManagerObject:: Exception add object"<<std::endl;
		std::cout<<"ExManagerObject:: Exception add object"<<std::endl;
		return false;
	}
UnGuard
}

template<class TypeA>
bool  ExManagerObject<TypeA>::Load(std::string FileName)
{
Guard(bool  ExManagerObject<TypeA>::Load(std::string FileName))
	return	Add(TypeA(FileName));
UnGuard
}

template<class TypeA>
bool  ExManagerObject<TypeA>::Add(std::string FileName)
{
Guard(bool  ExManagerObject<TypeA>::Add(std::string FileName))
	return Load(FileName);    	
UnGuard
}
//----------------------------------------------------------------------------------
template<class TypeA>
bool  ExManagerObject<TypeA>::Remove(ExNihilo::ExId id)
{
Guard(bool  ExManagerObject<TypeA>::Remove(ExNihilo::ExId id))
	if(0==m_Map->erase(id))return false;
	else{if(m_CurrentObjectId==id)m_CurrentObjectId=-1;return true;}
UnGuard
}

template<class TypeA>
bool  ExManagerObject<TypeA>::Remove(std::string  Name)
{
Guard(bool  ExManagerObject<TypeA>::Remove(std::string  Name))
	return	Remove(ManagerId->GetObjectId(Name,typeid(&TypeA)));
UnGuard
}

template<class TypeA>
bool  ExManagerObject<TypeA>::RemoveCurrentObject(void)
{
Guard(bool  ExManagerObject<TypeA>::RemoveCurrentObject(void))
	return	Remove(m_CurrentObjectId);
UnGuard
}
//----------------------------------------------------------------------------------
template<class TypeA>
TypeA *  ExManagerObject<TypeA>::GetObject(ExNihilo::ExId id)
{
Guard(TypeA *  ExManagerObject<TypeA>::GetObject(ExNihilo::ExId id))
	if(m_Map->find(id)==m_Map->end())return NULL;
	return &m_Map->find(id)->second;
UnGuard
}

template<class TypeA>
TypeA *  ExManagerObject<TypeA>::GetObject(std::string  Name)
{
Guard(TypeA *  ExManagerObject<TypeA>::GetObject(std::string  Name))
	return GetObject(ManagerId->GetObjectId(Name,typeid(&m_ItMap->second).name()));	
UnGuard
}

template<class TypeA>
TypeA *  ExManagerObject<TypeA>::GetCurrentObject(void)
{
Guard(TypeA *  ExManagerObject<TypeA>::GetCurrentObject(void))
	return GetObject(m_CurrentObjectId);	
UnGuard
}

template<class TypeA>
TypeA *  ExManagerObject<TypeA>::GetLastObject(void)
{
Guard(TypeA *  ExManagerObject<TypeA>::GetLastObject(void))
	m_ItMap=m_Map->end();
	m_ItMap--;
	return GetObject(m_ItMap->second.GetId());	
UnGuard
}
//----------------------------------------------------------------------------------
/*template<class TypeA>
typename std::map< ExNihilo::ExId   , TypeA , std::less <ExNihilo::ExId  >  >::iterator ExManagerObject<TypeA>::GetIterator(ExNihilo::ExId id)
{
Guard(... iterator ExManagerObject<TypeA>::GetIterator(ExNihilo::ExId id))
	return m_Map->find(id);
UnGuard
}
   
template<class TypeA> 
typename std::map< ExNihilo::ExId   , TypeA , std::less <ExNihilo::ExId  >  >::iterator ExManagerObject<TypeA>::GetIterator(std::string  Name)
{
Guard(... iterator ExManagerObject<TypeA>::GetIterator(std::string  Name))
	return GetIterator(ManagerId->GetObjectId(Name,typeid(&m_ItMap->second).name()));	
UnGuard
}	 */
//----------------------------------------------------------------------------------
template<class TypeA>
bool  ExManagerObject<TypeA>::SetCurrentObject(ExNihilo::ExId id)
{
Guard(bool  ExManagerObject<TypeA>::SetCurrentObject(ExNihilo::ExId id))
	if(GetObject(id)!=NULL)m_CurrentObjectId=id;return true;
	return false;
UnGuard
}

template<class TypeA>
bool  ExManagerObject<TypeA>::SetCurrentObject(std::string  Name)
{
Guard(bool  ExManagerObject<TypeA>::SetCurrentObject(std::string  Name))
	return SetCurrentObject(ManagerId->GetObjectId(Name,typeid(&m_ItMap->second).name()));
UnGuard
}

template<class TypeA>
ExNihilo::ExId   ExManagerObject<TypeA>::NextObject(void)
{
Guard(ExNihilo::ExId   ExManagerObject<TypeA>::NextObject(void))
	if(m_Map->upper_bound(m_CurrentObjectId)==m_Map->end())
	{
		m_CurrentObjectId=m_Map->begin()->first;
	}else
	{
		m_CurrentObjectId=m_Map->upper_bound(m_CurrentObjectId)->first;
	}
	return m_CurrentObjectId;
UnGuard
}

template<class TypeA>
ExNihilo::ExId   ExManagerObject<TypeA>::PreviousObject(void)
{
Guard(ExNihilo::ExId   ExManagerObject<TypeA>::PreviousObject(void))
	if(m_Map->begin()->first==m_CurrentObjectId)
	{
		m_CurrentObjectId=m_Map->rbegin()->first;
	}else
	{
		m_ItMap=m_Map->find(m_CurrentObjectId);
		m_ItMap--;
		m_CurrentObjectId=m_ItMap->first;
	}
	return m_CurrentObjectId;
UnGuard
}

//----------------------------------------------------------------------------------

#endif //__EXMANAGEROBJECT_H__
