#pragma once

#include <string>
#include <map>

template<class T>
class DevFactory
{
public:
	typedef T* (*CreatorFunction)();
	void RegistDevice(std::string devId, CreatorFunction);
	T* Create( std::string devId );

	static DevFactory& Instance();

private:
	std::map<std::string, CreatorFunction> _creators;

private:
	DevFactory<T>(void){};
	~DevFactory<T>(void){};
};

/*
* FactoryÀÇ Instance¸¦ ¹ÝÈ¯ÇÑ´Ù. Typeº°·Î »õ·Î¿î ÀÎ½ºÅÏ½º°¡ »ý¼ºµÊ.
*/
template<class T>
DevFactory<T>& DevFactory<T>::Instance(){
	
	static DevFactory<T> factory ;
	return factory;
}

/*
* T¸¦ Create ÇÑ´Ù.
*/
template<class T>
T* DevFactory<T>::Create( std::string devId )
{
	std::map<std::string, CreatorFunction>::const_iterator i = _creators.find( devId );
	if( i == _creators.end() ) {
		return NULL;
	}

	return i->second();
}

/*
* CreatorFunctionÀ» Regist ÇÑ´Ù.
*/
template<class T>
void DevFactory<T>::RegistDevice(std::string devId, CreatorFunction creator)
{
	_creators.insert( std::pair<std::string, CreatorFunction>(devId, creator) );

}

namespace Device {

// C : Concrete, B : Base
template<class C,class B>
class RegistHelper {

public:
	RegistHelper<C,B>( std::string devId );
	~RegistHelper<C,B>(){};

private:
	static B* createDevice();

};

template<class C, class B>
B* RegistHelper<C,B>::createDevice()
{
	return new C;
}

template<class C, class B>
RegistHelper<C,B>::RegistHelper( std::string devId )
{
	DevFactory<B>::Instance().RegistDevice( devId, &RegistHelper<C,B>::createDevice );
}

};
