#include "GameCore.h"

void GameCore::initGame(HWND _hWnd, int _width, int _height, bool _bWindowed){
	aCoreGraphic_.initD3D(_hWnd, _width, _height, _bWindowed);
	aCoreInput_.initDInput(_hWnd);
	aOggPlayer_.InitDirectSound(_hWnd);

	aRenderPocket_.setD3DDevice(aCoreGraphic_.getD3DDevice());
	aRenderPocket_.setSprite(aCoreGraphic_.getSprite());

	//Game 처음으로 시작될때 로딩되어야 할 것들
	pCurrentRenderQueuePocket_ = &mainRenderQueuePocket_;
	pCurrentRObjectPocket_ = &mainRObjectPocket_;
	loadXmlFile_("start.xml");
	loadSceneObject_(0);

	aOggPlayer_.OpenOgg("resource/game_resource/london.ogg");
	aOggPlayer_.Play(true);
}

void GameCore::run(){
	MSG msg;
	ZeroMemory( &msg, sizeof(msg) );
	while( msg.message != WM_QUIT ){
		if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) ){
			TranslateMessage( &msg );
			DispatchMessage( &msg );
		}else{
			aOggPlayer_.Update();
			switch(aControlTable_.controlType){
				case PROCESS:
					for(pItrRObject_=pCurrentRObjectPocket_->begin();
						pItrRObject_ != pCurrentRObjectPocket_->end(); pItrRObject_++){
						(*pItrRObject_)->process();
					}
				break;
				case COMMAND:
					while(pCommandElement_){
						key_ = pCommandElement_->Attribute("oper");
						if(!commandOper_[key_]){
							MessageBox(NULL, "Error in Render XML (Command Node)", "Error Message", MB_OK | MB_ICONERROR);
							exit(1);
						}
						(this->*commandOper_[key_])(pCommandElement_);
						pCommandElement_ = pCommandElement_->NextSiblingElement("command");
						if(aControlTable_.controlType == PROCESS){
							break;
						}
					}
					aControlTable_.controlType = PROCESS;
				break;
			}
			aCoreGraphic_.getD3DDevice()->Clear(0,NULL,D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,D3DCOLOR_XRGB(100,100,100),1.0f,0);
			aCoreGraphic_.getD3DDevice()->BeginScene();
			aCoreGraphic_.camera(0,0,0);
			aRenderPocket_.render();
			aCoreGraphic_.showFPS();
			aCoreGraphic_.getD3DDevice()->EndScene();
			aCoreGraphic_.getD3DDevice()->Present(NULL,NULL,NULL,NULL);
		}
	}
}

void GameCore::putRenderPocket_(TiXmlElement* _pRenderElement){
	while(_pRenderElement){
		key_ = _pRenderElement->Attribute("type");
		if(!makeRenderQueue_[key_]){
			MessageBox(NULL, "Error in Render XML (Render Node)", "Error Message", MB_OK | MB_ICONERROR);
			exit(1);
		}
		RenderQueue* pRenderQueue = makeRenderQueue_[key_](aRenderPocket_, _pRenderElement);
		pCurrentRenderQueuePocket_->push_back(pRenderQueue);
		_pRenderElement = _pRenderElement->NextSiblingElement("list");
	}
}

void GameCore::putRObjectPocket_(TiXmlElement* _pRObjectElement){
	while(_pRObjectElement){
		int render; _pRObjectElement->Attribute("render", &render);
		key_ = _pRObjectElement->Attribute("type");
		if(!makeRObject_[key_]){
			MessageBox(NULL, "Error in XML (RObject Node)", "Error Message", MB_OK | MB_ICONERROR);
			exit(1);
		}
		RObject* pRObject = makeRObject_[key_](_pRObjectElement);
		pRObject->setRObject(&aCoreGraphic_, &aCoreInput_, &aOggPlayer_, &aControlTable_);
		(*pCurrentRenderQueuePocket_)[render]->vectorRObject.push_back(pRObject);
		pCurrentRObjectPocket_->push_back(pRObject);
		_pRObjectElement = _pRObjectElement->NextSiblingElement("list");
	}
}

