#include "GShotManager.h"

#ifdef _DXLIB
#include "GStaticDataDX.h"
#else
#include "GStaticData.h"
#endif

using namespace std;
using namespace GEnum;

GShotManager::GShotManager() {
	m_bIsHitToPlayer = true;

	// タイプとシーケンスのIDマッピング読み込み
	{
		vector<string> vecLines = HPLFile::loadStringLinesFromFile( SHOT_SEQUENCE_ID_MAPPING_FILE_PATH );

		for( vector<string>::const_iterator it = vecLines.begin();
			it != vecLines.end(); it ++ )
		{
			string str = *it;

			if( HPLFile::isCommentLine( &(str) ) ) {
				continue;
			}

			vector<string> vecEquals = HPLString::split( str, "=" );
			HPLError::assertIt ( 
				static_cast<int>( vecEquals.size() ) >= 2 ,
				"%s", str.c_str() );
			this->m_mapTypeAndSequenceIDMapping[ 
				atoi( vecEquals[0].c_str() )] = atoi( vecEquals[1].c_str() );
		}
	}

	// 威力読み込み
	{
		vector<string> vecLines = HPLFile::loadStringLinesFromFile("data/image/Shot/ShotPower.txt");
		int index = 0;

		for( vector<string>::const_iterator it = vecLines.begin();
			it != vecLines.end(); it ++ )
		{
			string str = *it;
			if(HPLFile::isCommentLine(&str)){
				continue;
			}
			shotPowerList.push_back((float)atof(str.c_str()));
			index ++;
		}
		if( index < ShotType::MAX_NUM ) {
			for( int i = index; i < ShotType::MAX_NUM; i ++ ) {
				// 良く分かりやすいようにする
				shotPowerList.push_back( 9999 );
			}
		}
	}

	// ショット設定の読み込み
	{
	}
}

GShotManager::~GShotManager() {
	this->m_mapTypeAndSequenceIDMapping.clear();

	this->clear();
}

/** 種類からシーケンスIDを取得します。
  */
int GShotManager::getSequenceID( int nType ) {
	HPLError::assertIt( this->m_mapTypeAndSequenceIDMapping.find( nType ) != this->m_mapTypeAndSequenceIDMapping.end(),
		"Out of bounds %d", nType );

	return this->m_mapTypeAndSequenceIDMapping[ nType ];

}


/** 動かします
  */
void GShotManager::process( bool bIsMove, bool bIsAI ) {

	// 移動可能範囲。これを超えると通常消えます
	HPLRect merginedGameRange = getStaticData()->getMerginedGameRange();

	// 追加要素クリア
	m_Adds.clear();

	// マップ情報
	int mapIndex = getStaticData()->getMapManager()->getSelectedMap();

	// マップブロックマトリクス
	HPLMatrix<int>* mat = getStaticData()->getBlockManager()->getBlockMatrix();

	// タイルサイズ
	int tileSize = getStaticData()->getSetting()->tileSize;

	// タイルの大きさ
	HPLRect tileRange(0,0,
		static_cast<float>( mat->getColumnSize() * tileSize ),
		static_cast<float>( mat->getRowSize() * tileSize) );

	for( list<GShot*>::iterator it = this->getList()->begin();
		it != this->getList()->end();)
	{
		GShot* lpShot = *it;

		if(merginedGameRange.isShare( lpShot->getHitArea() ) == false) {
			// 領域外へ出た

			// 死ぬ
			lpShot->setAlive(false);

		}

		if( bIsMove && lpShot->isAlive() ){
			// 移動状態
			// 生きてる

			/*bool isCollisionToBlock = lpShot->collision(
				getStaticData()->getBlockManager()->getBlockMatrix(),
				getStaticData()->getBlockManager()->getBlockMap()
				);*/
			staticData.collisionObject( lpShot );

			// 当り判定
//			if( lpShot->isHitToBlock() ){
//				bool hitBlock = isCollisionToBlock;
//			}

			if( bIsAI ) {
				this->algorithm( lpShot );
			}

			if( this->m_bIsHitToPlayer ) {
				// 対象との当り判定
				this->checkHitToTarget( lpShot );
			}

		}

		if( lpShot->isAlive() ) {

#ifdef _DXLIB
			lpShot->draw();
#else
			lpShot->draw( getStaticData()->getImageManager() );
#endif


			it ++;

			/*if( lpShot->isMelee() ) {
				lpShot->setAlive( false );
			}*/

		} else {
			it = this->getList()->erase( it );
			delete lpShot;
		}
	}
	for(std::list<GShot*>::iterator it = m_Adds.begin(); it != m_Adds.end(); it ++){
		this->getList()->push_back(*it);
	}
	m_Adds.clear();

}

