#include "NeutralManager.h"
#include "StaticData.h"
#include <cstdlib>

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

NeutralManager::NeutralManager() {
}
NeutralManager::~NeutralManager() {
}

///////////////////
// オーバーライド
BOOL NeutralManager::is_Skip( E3DObject* obj ) {
	return obj->get_Valid() == FALSE ? TRUE: FALSE;

}
int NeutralManager::checkInView( E3DObject* obj ) {
	int status;
	// チェックイン
	if( E3DChkInView( staticData->get_SwapChainID(), obj->m_nSigID, &status ) ){
		_ASSERT( 0 );
		return 1;
	}
	return 0;
}
int NeutralManager::move( E3DObject* obj ) {
	int ret= 0;

	// 現在位置取得
	D3DXVECTOR3 vPos;
	E3DGetPos( obj->m_nSigID, &vPos );
	obj->m_Move.m_vPosition = vPos;

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

	BOOL bStopMotion = FALSE;

	if( obj->m_Game.m_nType == NeutralType::SHELL) 
	{
		// 足し算
		obj->m_Move.m_vPosition += obj->m_Move.m_vVelocity;

		E3DSetPos( obj->m_nSigID, obj->m_Move.m_vPosition );

		if( obj->m_Game.m_Counter->step() & General::CounterStateType::ALL_LOOP_END ) {
			// 死亡
			// 消える
			obj->set_Valid( FALSE) ;
			E3DSetValidFlag( obj->m_nSigID, -1, FALSE );
			return 0;
		}
	
	} else if( obj->m_Game.m_nType == NeutralType::HEAD ) {
		// 足し算
		obj->m_Move.m_vPosition += obj->m_Move.m_vVelocity;

		E3DSetPos( obj->m_nSigID, obj->m_Move.m_vPosition );

		int eventno = obj->m_nEventNumber;

		if( obj->m_nEventNumber == Motion::Head::IDLE ) {
			eventno = Motion::Head::I_CAN_FLY;
		} else if( obj->m_nEventNumber == Motion::Head::I_CAN_FLY ) {
			if( motid != 0 && obj->m_nOldEventNumber == obj->m_nEventNumber)
			{
				if( frameno ==15 ) {
					// 頂点に達した

					if( obj->m_Move.get_Trigger( TriggerType::ON_THE_GROUND ) ) {
						// 地上にいる
						// そのままアニメーション
					} else {
						// 空中にいる
						// 落ちるまでアニメーション停止
						bStopMotion = TRUE;
					}
				} else if( frameno > 58 ) {
					// sleepする
					eventno = Motion::Head::SLEEP;
				}
			}
		} else if( obj->m_nEventNumber == Motion::Head::SLEEP ) {
			
		} else {
			_ASSERT(0);
		}

		obj->m_nEventNumber = eventno;

	} else if( this->is_Item( obj->m_Game.m_nType ) ) {
		// アイテムである
		// 足し算
		obj->m_Move.m_vPosition += obj->m_Move.m_vVelocity;

		E3DSetPos( obj->m_nSigID, obj->m_Move.m_vPosition );

	} else if( obj->m_Game.m_nType == NeutralType::DANIMOTH ||
		obj->m_Game.m_nType == NeutralType::CONSOLE)
	{
		// 動かない
	}
	{
		// チェックイン
		int status;
		//E3DLookAtQ( obj->m_Move.m_nQuoatanion, obj->m_Move.m_vVelocity, D3DXVECTOR3(0,0,1), 0, 1 );
		if( E3DChkInView( staticData->get_SwapChainID(), obj->m_nSigID, &status ) ){
			_ASSERT( 0 );
			return 1;
		}
	}

	if( obj->m_Game.m_nType == NeutralType::DANIMOTH ||
		obj->m_Game.m_nType == NeutralType::HEAD)
	{
		if( bStopMotion ) {
		} else {
			int eventno = obj->m_nEventNumber;

			if( staticData->get_CurrentKeyBuffer('1' ) ) {
				eventno = 1;
			} else if( staticData->get_CurrentKeyBuffer('2' ) ) {
				eventno = 2;
			}
			
			obj->m_nEventNumber = eventno;

			ret = E3DSetNewPoseByMOA( obj->m_nSigID, eventno );
			if( ret ){
				_ASSERT( 0 );
				return 1;
			}
		}
	}

	obj->m_nOldEventNumber = obj->m_nEventNumber;

	return 0;
}
int NeutralManager::checkHitToGround( E3DObject* obj ) {
	int ret = 0;

	int nMode = 1;	

	// 結果
	int nResult = 0;

	D3DXVECTOR3 vAdjust;
	D3DXVECTOR3 n;
	ret = E3DChkConfGround( obj->m_nSigID, staticData->get_GroundSigID(), nMode, 
		MAP_HEIGHT, MAP_MIN, &nResult, &vAdjust, &n );
	if(ret ) {
		_ASSERT(0);
		return 1;
	}

	D3DXVECTOR3 vPosition;
	E3DGetPos( obj->m_nSigID, &vPosition );

	if( vPosition.y > vAdjust.y )	{
		// 空中

		obj->m_Move.set_Trigger( TriggerType::ON_THE_GROUND , FALSE);

		if( obj->m_Game.m_nType == NeutralType::DANIMOTH ||
			obj->m_Game.m_nType == NeutralType::CONSOLE)
		{
			// 何もしない
		} else {
			// 重力
			//ret = staticData->checkObjectOnGround( obj, FALSE);
			obj->m_Move.m_vVelocity.y += GRAVITY;
			obj->m_Move.m_vPosition += obj->m_Move.m_vVelocity;
			E3DSetPos( obj->m_nSigID, obj->m_Move.m_vPosition );
			//obj->m_Move.set_Trigger( TriggerType::ON_THE_GROUND ,
			//	FALSE);
		}
	} else {
		if( nResult ) {
			obj->m_Move.set_Trigger( TriggerType::ON_THE_GROUND , TRUE);

			// 触れた

			if( this->is_Item( obj->m_Game.m_nType ) ||
				obj->m_Game.m_nType == NeutralType::HEAD )
			{
				// 地上に設置
				ret = E3DSetPosOnGround( obj->m_nSigID, staticData->get_GroundSigID(),
					MAP_HEIGHT, MAP_MIN, obj->m_Move.m_vPosition.x, obj->m_Move.m_vPosition.z );
				ret = E3DGetPos( obj->m_nSigID, &obj->m_Move.m_vPosition );

				obj->m_Move.m_vVelocity = D3DXVECTOR3(0,0,0 );

			}

		}
	}

	return 0;
}
int NeutralManager::render( E3DObject* obj ) {

	// sig id取得
	int hsid = obj->m_nSigID;

	// 通常描画
	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;
	}
	int ret = E3DSetBeforePos( obj->m_nSigID) ;
	return 0;
}

