#include "GameScene.h"

#include "StaticData.h"

namespace MotionTest {
using namespace std;
using namespace MotionTestConsts;
using namespace HPL;
using namespace E3D;
using namespace BasicStaticDataConsts;
using namespace General;

GameScene::GameScene() : AbstractScene(){
}
GameScene::~GameScene() {
}

void GameScene::init() {

	int ret = 0;
	// マップ選択
	if( staticData->m_nScenarioIndex == 0 ) {
		staticData->set_GroundType( GroundType::PRACTICE_ROOM );
	} else if( staticData->m_nScenarioIndex == 2 ||
		staticData->m_nScenarioIndex == 3) 
	{
		staticData->set_GroundType( GroundType::WORM );

	} else if( staticData->m_nScenarioIndex == 5 ) {
		staticData->set_GroundType( GroundType::ZOMBIE );
	} else if( staticData->m_nScenarioIndex >= 6 ) {
		staticData->set_GroundType( GroundType::EVIL_STAR );
	} else {
		staticData->set_GroundType( GroundType::TEST );
	}


	BOOL bIsHPMax = TRUE;
	staticData->reset_Player( bIsHPMax );

	// 初期化
	staticData->m_EnemyManager.reset();
	staticData->m_ShotManager.reset();
	staticData->m_NeutralManager.reset();

	staticData->reset_Weapons();

	// BGM変更
	if( staticData->m_nScenarioIndex == 3 ) {
		staticData->set_BGMIndex( Sound::PANIC );
	} else if( staticData->m_nScenarioIndex >= 6 ) {
		staticData->set_BGMIndex( Sound::EVIL_STAR );
	} else {
		staticData->set_BGMIndex( Sound::GAME );
	}

	// コンソールを設置
	if( staticData->m_nScenarioIndex == 0 ||
		staticData->m_nScenarioIndex == 5)
	{
		char OBJ_FILE_PATH[][MAX_PATH] = {
			"Media\\Stage\\Stage0-PracticeRoom.txt",
			"Media\\Stage\\Stage1-zombie.txt",
		};


		// 配置情報読み込み
		vector<string> vecLines;
		ret = TextTool::load_StringLinesFromFile( OBJ_FILE_PATH[ staticData->m_nScenarioIndex == 0 ? 0:1 ], 
			&vecLines );
		if( ret ) {
			_ASSERT( 0 );
		}

		for( int i = 0; i < static_cast<int>(vecLines.size() ); i ++ ) {
			if( TextTool::is_SkipLine( vecLines[i] ) ) {
				continue;
			}

			// split
			vector<string> vecItems = TextTool::split( vecLines[i], "," );

			int nObjectType = atoi( vecItems[0].c_str() );
			int nType = atoi( vecItems[1].c_str() );
			float fX = static_cast<float>(atof( vecItems[2].c_str() ));
			float fY = static_cast<float>(atof( vecItems[3].c_str() ));
			float fZ = static_cast<float>(atof( vecItems[4].c_str() ));
			float fFaceX = static_cast<float>(atof( vecItems[5].c_str() ));
			float fFaceY = static_cast<float>(atof( vecItems[6].c_str() ));
			float fFaceZ = static_cast<float>(atof( vecItems[7].c_str() ));
			int nScenarioIndex = -1;
			if( static_cast<int>(vecItems.size()) > 8 ) {
				nScenarioIndex = atoi( vecItems[8].c_str() );
			}
			E3DObject* obj = NULL;
			if( nObjectType == 0 ) {
				obj = staticData->m_EnemyManager.search( nType );
			} else if( nObjectType == 1 ) {
				obj = staticData->m_NeutralManager.search( nType );
			} else {
				_ASSERT(0);
			}
			if( obj != NULL ) {
				obj->m_Move.m_vPosition = D3DXVECTOR3( fX, fY, fZ );
				ret = E3DSetPos( obj->m_nSigID, obj->m_Move.m_vPosition );
				staticData->face( D3DXVECTOR3( fFaceX, fFaceY, fFaceZ ),
					1, obj->m_nSigID, obj->m_Move.m_nQuoatanion ) ;
				
				obj->m_Game.m_nScenarioIndex = nScenarioIndex;
			} else {
				_ASSERT(0);
			}
		}
	}

	// シナリオリセット
	staticData->m_ScenarioManager.reset();
	staticData->m_ScenarioItem = NULL;
}
void GameScene::process() {
	int ret = 0;

	// キャラクターの移動等
	ret = this->frameMove();
	if( ret ){
		_ASSERT( 0 );
		return ;
	}

	// 描画等
	ret = this->render();
	if( ret ){
		_ASSERT( 0 );
		return ;
	}

}
void GameScene::quit() {
}
/** テキスト表示
  * @retval 成功時は0
  */
int GameScene::drawText() {
	int ret = 0;

	float zoom = 1.0f;

	int y = 10;
	int STEP = 20;

	vector<string> lines;
	
	lines.push_back( TextTool::get_String( "FPS:%d", staticData->get_FPS() ) );

	// 現在のフレームNoを取得
	int motid;
	int frameno;
	ret = E3DGetMotionFrameNo( staticData->get_Player()->m_nSigID, &motid, &frameno );


	////////////////////
	// プレイヤーの位置
	D3DXVECTOR3 vCameraPosition;
	D3DXVECTOR3 vPlayerPosition;
	//D3DXVECTOR3 vSatellite;

	E3DGetCameraPos( &vCameraPosition );
	E3DGetPos( staticData->get_Player()->m_nSigID, &vPlayerPosition );

	lines.push_back( TextTool::get_String( "PlayerPos[%5.2f,%5.2f,%5.2f]",
		vPlayerPosition.x, vPlayerPosition.y, vPlayerPosition.z ));

	lines.push_back( TextTool::get_String( "Mosuko num[%d]",
		staticData->m_EnemyManager.get_ValidNum(EnemyType::MOSUKO)+
		staticData->m_EnemyManager.get_ValidNum(EnemyType::MOSUKO_LONG)));

	for(int i = 0; i < static_cast<int>(lines.size()); i ++ ) {
		ret = E3DTool::drawText(
			10, y,			//pos XY
			255, 255, 255, 255,	//col RGBA
			zoom,				// zoom
			lines[i].c_str() );
		if( ret ) {
			_ASSERT( 0 );
			return ret;
		}
		y += STEP;
	}



	// 表示領域のウィンドウサイズ
	RECT rClientRect;
	staticData->get_ClientRect( &rClientRect );
	int nClientHeight = rClientRect.bottom - rClientRect.top;
	int nClientWidth = rClientRect.right - rClientRect.left;

	if( staticData->m_bNearByConsole ) {
		// コンソールに近づいたら[F]キーを押すよう表示する
		ret = E3DTool::drawTextWithFont(
			nClientWidth / 2 - 20, nClientHeight / 3 * 2,			//pos XY
			255, 255, 200, 255,	//col RGBA
			staticData->get_SwapChainID(), staticData->get_FontID(),				// zoom
			"[F]" );
		if( ret ) {
			_ASSERT( 0 );
			return ret;
		}
	}

	return 0;

}


/** 3Dレンダリング
  * @retval 0以外 処理に失敗した場合
  */
int GameScene::render() {
	int ret = 0;


	int nCurrentFrame = 0;
	int status;
	int counter = 0;


	/////////////////////////////
	// test
	// 表示数調整
/*	if(staticData->get_CurrentKeyBuffer(VK_UP)){
		staticData->m_nRenderNum += 1;
		if(staticData->m_nRenderNum >= OBJECT_MAX ) {
			staticData->m_nRenderNum = OBJECT_MAX;
		}
	}
	if(staticData->get_CurrentKeyBuffer(VK_DOWN)){
		staticData->m_nRenderNum -= 1;
		if(staticData->m_nRenderNum < 0 ) {
			staticData->m_nRenderNum = 0;
		}
	}*/

	// 地面のチェックイン
	ret = staticData->checkInGround();
	if( ret ){
		_ASSERT( 0 );
		return 1;
	}

	/////////////////////////////////////////
	// プレイヤー関連
	// チェックイン
	ret = E3DChkInView( staticData->get_SwapChainID(), staticData->get_Player()->m_nSigID, &status );
	if( ret ){
		_ASSERT( 0 );
		return 1;
	}

	if( staticData->is_Pause() == FALSE ) {
		// 地面との接触判定
		ret = staticData->checkPlayerOnGround();
		if( ret ){
			_ASSERT( 0 );
			return 1;
		}
	}

	/////////////////////////////////////////
	// ビルチェックイン
/*	ret = E3DChkInView( staticData->get_SwapChainID(), staticData->m_Building->m_nSigID,
		&status );
	if( ret ){
		_ASSERT( 0 );
		return 1;
	}*/

	////////////////////
	// 影付き描画
	staticData->renderWithShadow( TRUE, TRUE, FALSE, FALSE );

	/////////////////////////////////////////
	// シーン描画開始
	ret = E3DBeginScene( staticData->get_SwapChainID(), 1 );//skipflagは1（クリアしない）にすること
	if( ret ) { 
		_ASSERT( 0 );
		return 1;
	}

		if( staticData->m_nSelectedWallType >= 0 ) {
			// 壁と天井描画
			// sig id取得
			int hsid = staticData->m_mapWallSigMap[staticData->m_nSelectedWallType];

			// 通常描画
			if( E3DRender( staticData->get_SwapChainID(), hsid, 0, 1, 0, 0 ) ){
				_ASSERT( 0 );
				return 1;
			}

			// αブレンド描画
			if( E3DRender( staticData->get_SwapChainID(), hsid, 1, 1, 0, 0 ) ){
				_ASSERT( 0 );
				return 1;
			}
		}
		////////////////
		// ビル描画
//		ret = E3DRender( staticData->get_SwapChainID(), staticData->m_Building->m_nSigID, 
//			0,1,0,0);

		///////////////
		// 全ビルボード描画
		ret = E3DRenderBillboard( staticData->get_SwapChainID(), 0 );
		if( ret ) {
			_ASSERT( 0 );
			return ret;
		}

		//////////////
		// 敵の移動と描画
		ret = staticData->m_EnemyManager.process();

		////////////////
		// 弾の動作と描画
		ret = staticData->m_ShotManager.process();

		////////////////
		// そのたの動作と描画
		staticData->m_bNearByConsole = FALSE;
		ret = staticData->m_NeutralManager.process();

		/////////////////
		// UI表示
		ret = E3DBeginSprite();
			RECT rClientRect;
			staticData->get_ClientRect( &rClientRect );
			int nClientHeight = rClientRect.bottom - rClientRect.top;
			int nClientWidth = rClientRect.right - rClientRect.left;

			if( staticData->get_CameraMode() != CameraMode::AT_TARGET_MODE ) {
				// GTA通常モード以外

				POINT pCenter;
				staticData->get_ClientCenter( &pCenter );

				// 照準表示
				int nSpriteW = -1;
				int nSpriteH = -1;
				ret = E3DGetSpriteSize( staticData->m_SpriteIndexManager.get( Sprite::CROSS_HAIR ), 
					&nSpriteW, &nSpriteH );
				if( ret ) {
					_ASSERT( 0 );
					return ret;
				}
				const float CROSS_HAIR_DELTA = 10.f;
				ret = E3DRenderSprite( staticData->m_SpriteIndexManager.get( Sprite::CROSS_HAIR),
					1, 1, D3DXVECTOR3(static_cast<FLOAT>(pCenter.x - nSpriteW / 2 + CROSS_HAIR_DELTA ),
					static_cast<FLOAT>(pCenter.y - nSpriteH / 2 + CROSS_HAIR_DELTA), 0.0f ) );
				if( ret ) {
					_ASSERT( 0 );
					return ret;
				}
			}

			// Life Frame
			int nLifeFrameWidth = -1;
			int nLifeFrameHeight = -1;
			ret = E3DGetSpriteSize( staticData->m_SpriteIndexManager.get( Sprite::LIFE_FRAME), 
				&nLifeFrameWidth, &nLifeFrameHeight );
			if( ret ) {
				_ASSERT( 0 );
				return ret;
			}
			ret = E3DRenderSprite( staticData->m_SpriteIndexManager.get( Sprite::LIFE_FRAME),
				1.f, 1.f, D3DXVECTOR3(
				static_cast<FLOAT>(LIFE_FRAME_MERGINE),
				static_cast<FLOAT>(nClientHeight - LIFE_FRAME_MERGINE - nLifeFrameHeight - WINDOW_FRAME_DELTA), 0.0f ) );
			if( ret ) {
				_ASSERT( 0 );
				return ret;
			}

			// Life
			float fLifeRate = staticData->get_Player()->m_Game.m_fHP / staticData->get_Player()->m_Game.m_fHPMax;
			int nSpriteW = -1;
			int nSpriteH = -1;
			ret = E3DGetSpriteSize( staticData->m_SpriteIndexManager.get( Sprite::LIFE_BAR), 
				&nSpriteW, &nSpriteH );
			if( ret ) {
				_ASSERT( 0 );
				return ret;
			}
			ret = E3DRenderSprite( staticData->m_SpriteIndexManager.get( Sprite::LIFE_BAR),
				1, fLifeRate, D3DXVECTOR3(
				static_cast<float>(LIFE_FRAME_MERGINE),
				static_cast<float>(nClientHeight - LIFE_FRAME_MERGINE - static_cast<float>(nSpriteH) * fLifeRate - WINDOW_FRAME_DELTA ), 0.0f ) );
			if( ret ) {
				_ASSERT( 0 );
				return ret;
			}

			// Guns
			int nGunWidth = -1;
			int nGunHeight = -1;
			int nSpriteID = staticData->get_Weapon()->get_SpriteID();
			ret = E3DGetSpriteSize( nSpriteID, 
				&nGunWidth, &nGunHeight );
			if( ret ) {
				_ASSERT( 0 );
				return ret;
			}
			ret = E3DRenderSprite( nSpriteID,
				1, 1, D3DXVECTOR3(
				static_cast<FLOAT>(LIFE_FRAME_MERGINE + nLifeFrameWidth + LIFE_AND_GUNS_MERGINE ),
				static_cast<FLOAT>(nClientHeight - LIFE_FRAME_MERGINE - nGunHeight - WINDOW_FRAME_DELTA ), 0.1f ) );
			if( ret ) {
				_ASSERT( 0 );
				return ret;
			}

			// 敵の体力表示
			ret = E3DGetSpriteSize( staticData->m_SpriteIndexManager.get( Sprite::ENEMY_LIFE_BAR ),
				&nSpriteW, &nSpriteH );
			counter = 0;
			for(std::list<EnemyLifeBar*>::iterator it = staticData->m_lstEnemyLifeBarList.begin();
				it != staticData->m_lstEnemyLifeBarList.end(); )
			{
				EnemyLifeBar* lifeBar = *it;

				// バーを伸縮
				float fRate = lifeBar->m_fHP / lifeBar->m_fHPMax;

				// ライフバー表示
				ret = E3DRenderSprite( staticData->m_SpriteIndexManager.get( Sprite::ENEMY_LIFE_BAR),
					fRate, 1, D3DXVECTOR3(
					static_cast<FLOAT>(nClientWidth - LIFE_FRAME_MERGINE - static_cast<FLOAT>(nSpriteW) * fRate),
					static_cast<FLOAT>(nClientHeight - LIFE_FRAME_MERGINE - (counter+1) * (nSpriteH + ENEMY_LIFE_BAR_INTERVAL_Y) - TEXT_DELTA_Y  ), 0.0f ) );
				// 体力数値
				ret = E3DTool::drawText(
					nClientWidth - LIFE_FRAME_MERGINE - nSpriteW - TEXT_DELTA_X, 
					nClientHeight - LIFE_FRAME_MERGINE - (counter+1) * (nSpriteH + ENEMY_LIFE_BAR_INTERVAL_Y )- TEXT_DELTA_Y ,			//pos XY
					200, 200, 255, UI_ALPHA,	//col RGBA
					1.2f,				// zoom
					"%s [%d/%d]",
					lifeBar->m_strName.c_str(), 
					static_cast<int>(lifeBar->m_fHP),
					static_cast<int>(lifeBar->m_fHPMax));
				if( ret ) {
					_ASSERT( 0 );
					return ret;
				}
				counter ++;
				if( lifeBar->m_Counter.step() & General::CounterStateType::ALL_LOOP_END ) {
					// 消える
					it = staticData->m_lstEnemyLifeBarList.erase(it );
					delete lifeBar;
				} else {
					it ++;
				}
			}

			// 弾数
			ret = E3DTool::drawText(
				LIFE_FRAME_MERGINE + nLifeFrameWidth + LIFE_AND_GUNS_MERGINE, 
				nClientHeight - LIFE_FRAME_MERGINE - nGunHeight - AMMO_TEXT_MERGINE,			//pos XY
				200, 200, 255, UI_ALPHA,	//col RGBA
				0.5f,				// zoom
				"[%d/%d]",
				staticData->get_Weapon()->get_LoadedAmmo(), staticData->get_Weapon()->get_ChargedAmmo());
			if( ret ) {
				_ASSERT( 0 );
				return ret;
			}

			// 文字列描画
			if( this->drawText()) {
				_ASSERT( 0 );
				return 1;
			}

			// シナリオ表示
			staticData->draw_Scenario( staticData->m_ScenarioItem );

		ret = E3DEndSprite();


		
		staticData->afterRenderCommon();
	if( E3DEndScene() ) {
		_ASSERT( 0 );
		return 1;

	}

	return 0;
}


int GameScene::frameMove() {
	int ret = 0;

	if( staticData->is_Pause() == FALSE ) {
		////////////////////////
		// プレイヤー操作
		// プレイヤーWASD移動
		staticData->movePlayer();

		//
		////////////////////  プレイヤー操作 end
		/////////////////////
		// プレイヤーの弾の発射
		staticData->shotPlayer();


		ret = staticData->updatePlayerMotion();

		if( staticData->m_nScenarioIndex == 0// ||
			//staticData->m_nScenarioIndex == 5
			) 
		{
		} else if( staticData->m_cntEnemyGenerateCounter.step() == CounterStateType::ALL_LOOP_END ) {
			// 敵の生成
			int nType = 0;
			if( staticData->m_nScenarioIndex == 1 ) {
				nType = EnemyType::CYCLOPS;
			} else if( staticData->m_nScenarioIndex == 2 ) {
				//ちっこいのだけ
				nType = EnemyType::WORM_SMALL;
			} else if( staticData->m_nScenarioIndex == 3 ) {
				//でかいのだけ
				nType = EnemyType::WORM_BIG;
			} else if( staticData->m_nScenarioIndex == 4 ) {
				//ワームだけ
				nType = MathTool::nextRandom<int>(1,3);
			} else if( staticData->m_nScenarioIndex == 5 ) {
				// ゾンビだけ
				nType = EnemyType::ZOMBIE;
			} else if( staticData->m_nScenarioIndex == 6 ) {
				// モス子だけ
				nType = EnemyType::MOSUKO + MathTool::nextRandom<int>(0,2);
			} else if( staticData->m_nScenarioIndex == 7 ) {
				// ゾンビBだけ
				nType = EnemyType::ZOMBIE_B;
			} else {
				// 全部
				nType = MathTool::nextRandom<int>(0, EnemyType::NUM_MAX);
			}

			// 登場させる
			E3DObject* obj = staticData->m_EnemyManager.search( nType );
			int nFrameNumMax = 
				static_cast<int>(
				staticData->m_cntEnemyGenerateCounter.get_FrameCounterMax() - 
				GENERATE_DECREASE_STEP );
			if( nFrameNumMax < 1 ) {
				nFrameNumMax = 1;
			}
			if( obj != NULL ) {
				obj->set_Valid( TRUE );
				E3DSetValidFlag( obj->m_nSigID, -1, TRUE );
				// 速度アップ
				obj->m_Move.m_fSpeed *= (2 + 2.f * static_cast<float>(DEFAULT_GENERATE_COUNTER - nFrameNumMax + 1) / static_cast<float>(DEFAULT_GENERATE_COUNTER));// 

				if( staticData->m_nScenarioIndex == 2 ||
					staticData->m_nScenarioIndex == 3 ||
					staticData->m_nScenarioIndex == 5 ) 
				{
					// 位置調整
					float ERR_X = 12000;
					float ERR_Z = 10000;
					float CENTER_X = -10000.f;
					float CENTER_Z = 8600.f;
					if( staticData->m_nScenarioIndex == 2 ||
						staticData->m_nScenarioIndex == 3 )
					{
						CENTER_X = 16400;
						CENTER_Z = 19000.f;
					}
					E3DSetPosOnGround( obj->m_nSigID, staticData->get_GroundSigID(),
						MAP_HEIGHT, MAP_MIN, 
					//D3DXVECTOR3 vPos(
						CENTER_X + MathTool::nextRandom<float>( -ERR_X, ERR_X ) ,// 0,
						CENTER_Z + MathTool::nextRandom<float>( -ERR_Z, ERR_Z ) );
					//obj->m_Move.m_vPosition = vPos;
					//E3DSetPos( obj->m_nSigID, vPos );
					E3DGetPos( obj->m_nSigID, &obj->m_Move.m_vPosition );
				}
			}


			staticData->m_cntEnemyGenerateCounter.set_FrameCounterMax( nFrameNumMax );
			staticData->m_cntEnemyGenerateCounter.reset();
		}

		staticData->move_BillBoard();
	}
	//
	///////////
	///////////////////////////////
	// カメラ移動
	ret = staticData->moveCamera();
	if( ret ) {
		_ASSERT( 0 );
		return ret;
	}
	return 0;
}



}