/** 作成します。実体は本関数内でリストに追加されます。
  */ 
GShot* GShotManager::create( int nType, HPLVector& vCenter, int nParentID,
							int nFaceDirection)
{
	GShot* lpShot = new GShot( nType );
	lpShot->setCenter( vCenter );
	lpShot->setParentID( nParentID );

	lpShot->setPower( this->getShotPower( nType ) );
	lpShot->setFaceDirection( nFaceDirection );

	
	if( nType == ShotType::BULLET ||
		nType == ShotType::FRAME_THROWER_FIRE)
	{
		lpShot->setVelocityAngle( 
			( nFaceDirection > 0 ? 1 : -1 ) * EVIGEN_MINIGUN_BULLET_SPEED,
			static_cast<float>( HPLMath::nextDouble( - EVIGEN_MINIGUN_BULLET_ERROR_Y, EVIGEN_MINIGUN_BULLET_ERROR_Y ) ) );
	} else if( nType == ShotType::FIRE_BALL ) {
		lpShot->setVelocityAngle( 
			( nFaceDirection > 0 ? 1 : -1 ) * TRELLAMA_FIRE_BALL_SPEED,
			static_cast<float>( HPLMath::nextDouble( - TRELLAMA_FIRE_BALL_ERROR_Y, TRELLAMA_FIRE_BALL_ERROR_Y ) ) );
	} else if( nType == ShotType::PINE_APPLE_0 ) {
		lpShot->setVelocityAngle( 
			( nFaceDirection > 0 ? 1 : -1 ) * 
			EVIGEN_PINEAPPLE_THROW_SPEED_X ,
			- EVIGEN_PINEAPPLE_THROW_SPEED_Y);
	}
	this->getList()->push_back( lpShot );

	return lpShot;
}



/** 移動します。
  */
void GShotManager::algorithm( GShot* lpShot ) {
	int t = lpShot->getType();

	int st = lpShot->getState()->getState();

	HPLSequenceState seqState = lpShot->getSequence()->getState();

	/// ゲーム表示領域
	HPLRect gameRange = getStaticData()->getGameRange();

	if( seqState.isFinishAnimation ) {
		// 消える
		lpShot->setAlive( false );

		if( t == ShotType::PINE_APPLE_0 ) {
			// 1生成
			GShot* lpOther = new GShot( ShotType::PINE_APPLE_1 );
			lpOther->setCenter( lpShot->getCenter() );
			lpOther->setParentID( lpShot->getParentID() );
			lpOther->setVelocityAngle( lpShot->getVelocityAngle() );

			this->m_Adds.push_back( lpOther );

		} else if( t == ShotType::PINE_APPLE_1 ) {
			// 爆発

			this->createExplosion( lpShot );
		}
	}

	////
	// 移動
	HPLVector center = lpShot->getCenter();
	HPLVector velocityAngle = lpShot->getVelocityAngle();
	if( t == ShotType::FIRE_BALL ) {
		// 進行方向へ加速
		velocityAngle.add( ( lpShot->getFaceDirection() > 0 ? 1: -1 ) * FIRE_BALL_ACCEL_X, 0 );
		center.add( velocityAngle );
	} else if( t == ShotType::ODORO ) {
		// 上方向へ加速
		velocityAngle.add( 0, - ODORO_ACCEL_Y );
		center.add( velocityAngle );
	}

	lpShot->setCenter(center) ;
	lpShot->setVelocityAngle( velocityAngle );
}

