#include "GPlayerManager.h"

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

using namespace GEnum;
using namespace std;

///////
// 上下50ピクセル以上離れているものについては無視
const float INSIGHT_THRESHOLD_Y = 60;
const float FAR_INSIGHT_THRESHOLD_Y = 200;

// 至近距離
const float NEAR_ENEMY_THRESHOLD = 40;
/////
// 敵がここまで近づいたら敵に近づく

// 第二の距離
const float FAR_ENEMY_THRESHOLD = 80;

// 第三距離
const float TOO_FAR_ENEMY_THRESHOLD = 120;


float getDX(float aiboCenter, float enemyCenter, float enemyLeft, float enemyRight){
	if(aiboCenter > enemyRight){
		return enemyRight - aiboCenter;
	}else if(aiboCenter < enemyLeft){
		return enemyLeft - aiboCenter;
	}else{
		return enemyCenter - aiboCenter;
	}
}
/**
	相棒AI
	@param player プレイヤー
	@param aibo 相棒
*/
void GPlayerManager::moveAI( GPlayer* lpPlayer ){

	
	GPlayer*	lpTarget	 =	NULL;					// 目標

	
	int			st			 = lpPlayer->getState()->getState();	// 状態

	/////////////
	// 初期化
	lpPlayer->resetKeyState(GEnum::KeyMap::MAX_KEY);

//	int mapIndex = getSetting()->getMapManager()->getSelectedMap();
//	bool isChasePlayer = mapIndex == 14;


	//////
	// ターゲットの選定

	bool isDone = false;
	{
		// 近接持ち
		if( lpPlayer->m_bIsHasMeleeShot ){
			////
			// 上下調べない
			// 近接のみ
			bool isCheckOnlyNearY = true;
			bool isCheckMeleeThreshold = true;
			isDone = this->searchFarEnemy(lpPlayer, isCheckOnlyNearY, isCheckMeleeThreshold);

		}

		if(isDone == false){
			/////
			// 上下調べない
			// 近接以外も見る
			bool isCheckOnlyNearY = true;
			bool isCheckMeleeThreshold = false;
			isDone = this->searchFarEnemy(lpPlayer, isCheckOnlyNearY, isCheckMeleeThreshold);
		}

		if(isDone == false){
//			if(aibo->getType() == PlayerType::Durandana){
				/////
				// 上下も調べる
				bool isCheckOnlyNearY = false;
				bool isCheckMeleeThreshold = true;
				isDone = this->searchFarEnemy(lpPlayer, isCheckOnlyNearY, isCheckMeleeThreshold);
//			}
		}
		if(isDone == false){
			////
			// 上下調べる
			// 近接以外も確認
			bool isCheckOnlyNearY = false;
			bool isCheckMeleeThreshold = true;
			isDone = this->searchFarEnemy(lpPlayer, isCheckOnlyNearY, isCheckMeleeThreshold);
		}

	}


	if(isDone == false &&
		lpPlayer->getState()->isAttackState() == false &&
		lpPlayer->getState()->isDamageState() == false &&
		lpPlayer->getState()->isDeadState() == false)
	{

		////////
		// 何も見つからなかった
		//  →プレイヤーの方向へ動く

		// プレイヤーとの距離がこれを超えたら近づく（逆にこれ以上近づかない）
		// float FAR_PLAYER_THRESHOLD = 90;

		/*
		if(player->getType() == PlayerType::Undelsen){
			/////
			// 後方支援型なのでちょっと離れる
		//	FAR_PLAYER_THRESHOLD = 150;
		}*/
		//if(pdir.getLength() >= FAR_PLAYER_THRESHOLD){
			// 他のプレイヤーがいそうな方向へ進む
			float fDirection = 0;

			int nFirstDirection = 0;
			for( int i = 0; i < PLAYER_MAX_NUM; i ++ ) {
				GPlayer* lpEnemy = &getStaticData()->m_ObjectManager.m_aryPlayerList[i];
				if( lpEnemy == lpPlayer || lpEnemy->isAlive() == false) {
					continue;
				}

				
				//////
				// 縦が一定以上離れている場合は無視
				if(fabs( lpEnemy->getCenter().getY() - lpPlayer->getCenter().getY() ) >= FAR_INSIGHT_THRESHOLD_Y){
					continue;
				}
				fDirection += getDX( lpPlayer->getCenter().getX(), lpEnemy->getCenter().getX(),
					lpEnemy->getHitArea().getX(),
					lpEnemy->getHitArea().getRight() ) > 0 ? FaceDirection::LEFT : FaceDirection::RIGHT;
				if( nFirstDirection == 0 ) {
					nFirstDirection = HPLMath::getSgn<int>( static_cast<int>( fDirection ) );
				}
				
			}
			int nFaceDirection = 0;

			if( fDirection == 0 ) {
				// ランダム
				nFaceDirection = nFirstDirection;
				if( nFaceDirection == 0 ) {

				}
			} else {
				nFaceDirection = HPLMath::getSgn<int>( static_cast<int>( fDirection ) );
			}
			moveOverObject(lpPlayer, -nFaceDirection);
		//}
	}
}

