#include "BattleScene.h"
#include "mof/GraphicsDevice.h"
#include "mof/AmbientLight.h"
#include "mof/ConsoleIO.h"
#include "mof/KeyFrameAnimation.h"
#include <math.h>
#include "CommandMenu.h"
#include "FixedBattler.h"
#include "DataBasedBattler.h"
#include "BattlerGroup.h"
#include "Common.h"

et::BattleScene::BattleScene(mof::TextureResource& nullTexture)
: et::GameScene() , m_pCurrentFrame() , m_pHeroBattler(NULL)
{
	
	m_pMeshManager = NULL;
	m_pCamera = NULL;
	m_pCurrentFrame = NULL;
	m_popFlag = false;
	m_clearFlag = false;
	m_pBattleSystem = NULL;
	m_pBattleResultWindow = NULL;
	m_pBattleData = NULL;

}

et::BattleScene::~BattleScene(void)
{
	delete m_back;
	delete m_pCamera;
	delete m_pBattleSystem;
	for(std::list<et::BattlerWindow*>::iterator itr = m_battlerWindowList.begin() ; itr != m_battlerWindowList.end() ; ++itr){
		delete *itr;
	}
	delete m_pBattleResultWindow;
	

}


bool et::BattleScene::initialize(){
	

	m_back = new mof::Sprite(mof::Line2D(0 , 0 , 640 , 480) , mof::Line2D(0 , 0 , 64 , 64) , 
		m_pTextureManager->getResource(mof::tstring(_T("null"))));
	m_back->setCornerColor(mof::createColor(55 , 55 , 55));
	

	mof::GraphicsDevice::getInstance()->setProjectionTransform(0.01f , 50.0f);
	mof::GRAPHICS_DEVICE pDevice = mof::GraphicsDevice::getInstance()->getGraphicsDevice();

	m_field = m_pMeshManager->getResource(mof::tstring(_T("model/battleField0.x")));

	//バトルデータの初期化
	BattlerGroup* pGroup = new BattlerGroup();	
	et::BattlerParameter parameter;
	parameter.hp = 50;
	parameter.maxHp = 50;
	parameter.attack = 25;
	parameter.diffence = 10;
	parameter.actionPoint = 3;//3にすべき
	parameter.guard = false;
	parameter.alive = true;
	parameter.dActionPoint = 0;
	parameter.name = _T("リース");
	parameter.speed = 10;
	m_pHeroBattler = new FixedBattler(et::HERO , parameter , m_pTextureManager , m_pGameData);
	m_battlerWindowList.push_back(new BattlerWindow( m_pTextureManager , m_pHeroBattler ));
	pGroup->addBattler(et::HERO , m_pHeroBattler);
	et::BattlerFacade* pBattler = m_pHeroBattler;

	/*pBattler = new DataBasedBattler( _T("ラミアンハーピー") , m_pDataResourceManager ,  m_pTextureManager , _T('A'));
	m_battlerWindowList.push_back(new BattlerWindow( m_pTextureManager , pBattler ));
	pGroup->addBattler(et::ENEMY , pBattler);

	pBattler = new DataBasedBattler( _T("マンドラゴラ") , m_pDataResourceManager ,  m_pTextureManager , _T('B'));
	m_battlerWindowList.push_back(new BattlerWindow( m_pTextureManager , pBattler ));
	pGroup->addBattler(et::ENEMY , pBattler);

	pBattler = new DataBasedBattler( _T("ロッキー") , m_pDataResourceManager ,  m_pTextureManager , _T('C'));
	m_battlerWindowList.push_back(new BattlerWindow( m_pTextureManager , pBattler ));
	pGroup->addBattler(et::ENEMY , pBattler);*/

	mof::DataRow unitData(m_pDataResourceManager->getResource(_T("data/monster.unit.csv")) , 0);
	pGroup->addEnemyBattlers(unitData , et::Common(m_pTextureManager , m_pMeshManager , m_pDataResourceManager));
	std::vector<et::BattlerFacade*> enemyList = pGroup->getEnemyBattlerList();
	for(std::vector<et::BattlerFacade*>::iterator itr = enemyList.begin() ; itr != enemyList.end() ; ++itr){
		m_battlerWindowList.push_back(new BattlerWindow(m_pTextureManager , *itr));
	}

	parameter.name = _T("ガルナクリフ");
	pBattler = new FixedBattler(et::IDEAL , parameter , m_pTextureManager);
	m_battlerWindowList.push_back(new BattlerWindow( m_pTextureManager , pBattler ));
	pGroup->addBattler(et::IDEAL , pBattler);
	
	parameter.name = _T("ボボ");
	pBattler = new FixedBattler(et::IDEAL , parameter , m_pTextureManager);
	m_battlerWindowList.push_back(new BattlerWindow( m_pTextureManager , pBattler ));
	pGroup->addBattler(et::IDEAL , pBattler);

	parameter.name = _T("マース");
	pBattler = new FixedBattler(et::IDEAL , parameter , m_pTextureManager);
	m_battlerWindowList.push_back(new BattlerWindow( m_pTextureManager , pBattler ));
	pGroup->addBattler(et::IDEAL , pBattler);

	layoutBattlers(pGroup);
	m_pBattleData = new BattleData(m_pTextureManager , m_pGameData , pGroup);
	

	mof::AmbientLight(mof::createColor(255 , 255 , 255)).reflect();

	m_pCamera = new mof::Camera(mof::Vector3D(0.0f , 1.1f  , -1.4f) , mof::Vector3D(0.0f , 0 , 0.5f) , mof::Vector3D(0.0f , 1.0f , 0.0f));
	m_pCamera->reflect();

	//コマンドメニュー
	m_pCurrentFrame = new et::CommandMenu(m_pTextureManager , m_pBattleData);
	m_menuStack.push_back(mof::Container2D());
	m_menuStack.back().add(m_pCurrentFrame);
	m_translationScheduler.add(0 , m_pCurrentFrame->getAnimationSet());

	
	return true;
}

