//@STATE=嶌惉拞
//@DESCRIPTION ---------------------------------------------------------------
// Manager.h: Manager 僋儔僗偺僀儞僞乕僼僃僀僗
//	棜楌丗
//@DESCRIPTION_END -----------------------------------------------------------
//@AUTHOR=S.F.
///////////////////////////////////////////////////////////////////////////////

#if !defined(AFX_MANAGER_H__54ECBFD0_103D_4D71_83BB_83D948FD2892__INCLUDED_)
#define AFX_MANAGER_H__54ECBFD0_103D_4D71_83BB_83D948FD2892__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "windows.h"
#include "Exception.h"
#include <iosfwd>
#include "stdafx.h"
namespace sf {
	namespace application {
		namespace scene {
			// ----------------------------------------------------------------
			// 僐儞僥僫僋儔僗 
			// ----------------------------------------------------------------
			typedef std::list<Scene *> SceneContainer;

			class Container : public Listener
			{
				DECLARE_SINGLETON(Container)

				Container();
			public:
				~Container();

				void add(Scene * const pScene)
				{  
					mContainer.push_back(pScene);
					pScene->addListener(this);
				};

				// 僔乕儞億僀儞僞偺庢摼
				void move(void)
				{
					
					if(mContainer.empty()){
						throw sf::system::RecoverbleErrorException("Scene is Empty",__FILE__,__LINE__,sf::system::Exception::SCENE_IS_EMPTY);
					};

					for(SceneContainer::iterator it = mContainer.begin();it != mContainer.end();++it)
					{
						if(*it != NULL){
							if((*it)->isActive()){
								(*it)->move();
							}
						}
					}
				};

				// NULL億僀儞僞偺嶍彍
				void eraseNull(void)
				{
					for(SceneContainer::iterator it = mContainer.begin();it != mContainer.end();++it)
					{
						if(*it == NULL){
							it = mContainer.erase(it);
						}
					}

				};

				// 僔乕儞廔椆帪偺張棟 
				virtual void endOfScene(Scene * const pScene)
				{	
					for(SceneContainer::iterator it = mContainer.begin();it != mContainer.end();++it)
					{
						if(*it == pScene){
							*it = NULL;
							break;
						}
					}

				};

				// 僔乕儞廔椆帪偺張棟 
				const bool findScene(Scene * const pScene)
				{	
					for(SceneContainer::iterator it = mContainer.begin();it != mContainer.end();++it)
					{
						if(*it == pScene){
							return true;
						}
					}
					return false;
				};
				
				virtual void exitKeyPressed(Scene * const pScene)
				{	endOfScene(pScene);};
			private:
				 SceneContainer mContainer;
			};// Container
			
			
			// 亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅
			// 僔乕儞俢俴俴惂屼梡僋儔僗
			// 摦揑偍傛傃惷揑偵僔乕儞俢俴俴傪儘乕僪丄奐曻偡傞巇慻傒傪採嫙偡傞
			// 亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅

			class DLL;

			std::ostream & operator <<
                ( std::ostream &rOStrm    
                , const sf::application::scene::DLL & rDll);  
			
			std::istream& operator >> 
				(	std::istream& rIStrm, 
				sf::application::scene::DLL &rDLL);

			// DLL
			class DLL : public sf::application::scene::Listener
			{
			public:
				friend std::ostream & operator <<
                ( std::ostream &rOStrm    // cStrStrm
	                , const sf::application::scene::DLL & rDll);
				friend std::istream& operator >> 
				(	std::istream& rIStrm, 
				sf::application::scene::DLL &rDLL);
				
				// LIFE CYCLE;
				DLL()
				{
					mbPreLoad = false;
					mhModule = NULL;
					mpCreateFunc = NULL;
				};

				DLL(const char * pDLLName,const bool bPreLoad = false)
				{
					mDLLName = pDLLName;
					if(bPreLoad){
						mbPreLoad = true;
						mhModule = LoadLibrary(pDLLName);
						mpCreateFunc = (CreateSceneMethod)GetProcAddress(mhModule,"createScene");

					} else {
						mbPreLoad = false;
						mhModule = NULL;
						mpCreateFunc = NULL;
					}
				};

				~DLL()
				{
					// 嶍彍偝傟傞慜偵Talker傊偺Listner搊榐傪嶍彍
					std::vector<Scene *>::iterator it = mSceneList.begin();
					while(it != mSceneList.end()){
						(*it)->removeListener(this);
						it = mSceneList.erase(it);
						it++;
					}
					// 曐帩偟偰偄傞儔僀僽儔儕傪奐曻偡傞
					if(mhModule){
						FreeLibrary(mhModule);
					}

				};

				// OPERATORS //
				// OPERATIONS //
				// DLL偺儘乕僪
				void load()
				{
					if(mhModule) return;
					mhModule = LoadLibrary(mDLLName.c_str());
					mpCreateFunc = (CreateSceneMethod)GetProcAddress(mhModule,"createScene");
				};

				// DLL撪偺僔乕儞偺嶌惉
				Scene * const createScene(const int id,const bool bAddSceneContainer = true)
				{
					if(mhModule){
						Scene * pscene = (*mpCreateFunc)(id);
						pscene->addListener(this);
						mSceneList.push_back(pscene);
						addRef();
						if(bAddSceneContainer){
							Container::instance()->add(pscene);
						}
						return pscene;
					};
					return NULL;
				}

				// 僲乕儅儖廔椆
				void endOfScene(Scene * const pScene)
				{
					std::vector<Scene *>::iterator it = mSceneList.begin();
					while(it != mSceneList.end()){
						if(*it == pScene){
							mSceneList.erase(it);
							break;
						}
						it++;
					}
					release();
				};