bool GPlayerManager::isSkipToSearch( GPlayer* lpPlayer, GPlayer* lpTarget ) {
	if( lpPlayer == lpTarget ) {
		return true;
	}
	if( lpPlayer->m_nForceID == lpTarget->m_nForceID ) {
		// 同じグループ
		return true;
	}
	if( lpTarget->isAlive() == false ) {
		// 死んでる
		return true;
	}

	return false;
}

/** 単体の敵に対して攻撃対象とするかどうか判断
  * @retval		true		見つけた
  * @retval		false		見つからない
  */
bool GPlayerManager::checkEnemy( GPlayer* lpPlayer, bool isCheckOnlyNearY,
	bool isCheckMeleeThreshold, GPlayer* lpEnemy )
{
	if( this->isSkipToSearch( lpPlayer, lpEnemy ) ) {
		return false;
	}
	//////
	// 画面外の敵は無視
	/*if(gameRange.isShare(enemy->getHitArea()) == false){
		continue;
	}*/

	/////
	// 友好な敵は無視する
	/*if(enemy->isHitToPlayer() == false){
		continue;
	}*/

	
	if(isCheckOnlyNearY == true){
		float dy = lpEnemy->getCenter().getY() - lpPlayer->getCenter().getY();

		//////
		// 縦が一定以上離れている場合は無視
		if(fabs(dy) >= INSIGHT_THRESHOLD_Y){
			return false;
		}
	}

	if(isCheckMeleeThreshold == true){
		float dx = getDX(lpPlayer->getCenter().getX(),
			lpEnemy->getCenter().getX(),
			lpEnemy->getHitArea().getX(),
			lpEnemy->getHitArea().getRight());
		float dy = lpEnemy->getCenter().getY() - lpPlayer->getCenter().getY();


		HPLVector dir(dx,dy);
		float distance = NEAR_ENEMY_THRESHOLD;

		if(dir.getLength() > distance){
			return false;
		}
	}

	if(this->actionAgainstEnemy(lpPlayer, lpEnemy) == true){
		return true;
	}
	return false;
}

/**
	@param isCheckFarY 上下の差が大きい部分も確認するかどうか
*/
bool GPlayerManager::searchFarEnemy(GPlayer* lpPlayer, bool isCheckOnlyNearY,
									 bool isCheckMeleeThreshold)
{
	////
	// 画面範囲
	HPLRect gameRange = getStaticData()->getGameRange();

	/////
	// 近接野郎
	for(/*std::list<TTEnemy*>::iterator eit = getSetting()->getObjectManager()->getEnemyManager()->getList()->begin();
		eit != getSetting()->getObjectManager()->getEnemyManager()->getList()->end();
		eit ++*/
		int i = 0; i < PLAYER_MAX_NUM; i ++ )
	{
		GPlayer* lpEnemy = &getStaticData()->m_ObjectManager.m_aryPlayerList[i];
		if( this->checkEnemy( lpPlayer, isCheckOnlyNearY,
			isCheckMeleeThreshold, lpEnemy ) )
		{
			return true;
		}
	}

	// 召喚対象についても動作
	for( list<GPlayer*>::iterator it = getStaticData()->m_ObjectManager.m_EnemyManager.getList()->begin();
		it != getStaticData()->m_ObjectManager.m_EnemyManager.getList()->end();
		it ++ )
	{
		GPlayer* lpEnemy = *it;
		if( this->checkEnemy( lpPlayer, isCheckOnlyNearY,
			isCheckMeleeThreshold, lpEnemy ) )
		{
			return true;
		}
	}
	return false;
}



