#include "GPlayerManager.h"

#include "../game/GStaticData.h"

GPlayerManager::GPlayerManager(){
}
GPlayerManager::~GPlayerManager(){
}


/**
	移動関連の処理
	・PlayerInputへの振り分け。
	・自然発生的現象の処理
*/
void GPlayerManager::move(GPlayer* player, HPLVector* velocityAngle){
	HPLVector center = player->getCenter();
//	GPlayerState* state = player->getState();

//	加速度による移動
//		float ACCEL = 0.07f;

	if(player->getState()->getState() == StateType::DISAPPEAR){
		return;
	}

	HPLSDLInputManager* inputManager = staticData->getInputManager();
	////////////////
	// タンク状態で下キーを押すと降車
/*	if((player->getType() == PlayerType::Tank
			|| player->getType() == PlayerType::Robogen)
		&& inputManager->isPressedNow(BBEnum::KeyMap::DOWN)){

		// 降りる
		player->takeOut();
	}*/


	HPLMatrix<int>* matrix = staticData->getBlockManager()->getBlockMatrix();

	int tileSize = staticData->getSetting()->tileSize;

	// 限界領域
	HPLRect limitArea = staticData->getGameRange();
	/*(0,0,
		(float)(matrix->getColumnSize() * tileSize),
		(float)(matrix->getRowSize() * tileSize));*/
		
	////////////
	// 限界範囲は超えないようにする
	// 横方向
	if(player->getCenter().getX() < limitArea.getX()){
		player->setCenter(limitArea.getX(), player->getCenter().getY());
	}else if(player->getCenter().getX() > limitArea.getRight()){
		player->setCenter(limitArea.getRight(), player->getCenter().getY());
	}

	// 縦方向
	if(player->getCenter().getY() < limitArea.getY()){
		player->setCenter(player->getCenter().getX(), limitArea.getY());
	}
	
	// ただし下方向は死亡☆
	if(player->getCenter().getY() > limitArea.getBottom()){
		//player->setCenter(player->getCenter().getX(), limitArea.getBottom());

		player->setAlive(false);
	}
/*	GCommonProcess cp;
	if(cp.getGameRect().isShare(player->getHitArea()) == false){
		//player->setAlive(false);
		player->setHP(0);
		//player->changeState(StateType::DISAPPEAR);
	}*/
	//
	/////////////

	// 状態遷移
	int st = player->getState()->getState();

	// アニメーション状態
	HPLSequenceState seqState = player->getSequence()->getState();

	///////
	// 無敵時間
	if(player->isInvinsible()){
		player->invinsibleProcess();
	}



	if(player->isAlive() == true){

		if(player->isBind()){
			////////////
			// バインド状態
//			doBind(player);
		}else{
			if(player->isHeld() == true){
				/*********
					ホールドされている状態は、
					・左右移動
					・ジャンプ
					・しゃがみ
					・攻撃

					が出来ない。ただし、レバガチャでのダメージは敵に与えられる
				*/
			}else{
				if(staticData->getGame()->isGameOver()){
				}else{
					// 立ち→歩き の遷移（あれば）
					this->standToWalk(player, velocityAngle);

				}
				// 歩き→立ち の遷移（あれば）
				this->walkToStand(player, velocityAngle);
				if(staticData->getGame()->isGameOver()){
				}else{

					//jump(player, velocityAngle);
					//crouch(player, velocityAngle);
				}


				////////
				// 一定周期で瞬きをする
				//player->processMabataki();
			}
			//////
			// 毒状態のとき
			// ・毒マークを表示する
			// ・ある確率でダメージを受ける
/*			if(player->isPoison() || player->isErogen()){
				doPosion(player, player->isErogen());
			}*/

			//
			///////



			HPLSequence* seq = player->getSequence();
			HPLSequenceState seqState = seq->getState();

			////////
			// ダメージモーション終了
			//if(player->isDamageMotion()){
				
				if(st == StateType::DAMAGE){
					if(seqState.isFinishAnimation){
						player->changeState(StateType::STAND);
					}

				}else if(st == StateType::DAMAGE_A){
					if(seqState.isFinishAnimation){
						player->changeState(StateType::DAMAGE_A_2);
					}
				}else if(st == StateType::DAMAGE_A_2){
					if(seqState.isFinishAnimation){
						player->changeState(StateType::DAMAGE_A_3);
					}
				}else if(st == StateType::DAMAGE_A_3){
					if(seqState.isFinishAnimation){
						player->changeState(StateType::DAMAGE_A_4);
					}
				}else if(st == StateType::DAMAGE_A_4){


				}else if(st == StateType::DAMAGE_B){
					if(seqState.isFinishAnimation){
						player->changeState(StateType::STAND);
					}

				}else if(st == StateType::DAMAGE_C){
					if(seqState.isFinishAnimation){
						player->changeState(StateType::STAND);
					}
				}
				/*if(seqState.isFinishAnimation == true
					//||
//					player->isErogenDamage()
						){

					if(player->isHeld() == false){
						// 立ち(飛び)状態に戻る
						//player->changeState(StateType::STAND);
						//player->setErogenDamage(false);
					}
				}*/
			//}
		}
	}else{// if(player->isAlive() == false)

		///////////
		// 死んでる
		///////
		// 進行方向を向く
		if(player->getVelocityAngle().getX() > 0){
			player->setFaceDirection(FaceDirection::RIGHT);
		}else if(player->getVelocityAngle().getX() < 0){
			
			player->setFaceDirection(FaceDirection::LEFT);
		}

	}
	//
	//////
}