bool compareTo( mof::Component3D* &a ,   mof::Component3D* &b){
		return (*a).getPosition().z > (*b).getPosition().z;
	}

	
bool et::BattleScene::draw(){
	//m_pCapturer->capture();

	mof::GraphicsDevice::getInstance()->setAlphaBlendingMode(mof::GraphicsDevice::BLENDING_MODE_ALPHA);
	mof::GraphicsDevice::getInstance()->setZBuffer(false);
	
	m_back->draw();

	mof::GraphicsDevice::getInstance()->setZBuffer(true);
	mof::GraphicsDevice::getInstance()->clearZBuffer();
	m_field->draw();

	//Zソートして描画
	std::vector< mof::Component3D*> orderList;
	orderList.reserve(100);
	for(BattlerList::const_iterator itr = m_pBattleData->getBattlerGroup()->getBattlerList().begin() ;
		itr != m_pBattleData->getBattlerGroup()->getBattlerList().end() ; ++itr){
		orderList.push_back((*itr)->getGraphicsObject());
	}
	std::sort(orderList.begin() , orderList.end() , compareTo);
	for(std::vector<mof::Component3D*>::iterator itr = orderList.begin() ; itr != orderList.end() ; ++itr)(*itr)->draw();

	if(m_pBattleSystem != NULL){
		std::list<mof::GraphicsModelPtr> modelList;
		m_pBattleSystem->getModelList(modelList);
		for(std::list<mof::GraphicsModelPtr>::iterator itr = modelList.begin() ; itr != modelList.end() ; ++itr){
			(*itr)->draw();
		}
	}


	//mof::GraphicsDevice::getInstance()->setLight(false);
	mof::GraphicsDevice::getInstance()->setZBuffer(false);
	

	for(std::list<mof::Container2D>::iterator itr = m_menuStack.begin() ; itr != m_menuStack.end() ; ++itr){
		(*itr).draw();
	}
	
	
	if(m_pBattleSystem == NULL){
		for(std::list<et::BattlerWindow*>::iterator itr = m_battlerWindowList.begin() ; itr != m_battlerWindowList.end() ; ++itr){
			(*itr)->draw();
		}
	}
	if(m_pBattleResultWindow != NULL)m_pBattleResultWindow->draw();

	return true;
}