int NeutralManager::createObjects( int nType, int nNum ) {
	int ret = 0;

	char lpszSigFilePath[MAX_PATH];

	if( nType == NeutralType::SHELL ) {
		strcpy_s( lpszSigFilePath, MAX_PATH, "Media\\model_madogen\\shell.sig");

	} else if( nType == NeutralType::DANIMOTH ) {
		strcpy_s( lpszSigFilePath, MAX_PATH, 
			"Media\\dany_20000.sig");

	} else if( nType == NeutralType::MINI_GUN ) {
		strcpy_s( lpszSigFilePath, MAX_PATH, "Media\\model_madogen\\minigun.sig");

	} else if( nType == NeutralType::HAND_GUN ) {
		strcpy_s( lpszSigFilePath, MAX_PATH, "Media\\HandGun.sig");

	} else if( nType == NeutralType::MEDI_KIT ) {
		strcpy_s( lpszSigFilePath, MAX_PATH, "Media\\Item\\MediKit.sig");

	} else if( nType == NeutralType::AMMO ) {
		strcpy_s( lpszSigFilePath, MAX_PATH, "Media\\Item\\Ammo.sig");

	} else if( nType == NeutralType::MEAT ) {
		strcpy_s( lpszSigFilePath, MAX_PATH, "Media\\Item\\Meat.sig");

	} else if( nType == NeutralType::CONSOLE ) {
		strcpy_s( lpszSigFilePath, MAX_PATH, "Media\\Console.sig");

	} else if( nType == NeutralType::HEAD ) {
		strcpy_s( lpszSigFilePath, MAX_PATH, "Media\\you fired\\evi_neck.sig");

	} else {
		_ASSERT( 0 );
		return 1;
	}

	// 有効一覧に追加
	this->m_mapValidObjectListMap[nType] = std::list<E3DObject*>();


	// コピー元となるマスタSIGID
	int nMasterSigID = 0;

	float fMultipleRate = 1.f;

	if( nType == NeutralType::DANIMOTH ) {
		fMultipleRate *= 100.f;
	}
	/////////////////
	// Sigファイル読み込み
	ret = E3DSigLoad( lpszSigFilePath, 0, fMultipleRate, &nMasterSigID );
	if( ret ) {
		_ASSERT( 0 );
		return ret;
	}

	// 追加処理
	ret = this->add_Object( nType, nMasterSigID );

	// クローンマネージャに登録
	ret = this->m_CloneManager.add_MasterBuffer( nType, nMasterSigID);

	// 予約一個消化
	nNum --;

	if( nNum >= 1 ) {
		// まだ作成すべきものがある
		// バッファにコピーしてSigを複製

		// テクスチャパス
		char lpszTextureDirPath[MAX_PATH];
		if( nType == NeutralType::SHELL ) {
			strcpy_s( lpszTextureDirPath, MAX_PATH, "Media\\model_madogen\\");
		} else if( nType == NeutralType::DANIMOTH ) {
			strcpy_s( lpszTextureDirPath, MAX_PATH, "Media\\");
		} else if( nType == NeutralType::MINI_GUN ) {
			strcpy_s( lpszTextureDirPath, MAX_PATH, "Media\\model_madogen\\");
		} else if( nType == NeutralType::HAND_GUN ) {
			strcpy_s( lpszTextureDirPath, MAX_PATH, "Media\\");
		} else if( nType == NeutralType::MEDI_KIT ) {
			strcpy_s( lpszTextureDirPath, MAX_PATH, "Media\\Item\\");
		} else if( nType == NeutralType::AMMO ) {
			strcpy_s( lpszTextureDirPath, MAX_PATH, "Media\\Item\\");
		} else if( nType == NeutralType::MEAT ) {
			strcpy_s( lpszTextureDirPath, MAX_PATH, "Media\\Item\\");
		} else if( nType == NeutralType::CONSOLE ) {
			strcpy_s( lpszTextureDirPath, MAX_PATH, "Media\\");
		} else if( nType == NeutralType::HEAD ) {
			strcpy_s( lpszTextureDirPath, MAX_PATH, "Media\\you fired\\");
		} else {
			_ASSERT( 0 );
			return 1;
		}

		for(int i = 0; i < nNum; i ++ ) {
			E3DSigBufferData* bfSigBufferData = this->m_CloneManager.get_MasterBuffer(nType);
			// コピー
			int nSigID = 0;
			ret = E3DSigLoadFromBuf( lpszTextureDirPath,
				bfSigBufferData->m_lpczBuffer,
				bfSigBufferData->m_nBufferSize,
				0, fMultipleRate, &nSigID );
				
			// 登録作業
			ret = this->add_Object( nType, nSigID );
		}

	}
	return 0;
}