void GPlayerManager::collisionCheck(GPlayer* player, HPLVector* center, HPLVector* velocityAngle){

	HPLRect area = player->getArea();

	HPLRect hitArea = player->getHitRect();
	hitArea.setX(hitArea.getX() + area.getX());
	hitArea.setY(hitArea.getY() + area.getY());

//	BBPlayerState* state = player->getState();

	AbstractBlockManager* blockManager = staticData->getBlockManager();

	/////////////
	// common collision check and adjustment
	CollisionState states[2];


	///////
	// 衝突前の速度を記憶
	HPLVector prevVelocityAngle = HPLVector(velocityAngle->getX(), velocityAngle->getY());

	bool isOnTheGroundBefore = player->getTrigger()->getTrigger(TriggerType::ON_THE_GROUND);

	HPLCollisionTool::commonCollision((HPLShootingObject*)player,//this->getArea(), this->getHitRect(),
//		&center, &vel, width, height,
		staticData->getBlockManager()->getBlockMatrix(), 
		staticData->getSetting()->tileSize,
		staticData->getBlockManager()->getBlockMap(),
//		this->getTrigger(),
		states,
		staticData->getSetting()->gravity,
		staticData->getSetting()->resist,
		staticData->getSetting()->fallMaxSpeed);


	int st = player->getState()->getState();
	////////
	// ダメージモーション中
	bool isDamageMotion = 
		player->isDamageMotion() || 
		st == StateType::DEAD;

	//////
	// トリガによる動作
	HPLTrigger* trigger = player->getTrigger();


	///////
	//
	if(trigger->getTrigger(TriggerType::HIT_TO_THE_LEFT) ||
		trigger->getTrigger(TriggerType::HIT_TO_THE_RIGHT)){
		///////
		// 横方向にブロックにぶつかった
		//  →ダメージ中：はねる
		//  →通常時：とまる(通常止まる)

		if(isDamageMotion){
			/////
			// ダメージ中
			float a = -1 * HPLMath::getSgn(prevVelocityAngle.getX());
/*			if(trigger->getTrigger(TriggerType::HIT_TO_THE_LEFT)){
				a = 1;
			}*/
			HPLVector vel = player->getVelocityAngle();
			vel.setX(
				a * 
				staticData->getSetting()->wallBoundRefrection *
				fabs(prevVelocityAngle.getX()));

			/*if(prevVelocityAngle.getX() < staticData->getSetting()->player.airMaxSpeed / 2){
				/////
				// ゆっくり当たったら
				vel.set(0,0);
			}*/
			player->setVelocityAngle(vel);
		}else{
			HPLVector vel = player->getVelocityAngle();
			vel.setX(0);
			player->setVelocityAngle(vel);
		}

	}

	//////
	// 縦方向


	float FLYDOWN_SPEED_THRESHOLD = staticData->getSetting()->flydownSpeedThreshold;
/*	if(player->getType() == PlayerType::Robogen){
		FLYDOWN_SPEED_THRESHOLD /= 2.f;
	}*/

	if(trigger->getTrigger(TriggerType::ON_THE_GROUND)){
		//////
		// 接地した

		if(player->isAlive()){
			/////
			// 生きてる
			// 立ち状態にする
			if(st == StateType::FLYDOWN ||
				st == StateType::FLYUP){
					if(st != StateType::BORING){
						//player->changeState(StateType::STAND);
						player->changeState(StateType::SET_ON_THE_GROUND);
					}
			}

			/*if(st == StateType::DAMAGE_FLYDOWN ||
				st == StateType::DAMAGE_FLYDOWN_REVERSE){
					// ダメージ中地面についたら通常立ち
					player->changeState(StateType::STAND);

					// ではなく、倒れ状態にする。
					//player->changeState(StateType::LYING);

			}*/


			// ジャンプ回数をリセットする
			player->getJumpManager()->resetJumpNumMax();
		}else if(st != StateType::DISAPPEAR 
			&& st != StateType::BROKEN){
			/////
			// 死亡
			player->changeState(StateType::DEAD);
		}
	}else{
		////////
		// 空中に居る
		if(player->isAlive() == false && st != StateType::DISAPPEAR &&
			st != StateType::BROKEN){
			////////////
			// 死んでる…
			// 　→速度の方向で状態を変える

			// 落下速度が一定以上になったら下降モーションに移る
			if(velocityAngle->getY() >= FLYDOWN_SPEED_THRESHOLD && st != StateType::DEAD_FLYDOWN){
				player->changeState(StateType::DEAD_FLYDOWN);
			}else if(velocityAngle->getY() < FLYDOWN_SPEED_THRESHOLD &&
				st != StateType::DEAD_FLYUP){
//					if(velocityAngle->getY() < 0 && ){
				player->changeState(StateType::DEAD_FLYUP);
			}
		}else{

			if(st != StateType::DAMAGE_ELEC &&
				/////
				// 電気！
				player->isDamageMotion()){

					/////////
					// ダメージ中空中にいる場合、のけぞりとかさせる
/*				if(player->getFaceDirection() == FaceDirection::LEFT){
					if(velocityAngle->getX() > 0){
						// 逆
						if(st != StateType::DAMAGE_FLYDOWN){
							//player->changeState(StateType::DAMAGE_FLYDOWN);
							player->changeState(StateType::DAMAGE);
						}
					}else if(velocityAngle->getX() <= 0){
						// 順
						if(st != StateType::DAMAGE_FLYDOWN_REVERSE){
//							player->changeState(StateType::DAMAGE_FLYDOWN_REVERSE);
							player->changeState(StateType::DAMAGE);
						}
					}
				}else if(player->getFaceDirection() == FaceDirection::RIGHT){
					if(velocityAngle->getX() < 0){
						// 逆
						if(st != StateType::DAMAGE_FLYDOWN){
//							player->changeState(StateType::DAMAGE_FLYDOWN);
							player->changeState(StateType::DAMAGE);
						}
					}else if(velocityAngle->getX() >= 0){
						// 順
						if(st != StateType::DAMAGE_FLYDOWN_REVERSE){
//							player->changeState(StateType::DAMAGE_FLYDOWN_REVERSE);
							player->changeState(StateType::DAMAGE);
						}
					}
				}else{

				}*/
			}else{
				/////
				// 通常時
				if(st == StateType::STAND ||
					st == StateType::WALK ||
					st == StateType::CROUCH ||
					st == StateType::BORING_CROUCH ||
					st == StateType::FLYDOWN ||
					st == StateType::FLYUP ||
					st == StateType::WALK_READY ||
					st == StateType::READY_TO_JUMP ||
					st == StateType::SET_ON_THE_GROUND){


					if(velocityAngle->getY() >= FLYDOWN_SPEED_THRESHOLD){
                        if(st != StateType::FLYDOWN){
 							player->changeState(StateType::FLYDOWN);
                        }
					}else if(
						st != StateType::FLYUP){
						player->changeState(StateType::FLYUP);
					}
				}


				//////
				// もし地面にいて飛び降りたとしたら、ジャンプ回数を一回減らす
				if(player->getVelocityAngle().getY() > 0 
					&& isOnTheGroundBefore 
					&& staticData->getInputManager()->isPressedNow(GEnum::KeyMap::B) == false
					){
					player->getJumpManager()->jump();

				}
			}
		}
	}

}
