///////////////////////////////
//File:CSGD_ObjectFactory.h
//Author:Eric Green
//Purpose:Contains the object factory class which is used to create objects in the game.
#pragma once
#include <map>
#pragma warning (disable:4291)
using std::map;
#include "CSGD_MemoryManager.h"
template<typename ClassIDType, typename BaseClassType>
class CSGD_ObjectFactory
{
private:

	
	typedef BaseClassType*(*ObjectCreator)(void);

	//a map of all the derived class types and the create functions associated with it
	map<ClassIDType, ObjectCreator> m_ObjectCreators;
	//singleton
	static CSGD_ObjectFactory<ClassIDType, BaseClassType> m_Instance;

	//constructobject
	template <typename DerivedClassType>
	static BaseClassType* ConstructObject()
	{
		return new DerivedClassType;
	}


	CSGD_ObjectFactory(void){}
public:
	
	virtual ~CSGD_ObjectFactory(void){}

	static CSGD_ObjectFactory<ClassIDType, BaseClassType> *GetInstance()
	{
		return &m_Instance;
	}

	template <typename DerivedClassType>
	bool RegisterClassType(ClassIDType id)
	{
		//create a new clss definition
		std::pair<ClassIDType, ObjectCreator> objTypeDef;
		objTypeDef.first = id;
		objTypeDef.second = ConstructObject<DerivedClassType>;

		//add the class defnition to our registry.
		m_ObjectCreators.insert(objTypeDef);

		return true;
	}

	bool UnregisterClassType(ClassIDType id)
	{
		//find the given key in the map.
		map<ClassIDType, ObjectCreator>::iterator mIter = m_ObjectCreators.find(id);

		//make sure we found the eky in the map(registry)
		if(mIter == m_ObjectCreators.end())
			return false;

		m_ObjectCreator.erase(mIter);

		//success
		return true;
	}

	// createobject - creates a new class object of the given type
	// can only create objects that have been registered.

	BaseClassType* CreateObject(ClassIDType id)
	{
		map<ClassIDType, ObjectCreator>::iterator mIter = m_ObjectCreators.find(id);

		//make sure we found the eky in the map(registry)
		if(mIter == m_ObjectCreators.end())
			return 0;

		return (*mIter).second();
	}

	void ShutdownObjectFactory()
	{
		m_ObjectCreators.clear();
	}

};

template <typename ClassIDType, typename BaseClassType>
CSGD_ObjectFactory<ClassIDType, BaseClassType> CSGD_ObjectFactory<ClassIDType, BaseClassType>::m_Instance;