				// Exit僉乕偑墴偝傟偨
				void exitKeyPressed(Scene * const pScene){;};

				// INQUIRY //
				// DLL偑儘乕僪偝傟偰偄傞偐偳偆偐
				const bool isLoad() const {return (mhModule != NULL);};
				const std::string & name(void){return mDLLName;};
			private:
				// DLL偺奐曻
				void freeLibrary()
				{	FreeLibrary(mhModule);
					mhModule = NULL;
				};

				// 嶲徠僇僂儞僞偺壛嶼 
				void addRef(){mRefCount++;};

				// 嶲徠僇僂儞僞偺尭嶼丄儕儕乕僗 
				void release()
				{	if(mRefCount){
						mRefCount--;
						if(!mRefCount && !mbPreLoad){
							freeLibrary();
						}
					}
				};

				std::string mDLLName;
				HMODULE mhModule;
				bool mbPreLoad;
				CreateSceneMethod mpCreateFunc;
				int mRefCount;

				// Talker傊偺億僀儞僞傪曐帩 //
				std::vector<Scene *> mSceneList;

			};// DLL 僋儔僗;
			
			// DLL儘乕僨傿儞僌梡僆儁儗乕僞僆乕僶乕儘乕僪
			std::ostream& operator <<
                ( std::ostream &rOStrm    
                , const sf::application::scene::DLL & rDLL)   
			{
				rOStrm << rDLL.mDLLName;
				if(rDLL.mbPreLoad){
					rOStrm << " PRELOAD";
				} else {
					rOStrm << " DELAYLOAD";
				}
				return rOStrm;
			};// std::ostream & operator<<;

			std::istream& operator >> 
				(	std::istream& rIStrm, 
				sf::application::scene::DLL &rDLL)
			{
				std::string tmp;
				rIStrm >> rDLL.mDLLName;
				rIStrm >> tmp;
				
				if(tmp == "PRELOAD"){
					rDLL.mbPreLoad = true;
				} else {
					rDLL.mbPreLoad = false;
				}
				return rIStrm;
			};// std::istream& operator >> 
			
			// 亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅
			// DLL娗棟僋儔僗 
			// 亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅
			class DLLManager
			{
				DECLARE_SINGLETON(DLLManager)
			public:
				~DLLManager(){
					unload();
				};//

				// 僔乕儞DLL偺儘乕僪 //
				void load(const char * pFileName)
				{
					std::fstream dll_conf(pFileName,std::ios::in);
					if(!dll_conf.is_open()){
						throw sf::system::FatalErrorException("Scene Def File Not Found",__FILE__,__LINE__);
					}
					
					int i = 0;
					int scene_index;

					while(!dll_conf.eof())
					{
						dll_conf >> scene_index;
						DLL* pdll = new DLL;
						dll_conf >> (*pdll);
						int j;
						int dll_index = i;
						
						for(j = 0;j < mDLLs.size();j++){
							if(mDLLs[j]->name() == pdll->name()){
								dll_index = j;
								break;
							}
						}
						
						if(dll_index == i){
							mDLLs.push_back(pdll);
						} else {
							delete pdll;
						};

						Node* nd = new Node;
						nd->mDLLIndex = dll_index;
						nd->mDLLInternalIndex = scene_index;
						mSceneIndex.push_back(nd);
					};

				};// load()
				
				// 傾儞儘乕僪 //
				void unload(){

					std::vector<Node *>::iterator it = mSceneIndex.begin();
					while(!mSceneIndex.empty()){
						delete *it;
						it = mSceneIndex.erase(it);
					}

					std::vector<sf::application::scene::DLL *>::iterator it1 = mDLLs.begin();
					while(!mDLLs.empty()){
						delete *it1;
						it1 = mDLLs.erase(it1);
					}

				};// unload()

				// 僔乕儞僀儞僗僞儞僗偺惗惉 //
				Scene * const createScene(const int id,const bool bAddSceneContainer = true){
					return mDLLs[mSceneIndex[id]->mDLLIndex]->createScene(mSceneIndex[id]->mDLLInternalIndex,bAddSceneContainer); 
				};// createScene()

			private:
				
				struct Node {
					int mDLLIndex;
					int mDLLInternalIndex;
				};

				// DLL偺儕僗僩
				std::vector<sf::application::scene::DLL *> mDLLs;
				// 僔乕儞仺DLL懳墳昞
				std::vector<Node *> mSceneIndex;
			};// DLLManager
			
/*
			// ----------------------------------------------------------------
			// 曇廤夋柺僷儔儊乕僞 僋儔僗 
			// ----------------------------------------------------------------
			class Game;

			SF_INTERFACE BGEditor
			{
			public:
				BGEditor(){;};
				virtual ~BGEditor(){;};
				// OPERATORS //
				// OPERATIONS //
				// ACCESS //
				virtual void game(Game * const pGame) = 0;
				virtual Game * const game(void) const = 0;
			};

			SF_INTERFACE DispositionEditor
			{
			public:
				DispositionEditorParameter(){;};
				virtual ~DispositionEditorParameter(){;};
				// OPERATORS //
				// OPERATIONS //
				// ACCESS //
				
				virtual void game(Game * const pGame) = 0;
				virtual Game * const game(void) const  = 0; 
			};
*/

		}
	}
}

#endif // !defined(AFX_MANAGER_H__54ECBFD0_103D_4D71_83BB_83D948FD2892__INCLUDED_)