bool et::BattleScene::update(){
	
	if(m_translationScheduler.isFinalized() && m_popFlag){
		m_menuStack.pop_back();
		m_popFlag = false;
	}
	if(m_translationScheduler.isFinalized() && m_clearFlag){
		m_menuStack.clear();
		m_clearFlag = false;
	}
	

	if( m_pCurrentFrame != NULL && m_translationScheduler.isFinalized() && !m_pBattleData->isOver()){
		//ウィンドウに対するキー
		if(m_pInputReceiver->checkKeyPressed(mof::InputReceiver::UP))m_pCurrentFrame->getSelectionModel()->up();
		else if(m_pInputReceiver->checkKeyPressed(mof::InputReceiver::DOWN))m_pCurrentFrame->getSelectionModel()->down();
		else if(m_pInputReceiver->checkKeyPressed(mof::InputReceiver::LEFT))m_pCurrentFrame->getSelectionModel()->left();
		else if(m_pInputReceiver->checkKeyPressed(mof::InputReceiver::RIGHT))m_pCurrentFrame->getSelectionModel()->right();
		else if(m_pInputReceiver->checkKeyPressed(mof::InputReceiver::Z) && 
			m_pCurrentFrame->getSelectionModel()->getSelectingItem()->isAvailable()){
			
			int selectedIndex = m_pCurrentFrame->getSelectionModel()->getSelectingIndex();
			MyFrame* pPrevFrame = m_pCurrentFrame;
			MyFrame* pNextFrame = m_pCurrentFrame->performAction();
			if(pNextFrame != m_pCurrentFrame){
				//ウィンドウの遷移
				m_translationScheduler.clear();
				if(!m_pCurrentFrame->isVisible())m_translationScheduler.add(0 , m_pCurrentFrame->getAnimationSet());
				m_pCurrentFrame = pNextFrame;
				if(m_pCurrentFrame != NULL){
					m_translationScheduler.add(0 , m_pCurrentFrame->getAnimationSet());
					m_menuStack.push_back(mof::Container2D());
					m_menuStack.back().add(m_pCurrentFrame);
				}

			}
			//特化処理
		}
		else if(m_pInputReceiver->checkKeyPressed(mof::InputReceiver::X) && m_menuStack.size() > 1){//トップメニュー以外

			//メニュースタックをポップする
			m_translationScheduler.clear();
			std::list<mof::Container2D>::iterator itr = m_menuStack.end();
			--itr;//最後尾の要素を指す
			for(int i = 0 ; i < (*itr).size() ; ++i){
				(*itr).get(i)->setVisible(false);
				m_translationScheduler.add(0 , (*itr).get(i)->getAnimationSet());
			}
			m_popFlag = true;
			if(m_menuStack.size() >= 2){
				//後ろから２番目の要素を復活
				--itr;
				for(int i = 0 ; i < (*itr).size() ; ++i){
					if(dynamic_cast<MyFrame*>((*itr).get(i))->isVisible())continue;
					(*itr).get(i)->setVisible(true);
					m_translationScheduler.add(0 , (*itr).get(i)->getAnimationSet());
				}
				m_pCurrentFrame = dynamic_cast<MyFrame*>((*itr).get(0));
			}
			else m_pCurrentFrame = NULL;
		}

	}
	

	if(m_pBattleData->hasBattleAction() && m_pBattleSystem == NULL){
		//全メニューを閉じる
		m_translationScheduler.clear();
		for(std::list<mof::Container2D>::iterator itr = m_menuStack.begin() ; itr != m_menuStack.end() ; ++itr){
			for(int i = 0 ; i < (*itr).size() ; ++i){
				if(!dynamic_cast<MyFrame*>((*itr).get(i))->isVisible())continue;
				(*itr).get(i)->setVisible(false);
				m_translationScheduler.add(0 , (*itr).get(i)->getAnimationSet());
			}
		}
		m_pCurrentFrame = NULL;
		m_clearFlag = true;
		m_pHeroBattler->setBattleCommand(m_pBattleData->pollBattleAction());
		m_pBattleSystem = new BattleSystem(m_pBattleData , &m_turnScheduler , et::Common(m_pTextureManager , m_pMeshManager , m_pDataResourceManager));
		if(m_pBattleData->getBattlerGroup()->getHeroBattler()->getParameter().guard){
			//待機アニメを変更
			m_pBattleData->getBattlerGroup()->getHeroBattler()->setAidlingAnimation(m_pBattleData->getBattlerGroup()->getHeroBattler()->getPosition());
		}
		m_turnScheduler.clear();
	}
	else if(m_pBattleSystem != NULL ){
		if(m_pInputReceiver->checkKeyPressed(mof::InputReceiver::Z))m_pBattleSystem->notifyPushKey();
		m_pBattleSystem->update();
		if(m_pBattleSystem->isFinalized() && m_menuStack.empty()){
			delete m_pBattleSystem;
			m_pBattleSystem = NULL;
				
			if(m_pBattleData->getBattlerGroup()->getHeroBattler()->getParameter().guard){
				//待機アニメを変更
				et::BattlerParameter parameter = m_pBattleData->getBattlerGroup()->getHeroBattler()->getParameter();
				parameter.guard = false;
				m_pBattleData->getBattlerGroup()->getHeroBattler()->setParameter(parameter);
				m_pBattleData->getBattlerGroup()->getHeroBattler()->setAidlingAnimation(m_pBattleData->getBattlerGroup()->getHeroBattler()->getPosition());
			}

			if(m_pBattleData->isOver()){
				//戦闘終了状態へ移行
				m_pBattleData->setBattleAction(et::BattleAction());
				m_pBattleResultWindow = new MyWindow(mof::Sprite::createSpriteFromText(_T("バトル終了") , 17) , m_pTextureManager);
			}
			else {
				m_translationScheduler.clear();
				m_pCurrentFrame = new et::CommandMenu(m_pTextureManager , m_pBattleData);
				m_menuStack.push_back(mof::Container2D());
				m_menuStack.back().add(m_pCurrentFrame);
				m_translationScheduler.add(0 , m_pCurrentFrame->getAnimationSet());
			}
		}
	}


	if(m_pBattleSystem != NULL){
		std::list<mof::GraphicsModelPtr> modelList;
		m_pBattleSystem->getModelList(modelList);
		for(std::list<mof::GraphicsModelPtr>::iterator itr = modelList.begin() ; itr != modelList.end() ; ++itr){
			(*itr)->update();
		}
	}


	//メニューの更新
	for(std::list<mof::Container2D>::iterator itr = m_menuStack.begin() ; itr != m_menuStack.end() ; ++itr){
		for(int i = 0 ; i < (*itr).size() ; i++)(*itr).get(i)->update();
	}
	for(std::list<et::BattlerWindow*>::iterator itr = m_battlerWindowList.begin() ; itr != m_battlerWindowList.end() ; ++itr){
		(*itr)->update();
	}
	if(m_pBattleResultWindow != NULL)m_pBattleResultWindow->update();

	m_pCamera->reflect();
	for(BattlerList::const_iterator itr = m_pBattleData->getBattlerGroup()->getBattlerList().begin() ;
		itr != m_pBattleData->getBattlerGroup()->getBattlerList().end() ; ++itr){
		(*itr)->getGraphicsObject()->update();
	}

	mof::Billboard::updateBillboardDirection(m_pCamera);

	m_translationScheduler.update();
	m_turnScheduler.update();
	return true;
}