int NeutralManager::add_Object(int nType, int nSigID ) {
	int ret = 0;

	// オブジェクト生成
	E3DObject* obj = new E3DObject();

	// sig id 登録
	obj->m_nSigID = nSigID;

	// 逆引きに登録
	this->m_mapSigIDToObjectMap[ nSigID ] = obj;

	// リストに追加
	this->m_mapObjectListMap[nType].push_back( obj );

	// クォータニオン
	ret = E3DCreateQ( &obj->m_Move.m_nQuoatanion );

	//! オブジェクトタイプ
	obj->m_Game.m_nObjectType = ObjectType::NEUTRAL;

	//! タイプ
	obj->m_Game.m_nType = nType;

	//////////////////
	// モーション読み込み
	if( nType == NeutralType::DANIMOTH ||
		nType == NeutralType::HEAD)
	{

		char lpszMOAFilePath[MAX_PATH];
		if( nType == NeutralType::DANIMOTH ) {
			strcpy_s( lpszMOAFilePath, MAX_PATH, "Media\\dany_motion\\dany.moa");
		} else if( nType == NeutralType::HEAD ) {
			strcpy_s( lpszMOAFilePath, MAX_PATH, "Media\\you fired\\evi_neck\\evi_neck.moa");
		} else {
			_ASSERT( 0 );
			return 1;

		}

		// MOAファイル読み込み
		ret = staticData->loadMOAFile( lpszMOAFilePath, obj );
	}

	/////
	// 状態
	int nCounterMax = SHELL_LIFE_COUNT;
	if( this->is_Item( nType) )
	{
		nCounterMax = ITEM_REMAIN_COUNTER_MAX;
	}
	obj->m_Game.m_Counter = new HPLCounter( nCounterMax, 1);

	float fSpeed = SHOT_SPEED;
	obj->m_Move.m_fSpeed = fSpeed;

	return 0;
}

/** MOAファイル読み込み
  *
  */
int NeutralManager::loadMOAFile( const char* lpszFilePath, E3DObject* obj ) {

	// 読み込まない
	return 1;

}
/** 待機しているオブジェクトを呼び出します。
  * @retval NULL	既に全て埋まっていて存在しない場合
  */