bool GShotManager::checkHitToOneTarget( GShot* lpShot, GPlayer* lpPlayer ) {

	if( lpPlayer->getID() == lpShot->getParentID() ) {
		// 自分が発射したもの
		if( lpShot->getType() == ShotType::EXPLOSION ) {
			// 爆発にはあたる
		} else {

			// それ以外

			// 当らない
			return false;
		}
	}

	if( lpShot->getType() == ShotType::SLASH ) {
		// 打撃
		// 持続するので、最初だけあたり判定?

	}

	if( lpShot->getObjectAttribute( ObjectAttribute::HIT_TO_PLAYER) == false /*lpShot->getType() == ShotType::PINE_APPLE_0 ||
		lpShot->getType() == ShotType::PINE_APPLE_1*/ )
	{
		// プレイヤーにヒットしない
		return false;
	}

	if( lpPlayer->m_RespawnWaitCounter.getState().isFinishAnimation == false) {
		// リスポーン待ち
		// ヒットしない
		return false;
	}


	if( getStaticData()->m_CommonWork.isHit( lpShot, lpPlayer ) ) {
		// ヒットした

		// エフェクト追加
		GEffect* lpEffect = getStaticData()->m_CommonWork.createEffect(
			Sequence::Effect::HIT,
			lpShot->getCenter(),
			lpPlayer->getCenter(), 0, -1);

		// 吹っ飛ぶ
		float fSpeed = SHOT_BLOW_SPEED;
		if( lpShot->getType() == ShotType::SLASH ||
			lpShot->getType() == ShotType::SWORD_SLASH ||
			lpShot->getType() == ShotType::ONLY_SLASH
			)
		{
			fSpeed = SLASH_BLOW_SPEED;
		} else if( lpShot->getType() == ShotType::MISSILE ) {
			fSpeed = MISSILE_BLOW_SPEED;
		}
			

		getStaticData()->m_CommonWork.hitToPlayer( lpShot, lpPlayer, fSpeed, lpShot->getPower() );

		return true;
	}

	return false;
}

/** 対象へのあたり判定を行います。
  */
void GShotManager::checkHitToTarget( GShot* lpShot ) {

	bool bIsHit = false;

	// プレイヤーとのあたり判定
	for( int i = 0; i < GEnum::PLAYER_MAX_NUM; i ++ ) {
		if( this->checkHitToOneTarget( lpShot, &getStaticData()->m_ObjectManager.m_aryPlayerList[i] ) ) {
			bIsHit = true;
		}
	}
	for( list<GPlayer*>::iterator it = getStaticData()->m_ObjectManager.m_EnemyManager.getList()->begin();
		it != getStaticData()->m_ObjectManager.m_EnemyManager.getList()->end();
		it ++ )
	{
		if( this->checkHitToOneTarget( lpShot, *it ) ) {
			bIsHit = true;
		}
	}
	if( bIsHit ) {
		// プレイヤーにヒットした

		if( lpShot->getType() == ShotType::PINE_APPLE_0 ||
			lpShot->getType() == ShotType::MISSILE
			)
		{
			// 一部の弾は当たると爆発

			// パイナップルが直撃
			// 爆発
			this->createExplosion( lpShot );
		}

		if( lpShot->getType() == ShotType::SLASH ||
			lpShot->getType() == ShotType::BEAM ||
			lpShot->getType() == ShotType::ONLY_SLASH ||
			lpShot->getType() == ShotType::THUNDER_BOLT ||
			lpShot->getType() == ShotType::ODORO ||
			lpShot->getType() == ShotType::EXPLOSION ||
			lpShot->getType() == ShotType::RYUHA_1 ||
			lpShot->getType() == ShotType::RYUHA_2

			)
		{
			// 一部の弾は消えない(貫通)
			// do nothing
		} else {
			lpShot->setAlive( false );
		}
	}
}

/**
	ホーミング能力がある場合ホーミング処理を行う
*/
void GShotManager::homing( GShot* lpShot ) {
	HPLError::error( "hoge");
}

/**
	@param shot 跳ね返される弾
	@param isKillShot 弾をかき消すかどうか
	@param reflectPowerRate 反射後の攻撃力変化割合
	@param parentID 反射する本体のID
*/
void GShotManager::reflect( GShot* lpShot, bool bIsKillShot,
	float fReflectPowerRate,
	int nParentID)
{
	HPLError::error( "hoge");
}

/** 爆発の定型
  */
GShot* GShotManager::createExplosion( GShot* lpShot ) {
	GShot* lpOther = new GShot( ShotType::EXPLOSION );
	lpOther->setCenter( lpShot->getCenter() );
	lpOther->setParentID( lpShot->getParentID() );
	lpOther->setVelocityAngle( 0,0 );
	lpOther->setPower( this->getShotPower(ShotType::EXPLOSION ));

	this->m_Adds.push_back( lpOther );
	return lpOther;
}

/** ダメージ量取得
  */
float GShotManager::getShotPower(int t) {
	return this->shotPowerList[t];
}