inline void GameCore::loadXmlFile_(const char* _fileName){
	if ( !xmlDoc_.LoadFile(_fileName) ){
		const char* errorMsg = xmlDoc_.ErrorDesc();
		MessageBox(NULL, errorMsg, "Error Message", MB_OK | MB_ICONERROR);
		exit( 1 );
	}
}

inline void GameCore::loadSceneObject_(int _sceneNum){
	TiXmlHandle docHandle( &xmlDoc_ );
	TiXmlHandle scene = docHandle.FirstChild("stage").Child( "scene", _sceneNum );
	TiXmlElement* pRenderElement = scene.FirstChild("Render").FirstChild("list").Element();
	assert(pRenderElement->Attribute("type"));
	putRenderPocket_(pRenderElement);

	TiXmlElement* pRObjectElement = scene.FirstChild("RObject").FirstChild("list").Element();
	assert(pRObjectElement);
	putRObjectPocket_(pRObjectElement);

	TiXmlElement* pControlElement = scene.FirstChild("control").Element();
	const char *strControlType = pControlElement->Attribute("type");
	if(strcmp("mode", strControlType) == 0){
		string key(pControlElement->Attribute("mode"));
		aControlTable_.setControlType(key.c_str());
	}else if(strcmp("script", strControlType) == 0){
		int index; pControlElement->Attribute("index", &index);
		TiXmlElement* pScriptElement = scene.FirstChild("script").Child("list", index).Element();
		assert(pScriptElement->Attribute("mode"));
		controlScript_(pScriptElement);
	}
}
void GameCore::clearMainPocket_(){
    for(pItrRenderQueue_ = mainRenderQueuePocket_.begin();
		pItrRenderQueue_ != mainRenderQueuePocket_.end(); pItrRenderQueue_++){
		delete *pItrRenderQueue_;
	}
	for(pItrRObject_ = mainRObjectPocket_.begin();
		pItrRObject_ != mainRObjectPocket_.end(); pItrRObject_++){
		delete *pItrRObject_;
	}
}

void GameCore::clearScriptPocket_(){
    for(pItrRenderQueue_ = scriptRenderQueuePocket_.begin();
		pItrRenderQueue_ != scriptRenderQueuePocket_.end(); pItrRenderQueue_++){
		delete *pItrRenderQueue_;
	}
	for(pItrRObject_ = scriptRObjectPocket_.begin();
		pItrRObject_ != scriptRObjectPocket_.end(); pItrRObject_++){
		delete *pItrRObject_;
	}
}

void GameCore::controlScript_(TiXmlElement* _pScriptElement){
	if(strcmp("command", _pScriptElement->Attribute("mode")) == 0){
		aControlTable_.controlType = COMMAND;
		pCommandElement_ = _pScriptElement->FirstChildElement("command");
		while(pCommandElement_){
            key_ = pCommandElement_->Attribute("oper");
			if(!commandOper_[key_]){
				MessageBox(NULL, "Error in Render XML (Command Node)", "Error Message", MB_OK | MB_ICONERROR);
				exit(1);
			}
			(this->*commandOper_[key_])(pCommandElement_);
			pCommandElement_ = pCommandElement_->NextSiblingElement("command");
			if(aControlTable_.controlType == PROCESS){
				break;
			}
		}
		aControlTable_.controlType = PROCESS;
	}else if(strcmp("load", _pScriptElement->Attribute("mode")) == 0){
		clearScriptPocket_();
		pCurrentRenderQueuePocket_ = &scriptRenderQueuePocket_;
		pCurrentRObjectPocket_ = &scriptRObjectPocket_;
		TiXmlElement* pRenderElement = _pScriptElement->FirstChildElement("Render");
		assert(pRenderElement->Attribute("type"));
		putRenderPocket_(pRenderElement);

		TiXmlElement* pRObjectElement = _pScriptElement->FirstChildElement("RObject");
		assert(pRObjectElement->Attribute("type"));
		putRObjectPocket_(pRObjectElement);
	}
}