E3DObject* NeutralManager::search( int nType ) {
	for(std::list<E3DObject*>::iterator it = this->m_mapObjectListMap[nType].begin();
		it != this->m_mapObjectListMap[nType].end(); it ++ )
	{
		E3DObject* obj = *it;
		if( obj->get_Valid() == FALSE ) {

			obj->set_Valid( TRUE );

			// モデル有効化
			E3DSetValidFlag( obj->m_nSigID, -1, TRUE );

			// Validリストに追加
			this->m_mapValidObjectListMap[nType].push_back(obj);

			obj->m_Game.m_Counter->reset();

			if( this->is_Item( obj->m_Game.m_nType ) ) {
				// アイテムである

				// ランダム方向
				D3DXVECTOR3 vDirection( MathTool::nextRandom<float>(-1,1), 0, MathTool::nextRandom<float>( -1, 1 ) );
				D3DXVec3Normalize( &vDirection, &vDirection);

				// 方向をランダムにする
				staticData->face( vDirection, 1, obj->m_nSigID, obj->m_Move.m_nQuoatanion );

			}
			return obj;
		}
	}
	return NULL;
}

int NeutralManager::checkHitToPlayer( E3DObject* obj ) {

	int ret = 0;
	int confptr = 0;		

	int inviewptr;

	ret = E3DChkConflictOBB( staticData->get_Player()->m_nSigID, -1,
		obj->m_nSigID, -1, &confptr , &inviewptr);
	if( ret ) {
		_ASSERT( 0 );
		return 1;
	}
	if( confptr ) {


		// 接触した

		if( obj->m_Game.m_nType == NeutralType::CONSOLE ) {
			staticData->m_bNearByConsole = TRUE;

			if( staticData->get_CurrentKeyBuffer( 'F') && staticData->get_PreviousKeyBuffer('F' ) == FALSE) {
				// Fキーを押した
				// コンソールの情報取得
				//staticData->m_Console = obj;
				// シナリオスタート
				if( obj->m_Game.m_nScenarioIndex >= 0 ) {
					if( staticData->m_ScenarioItem == NULL ) {
						// リセット
						staticData->m_ScenarioManager.reset();
					}

					staticData->m_nScenarioListID = obj->m_Game.m_nScenarioIndex;
					staticData->m_ScenarioItem = staticData->m_ScenarioManager.get(obj->m_Game.m_nScenarioIndex )->next();
				} else {
					_ASSERT( 0 );
				}
			}
		} else if( this->is_Item(obj->m_Game.m_nType) ) {
			// 死亡
			obj->set_Valid( FALSE );
			E3DSetValidFlag( obj->m_nSigID, -1, FALSE );


			if( obj->m_Game.m_nType == NeutralType::AMMO ) {

				// 弾を取った


				// 弾薬増加(全部)
				for(int i = 0; i < WeaponType::MAX_NUM; i ++ ) {
					Weapon* weapon = &staticData->m_aryWeaponList[i];
					if( weapon->is_Enable() ) {
						weapon->set_ChargedAmmo( weapon->get_ChargedAmmo() + weapon->get_ItemAmmo() );
					}
				}
				
			} else if( obj->m_Game.m_nType == NeutralType::MEDI_KIT ) {
				staticData->get_Player()->m_Game.set_HP( staticData->get_Player()->m_Game.m_fHP + staticData->get_Player()->m_Game.m_fHPMax * MEDI_KIT_HEAL_RATE );
			} else if( obj->m_Game.m_nType == NeutralType::MEAT ) {
				staticData->get_Player()->m_Game.set_HP( staticData->get_Player()->m_Game.m_fHP + staticData->get_Player()->m_Game.m_fHPMax * MEAT_HEAL_RATE );
			} else if( obj->m_Game.m_nType == NeutralType::MINI_GUN ) {
				staticData->m_aryWeaponList[WeaponType::MINI_GUN].set_Enable( TRUE );
			} else if( obj->m_Game.m_nType == NeutralType::HAND_GUN ) {
				staticData->m_aryWeaponList[WeaponType::HAND_GUN].set_Enable( TRUE );
			}
		}
	}
	return 0;
}
BOOL NeutralManager::is_Item(int nType) {
	return nType == NeutralType::AMMO ||
		nType == NeutralType::MEDI_KIT ||
		nType == NeutralType::MEAT || 
		nType == NeutralType::MINI_GUN ||
		nType == NeutralType::HAND_GUN;
}

}
