#pragma once
#include "mof/tstring.hpp"
#include <map>
#include <list>
#include <memory>
#include "mof/ConsoleIO.hpp"

namespace mof{
	
	

	/** リソースのプール、遅延ロード機能を提供するテンプレート
	 *
	 *
	*/
	template <class T >
	class ResourceManager
	{
		typedef std::list<std::shared_ptr<ResourceManager<T > > > MANAGER_LIST;
		typedef std::map<mof::tstring , std::shared_ptr<T>> RESOURCE_MAP;
		

        ResourceManager<T>* m_pParent;
		RESOURCE_MAP m_resources;
		MANAGER_LIST m_children;
	
		static std::shared_ptr<T> nullPtr;
		//void addResouce(Resouce* pResource);
	public:
		typedef std::shared_ptr<ResourceManager<T>> ptr;
		ResourceManager();
		virtual ~ResourceManager(void);

		std::shared_ptr<T> getResource(const tstring& name );
		void addResource(const TCHAR * const name , std::shared_ptr<T>& resource);
        std::shared_ptr< ResourceManager<T> > createChild();
	};



	template <class T>
	std::shared_ptr<T> ResourceManager<T>::nullPtr = std::shared_ptr<T>();



	/** 親なしとしてオブジェクト生成
	 *
	 */
	template <class T >
	ResourceManager<T >::ResourceManager( ){
		m_pParent = NULL;
	}

	/** 自身のリソースと子を解放し、親の子リストから自身を削除
	 */
	template <class T  >
	ResourceManager<T >::~ResourceManager(){
		//自身の管理するリソースをアンロード
        m_resources.clear();

		//子オブジェクトを削除
        m_children.clear();
			
		//親から自身を削除
		if(m_pParent != NULL){
			for(MANAGER_LIST::iterator itr = m_pParent->m_children.begin() ; itr != m_pParent->m_children.end() ; ++itr){
				if(this == itr->get() ){
					m_pParent->m_children.erase(itr);
					return;
				}
			}
		}
	}

	

	/** 新たな子を追加し、返す
	 * @return 生成した子
	 */
	template <class T  >
	std::shared_ptr< ResourceManager<T> > ResourceManager<T >::createChild(){
        std::shared_ptr< ResourceManager<T > > manager(new ResourceManager<T>( ));
		manager->m_pParent = this;
		m_children.push_back(manager);
		return manager;
	}

	
	/** 木構造全体から指定された名前のリソースを検索・取得<br>
	 * 見つからなければ、引数を元に新たに生成する。
	 * @param name リソース名
	 * @param parameter リソース作成時の引数（指定しなくてもよい） 
	 * @return 要求されたリソース
	 */
	template <class T >
	std::shared_ptr<T> ResourceManager<T >::getResource(const mof::tstring& name){
		//自分のリストから探す
		RESOURCE_MAP::const_iterator n = m_resources.find(name);
		if (n != m_resources.end()) {
			return n->second;
			//return (std::shared_ptr<T>&)n->second;
		}
		
		//子のリストから探す

		//親のリストから探す

		//なければ作成する
		std::shared_ptr<T> resource( new T( name ) );
		DEBUG_PRINT(name << _T("が生成されました") );
		m_resources.insert(RESOURCE_MAP::value_type(name , resource));
		n = m_resources.find(name);
		return n->second;
		//return (std::shared_ptr<T>&)n->second;
	}

	
	template <class T>
	void ResourceManager<T>::addResource(const TCHAR* const name , std::shared_ptr<T>& resource){
		m_resources.insert(RESOURCE_MAP::value_type(mof::tstring(name) , resource));
	}


	/*template <class T , typename K >
	std::shared_ptr<T>& ResourceManager<T , K>::findResource(mof::tstring& name , K parameter){

	}*/


};