void et::BattleScene::layoutBattlers(BattlerGroup* pGroup){
	int nEnemy = pGroup->getEnemyBattlerList().size();
	int nIdeal = pGroup->getIdealBattlerList().size();
	
	int cntEnemy = 0;
	int cntIdeal = 0;
	float zTable[3][3] = { {0.6f , 0.6f , 0.6f} , { 0.8f , 0.4f , 0.6f} , {0.9f , 0.6f , 0.30f} };//[総数][番号]
	float xTable[3][3] = { {-0.2f , 0.0f , 0.0f} , { -0.0f , -0.3f , 0.0f} , {-0.05f , -0.2f , -0.35f} };//[総数][番号]
	float ixTable[3][3] = { {0.2f , 0.0f , 0.0f} , { 0.0f , 0.07f , 0.6f} , {0.1f , 0.2f , 0.25f} };//[総数][番号]

	BattlerFacade* pBattler = pGroup->getHeroBattler();
	pBattler->setAidlingAnimation(mof::Vector3D(0.3f , 0.0f , 0.6f));
	pBattler->setBasePosition(mof::Vector3D(0.3f , 0.0f , 0.6f));
	
	
	for(std::vector<BattlerFacade*>::const_iterator itr = pGroup->getEnemyBattlerList().begin() ; itr != pGroup->getEnemyBattlerList().end() ; ++itr){
		mof::KeyFrameAnimation* pAnimation = new mof::KeyFrameAnimation();
		(*itr)->setAidlingAnimation(mof::Vector3D(-0.45f + xTable[nEnemy-1][cntEnemy] , 0.0f , zTable[nEnemy-1][cntEnemy]));
		(*itr)->setBasePosition(mof::Vector3D(-0.45f + xTable[nEnemy-1][cntEnemy] , 0.0f , zTable[nEnemy-1][cntEnemy]));
		cntEnemy++;	
	}

	for(std::vector<BattlerFacade*>::const_iterator itr = pGroup->getIdealBattlerList().begin() ; itr != pGroup->getIdealBattlerList().end() ; ++itr){
		mof::KeyFrameAnimation* pAnimation = new mof::KeyFrameAnimation();
		(*itr)->setAidlingAnimation(mof::Vector3D(0.6 +ixTable[nIdeal-1][cntIdeal] , 0.0f , zTable[nIdeal-1][cntIdeal]));
		cntIdeal++;	
		
	}

}