/**
	敵に対する行動
*/
bool GPlayerManager::actionAgainstEnemy(GPlayer* lpPlayer,GPlayer* lpEnemy)
{
	float dx = getDX(lpPlayer->getCenter().getX(),
		lpEnemy->getCenter().getX(),
		lpEnemy->getHitArea().getX(),
		lpEnemy->getHitArea().getRight());
	float dy = lpEnemy->getCenter().getY() - lpPlayer->getCenter().getY();


	HPLVector dir(dx,dy);
	HPLVector aim = dir;
	aim.normalize();

	//int targetDirection = HPLMath::getSgn(-dx);

	//bool isEnemyInAiboSight = (dx * aibo->getFaceDirection()) > 0;

	bool isDone = false;

	int st = lpPlayer->getState()->getState();
	// 攻撃可能な状態
	bool bIsReadyToAttack = st == StateType::STAND ||
				st == StateType::WALK ||
				st == StateType::FLYDOWN ||
				st == StateType::FLYUP;
	if( bIsReadyToAttack == false ) {
		return false;
	}

	//int st = player->getState()->getState();
	//int aiboSt = aibo->getState()->getState();

	HPLSequence* lpSequence = lpPlayer->getSequence();


	if(lpPlayer->getType() == PlayerType::DURANDANA){
		
		/////

		if(dir.getLength() <= NEAR_ENEMY_THRESHOLD){
			/////
			// 攻撃する
			//lpPlayer->setFaceDirection((int)HPLMath::getSgn(dx));


			//bool prevA = aibo->isPressedPrevious(GEnum::KeyMap::A);

			/////
			// 連打！
			lpPlayer->setKeyState(GEnum::KeyMap::A, true);
				
			isDone = true;

		}else if(dir.getLength() <= FAR_ENEMY_THRESHOLD){
			// ちょっと離れる
			//lpPlayer->setFaceDirection((int)HPLMath::getSgn(dx));

			// 居合い
			lpPlayer->setKeyState(GEnum::KeyMap::B, true);
			isDone = true;
		} else if (dir.getLength() <= TOO_FAR_ENEMY_THRESHOLD){
			// グランドタイパー
			lpPlayer->setKeyState(GEnum::KeyMap::C, true);
			isDone = true;
		}

		

	}else if(lpPlayer->getType() == PlayerType::UNDELSEN){
		/////
		// もし横軸がそろっていたら攻撃！
		float FAR_ENEMY_THRESHOLD = 250;
		float X_AXIS_ENEMY_THRESHOLD = 20;

		if(fabs(dx) <= TOO_FAR_ENEMY_THRESHOLD){

			int nKey = KeyMap::A;
			if( fabs( dx ) <= NEAR_ENEMY_THRESHOLD ) {
				// 至近距離
				// ODORO
				nKey = KeyMap::C;
			} else if( fabs( dx ) <= FAR_ENEMY_THRESHOLD ) {
				// ちょっと離れる
				// 雷
				nKey = KeyMap::B;
			} else if( dy > X_AXIS_ENEMY_THRESHOLD ) {
				// すごい離れている＋上にいる
				//ODORO
				nKey = KeyMap::C;
			}


			//lpPlayer->setFaceDirection((int)HPLMath::getSgn(dx));
			/////
			// ・ある程度近くに居る
			// ・横軸がそろった
			// ・相棒の視線に敵が居る
			//  →攻撃！
			lpPlayer->setKeyState( nKey, true);
			isDone = true;
		}
	} else if( lpPlayer->getType() == PlayerType::EVIGEN ) {
		if( fabs(dx ) <= NEAR_ENEMY_THRESHOLD ) {
			// ミニガン
			lpPlayer->setKeyState( KeyMap::A, true);
			isDone = true;
		} else if( fabs(dx) <= FAR_ENEMY_THRESHOLD ) {
			//パイナップル
			lpPlayer->setKeyState( KeyMap::B, true);
			isDone = true;
		} else if( fabs(dx) <= TOO_FAR_ENEMY_THRESHOLD ) {
			// ろけらん
			lpPlayer->setKeyState( KeyMap::C, true);
			isDone = true;
		}
	} else if( lpPlayer->getType() == PlayerType::TANYA ) {
		if( fabs(dx ) <= NEAR_ENEMY_THRESHOLD ) {
			// ふるふる
			lpPlayer->setKeyState( KeyMap::A, true);
			isDone = true;
		} else if( fabs(dx) <= FAR_ENEMY_THRESHOLD ) {
		} else if( fabs(dx) <= TOO_FAR_ENEMY_THRESHOLD ) {
		}
	} else if( lpPlayer->getType() == PlayerType::TRELLAMA ) {
		if( fabs(dx ) <= NEAR_ENEMY_THRESHOLD ) {
			// 剣で攻撃
			lpPlayer->setKeyState( KeyMap::A, true);
			isDone = true;
		} else if( fabs(dx) <= FAR_ENEMY_THRESHOLD ) {
			// オプティカ
			lpPlayer->setKeyState( KeyMap::C, true);
			isDone = true;
		} else if( fabs(dx) <= TOO_FAR_ENEMY_THRESHOLD ) {

			// メイル
			lpPlayer->setKeyState( KeyMap::B, true);
			isDone = true;
		}
	} else if( lpPlayer->getType() == PlayerType::PESERU ) {
		if( fabs(dx ) <= NEAR_ENEMY_THRESHOLD ) {
			// 剣で攻撃
			lpPlayer->setKeyState( KeyMap::A, true);
			isDone = true;
		} else if( fabs(dx) <= FAR_ENEMY_THRESHOLD ) {
			// スライディング
			lpPlayer->setKeyState( KeyMap::B, true);
			// ランダムで脱ぐ
			if( HPLMath::nextDouble(0,100) < 0.5) {
				lpPlayer->setKeyState( KeyMap::C, true);
			}
			isDone = true;
		} else if( fabs(dx) <= TOO_FAR_ENEMY_THRESHOLD ) {
			// 近づく
			this->moveOverObject( lpPlayer, HPLMath::getSgn<int>( static_cast<int>(dx)) );
			isDone = true;

		}
	} else if( lpPlayer->getType() == PlayerType::GARDA ) {
		if( fabs(dx ) <= NEAR_ENEMY_THRESHOLD ) {
			// C 転生
			lpPlayer->setKeyState( KeyMap::C, true);
			isDone = true;
		} else if( fabs(dx) <= FAR_ENEMY_THRESHOLD ) {
			// X ↑
			lpPlayer->setKeyState( KeyMap::B, true);
			isDone = true;
		} else if( fabs(dx) <= TOO_FAR_ENEMY_THRESHOLD ) {
			// Z 横
			lpPlayer->setKeyState( KeyMap::A, true);
			isDone = true;

		}
	} else if( true) {//lpPlayer->getType() == PlayerType::TANYA_YOUJO ) {
		// さくり、ターニャ幼女、ふぉぼこ、λ、・θ・
		// その他
		if( fabs(dx ) <= NEAR_ENEMY_THRESHOLD ) {
			// Z すばやく振る
			lpPlayer->setKeyState( KeyMap::A, true);
			// テスト
//			lpPlayer->changeState( StateType::ATTACK );
			isDone = true;
		} else if( fabs(dx) <= FAR_ENEMY_THRESHOLD ) {
			// X 力を込める
			lpPlayer->setKeyState( KeyMap::B, true);
			// テスト
//			lpPlayer->changeState( StateType::ATTACK_2 );
			isDone = true;
		} else if( fabs(dx) <= TOO_FAR_ENEMY_THRESHOLD ) {
			// C 力をさらに込める？
			lpPlayer->setKeyState( KeyMap::C, true);
			// テスト
//			lpPlayer->changeState( StateType::ATTACK_GUN );
			isDone = true;

		}
	}
	if( isDone ) {
		// 対象の方向を向く
		lpPlayer->setFaceDirection((int)HPLMath::getSgn(dx));
	}
	return isDone;
}


/******
	移動する（障害物があれば飛び越える)
*/
void GPlayerManager::moveOverObject(GPlayer* lpPlayer, int direction){
	if(direction > 0){
		lpPlayer->setKeyState(GEnum::KeyMap::RIGHT, true);
		if(lpPlayer->getTrigger()->getTrigger(TriggerType::HIT_TO_THE_RIGHT) ||
			lpPlayer->getTrigger()->getTrigger( TriggerType::NO_GROUND_AT_THE_FACE_DIRECTION ))
		{
			lpPlayer->setKeyState(GEnum::KeyMap::UP, true);
		}
		
	}else if(direction < 0){
		lpPlayer->setKeyState(GEnum::KeyMap::LEFT, true);
		if(lpPlayer->getTrigger()->getTrigger(TriggerType::HIT_TO_THE_LEFT) ||
			lpPlayer->getTrigger()->getTrigger( TriggerType::NO_GROUND_AT_THE_FACE_DIRECTION )){
			lpPlayer->setKeyState(GEnum::KeyMap::UP, true);
		}
	}
}

