#include "GPlayer.h"

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

#include "../../../DXProject/Ryonash/src/GGameScene.h"


using namespace GEnum;

static const float NORMAL_HEIGHT = 65;
static const float PESERU_HEIGHT = 51;

/*
BuildData::BuildData(int t){
	this->type = t;
	this->mineralNum = 1;
	this->coinNum = 0;
	this->evilElementNum = 0;

//	this->enemyType = EnemyType::Missiler;

	this->loopNum = 10;

//	this->iconSequenceID = GEnum::Common::BuildMissiler + t;

	if(t == BuildType::FobokoP){
		mineralNum *= 2;
		this->evilElementNum = 2;
		this->enemyType = EnemyType::FobokoP;
		loopNum *= 2;

	}else if(t == BuildType::FobokoF){
		mineralNum *= 3;
		this->evilElementNum = 20;
		this->enemyType = EnemyType::FobokoF;
		loopNum *= 3;
	}else if(t == BuildType::BigMissiler){
		mineralNum *= 10;
		coinNum = 3;
		this->enemyType = EnemyType::BigMissiler;
		loopNum *= 10;
	} else if( t == BuildType::AllySlime ) {
		mineralNum *= 1;
		coinNum = 0;
		this->enemyType = EnemyType::AllySlime;
		loopNum *= 1;
	} else if( t == BuildType::Evigen ) {
		mineralNum *= 5;
		coinNum = 1;
		this->evilElementNum = 5;
		this->enemyType = EnemyType::ShadowEvigen;
		loopNum *= 3;
	}
}
*/

GPlayer::GPlayer():
#ifdef _DXLIB
DXPlayer
#else
HPLPlayer
#endif
( 0, GEnum::KeyMap::MAX_KEY ) {

	setObjectType(ObjectType::PLAYER);

	setFaceDirection(FaceDirection::RIGHT);

	// 一部を除いて使用しない
	this->setHPMax(100);
	this->setHP(this->getHPMax());


	this->setStoredDamage( 0 );

	this->m_bIsNaked = false;

	this->m_nStockNum = DEFAULT_STOCK_NUM;
	this->m_nFirstStockNum = DEFAULT_STOCK_NUM;

	this->m_RespawnWaitCounter.setWaitFrameNum( RESPAWN_WAIT_FRAME_NUM );

	// 終わらせておく
	this->m_RespawnWaitCounter.end();
}


GPlayer::~GPlayer(){
	
	this->setSprite(NULL);
}

void GPlayer::die(HPLShootingObject* damageSource){
	setAlive(false);

	// HP0
//	this->setHP(0);

	if( getStaticData()->getSceneManager()->getSceneType() == SceneType::GAME &&
		getStaticData()->m_CommonWork.getGameSceneType() == GameSceneType::G_GAME)
	{
		// ゲームモードである

		// ストックを失う
		this->setStockNum( this->getStockNum() - 1 );

		// リスポーンまで待つ
		this->m_RespawnWaitCounter.reset();

		// エフェクト発生
		GEffect* lpEffect = getStaticData()->m_CommonWork.createEffect(
			Sequence::Effect::ABESHI,
			this->getCenter(),
			this->getCenter(), 0, -1 );

		if( this->getStockNum() <= 0 ) {
			// スタート地点に戻す(観戦)
			this->setCenter( getStaticData()->m_CommonWork.m_ObjectPlacer.getRandomPlayerPoint() );
		}
	}
}

void GPlayer::damage(float dmg, HPLShootingObject* damageSource,
					 bool isInv, int damageState)
{

	// 蓄積ダメージ
	this->addDamage( dmg );
			
	bool bIsPreviousDamageState = this->getState()->isDamageState();
	int oldSt = this->getState()->getState();

	if( isInv ) {
		this->startInvinsible();
	}

	if(this->isSpecialState()){
		// 特殊状態ではダメージ状態にならない
	}else{	
		this->changeState(damageState);

		if( bIsPreviousDamageState == false ) {
			// 今ダメージ状態になった
			this->m_DamageRecoveryCounter.resetCounter();
		}
	}
}

#ifdef _DXLIB
void GPlayer::draw(){
#else
void GPlayer::draw(HPLSDLImageManager* imageManager){
#endif
	
	HPLScroller* scroller = getStaticData()->getScrollManager()->getScroller(0);
	float left = this->getArea().getX() + scroller->getVirtualRect().getX();
	float top = this->getArea().getY() + scroller->getVirtualRect().getY();
	float fCenterX = this->getCenter().getX() + scroller->getVirtualRect().getX();
	float fCenterY = this->getCenter().getY() + scroller->getVirtualRect().getY();
	float fZoom = scroller->m_fZoomRate;
	fCenterX *= fZoom;
	fCenterY *= fZoom;

	if(getStaticData()->m_CommonWork.m_Game.isCheat()){
		// チート中
		// →当り判定表示
#ifdef _DXLIB
#else
		getStaticData()->fillRect(
			(int)(left + this->getHitRect().getX()),
			(int)(top + this->getHitRect().getY()),
			(int)(this->getHitRect().getWidth()),
			(int)(this->getHitRect().getHeight()),
			255,0,0);
#endif
	}

	if(this->getSprite() != NULL){


#ifdef _DXLIB
		int nFaceDirection = FaceDirection::LEFT;
#else
		int nFaceDirection = this->getFaceDirection();
#endif
		HPLSequence* seq = this->getSequence();

		float rotate = 0;
		int alpha = 255;

		if(this->isInvinsible() && seq->getStepCounter() % 2 == 0){
			// 無敵中は点滅する
			alpha = 100;
		}else if(this->getState()->getState() == StateType::REITAI){
			alpha = 80;
		} 


#ifdef _DXLIB
		// 半透明表示
		//SetDrawBlendMode(DX_BLENDMODE_ALPHA, alpha);
		getStaticData()->m_Basic.m_Graphics.draw(
			fCenterX, fCenterY, seq,
			this->getFaceDirection(), rotate, fZoom );
		//SetDrawBlendMode(DX_BLENDMODE_NOBLEND, 255);
#else
		HPLSDLImageTool::blitRotozoomSpriteLeftTop(
			left, top, rotate, seq, imageManager,
			getStaticData()->getGraphics()->getScreen(), alpha);
#endif
		if(getStaticData()->m_CommonWork.m_Game.isTheWorld() == false){
			seq->step();

		}

		// 武器表示
		getStaticData()->m_CommonWork.drawPlayerWeapon( *this, left, top );
	}
}

HPLSequence* GPlayer::getSequence(){
	HPLSprite* lpSprite = this->getSprite();

	if( this->getType() == PlayerType::PESERU &&
		this->m_bIsNaked )
	{
		lpSprite = this->m_lpNakedPeseruSprite;
	}
	HPLSequence* seq = 
#ifdef _DXLIB
		lpSprite->getPair(getSequenceID())->left;
#else
		this->getFaceDirection() == FaceDirection::LEFT ?
		lpSprite->getPair(getSequenceID())->left :
		lpSprite->getPair(getSequenceID())->right;
#endif

	return seq;
}

int GPlayer::getSequenceID(){
	int id = 0;

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

	int t = this->getType();

	if( true ) {
		id = getStaticData()->m_CommonWork.getEvigenSequenceID( this );
	}

	return id;
}

void GPlayer::changeState(int st){
	int oldSt = this->getState()->getState();

	if(oldSt != st){
		int nSequenceID = this->getSequenceID();

		this->getSprite()->getPair( nSequenceID )->left->resetCounter();
#ifndef _DXLIB
		this->getSprite()->getPair( nSequenceID )->right->resetCounter();
#endif
		HPLSequencePair* lpPair = getStaticData()->m_CommonWork.getWeaponSequencePair(*this);
		if( lpPair != NULL ) {
			lpPair->left->resetCounter();
#ifndef _DXLIB
			lpPair->right->resetCounter();
#endif
		}

		if( this->getType() == PlayerType::PESERU ) {
			this->m_lpNakedPeseruSprite->getPair(nSequenceID )->left->resetCounter();
#ifndef _DXLIB
			this->m_lpNakedPeseruSprite->getPair(nSequenceID )->right->resetCounter();
#endif
		}
	}

	this->getState()->setState(st);
}
int GPlayer::rollBackState(){
	if(this->getTrigger()->getTrigger(TriggerType::ON_THE_GROUND)){
		this->changeState(StateType::STAND);
	}else{
		if(this->getVelocityAngle().getY() > getStaticData()->m_CommonWork.m_Setting.flydownSpeedThreshold){
			this->changeState(StateType::FLYDOWN);
		}else{
			this->changeState(StateType::FLYUP);
		}
	}
	return this->getState()->getState();
}

void GPlayer::jump(){
	
}
void GPlayer::checkJump(){
	
	int st = this->getState()->getState();

	if(st == StateType::STAND ||
		//st == StateType::READY_TO_JUMP ||
		st == StateType::WALK){
			// ジャンプ可能な状態

			if(this->isPressedNow(GEnum::KeyMap::B)){
				// ジャンプキー押下

				this->getTrigger()->setTrigger(TriggerType::ON_THE_GROUND, false);

				HPLVector v = this->getVelocityAngle();
				float SPD = getStaticData()->m_CommonWork.m_Setting.player.jumpSpeed;
				v.setY(-SPD);
				this->setVelocityAngle(v);

			}
	}
}

void GPlayer::changeType(int t){
	this->setSprite(this->spriteList[t]);

	this->setType(t);

	setSize(96,96);

	setHitRect(37,30,25,NORMAL_HEIGHT);

	if( t == GEnum::PlayerType::PESERU ) {
		setSize( 96, 64 );
		setHitRect( 34,10, 27, 51 );
	} else if( t == GEnum::PlayerType::NOTOKO ) {
		setSize( 128,138 );
		setHitRect( 47,63,34,64 );
	} else if( t == GEnum::PlayerType::EVIGEN ) {
		HPLRect r = getHitRect();
		r.setHeight(NORMAL_HEIGHT - 3) ;
		setHitRect(r);
	}

	// 近接攻撃を持っているかどうか
	// そのうち設定ファイルとかで自動的に判断したい
	this->m_bIsHasMeleeShot = false;
	if( t == PlayerType::PESERU ||
		t == PlayerType::TANYA ||
		t == PlayerType::DURANDANA ||
		t == PlayerType::TRELLAMA )
	{
		this->m_bIsHasMeleeShot = true;
	}
}

/**
	ダメージを受けたときに通常のDAMAGE,DAMAGE_ELEC,DEADに移行しない状態か？
*/
bool GPlayer::isSpecialState(){
	int st = this->getState()->getState();

	if(st == StateType::DIE_RESSHO ||
		st == StateType::RESSHO ||
		st == StateType::CAKE ||
		st == StateType::CAKE_2 ||
		st == StateType::CAKE_3 ||
		st == StateType::DIE_HARAKIRI ||
		st == StateType::DIE_CAKE ||
		st == StateType::HARAKIRI ||
		st == StateType::DIE_HARAKIRI ||
		st == StateType::FLYDOWN_RESSHO ||
		st == StateType::ZENRA ||
		st == StateType::BITE ||
		st == StateType::JIGO ||
		st == StateType::ZUBUNURE ||
		st == StateType::DIE_BITE ||
		st == StateType::JII ||
		st == StateType::REITAI ||
		st == StateType::STONE ||
		st == StateType::SAND 
		){
			return true;
	}

	return false;
}


/**
	敵や弾と接触しなくなる状態である
*/
bool GPlayer::isIgnoreAfterDie(){
	int st = this->getState()->getState();

	return /*st == StateType::DIE_RESSHO ||
		st == StateType::DIE_HARAKIRI ||
		st == StateType::DIE_CAKE ||*/
		st == StateType::HARAKIRI ||
		st == StateType::DIE_HARAKIRI ||
		st == StateType::DIE_BITE ||
		st == StateType::JII ||
		st == StateType::REITAI ||
		st == StateType::STONE ||
		st == StateType::SAND ||
		st == StateType::SANRAN ||
		st == StateType::AFTER_SANRAN;
}


/**
	この状態の間は物理的に吹っ飛ばない
*/
bool GPlayer::isNoImpactState(){
	return false;
}

/**
	プレイヤーが操作できなくなる状態か？
*/
bool GPlayer::isNoPlayerControllableState(){
	int st = this->getState()->getState();

	return st == StateType::FEAR ||
		st == StateType::RESSHO ||
		st == StateType::HARAKIRI ||
		this->isAlive() == false ||
		st == StateType::CAKE ||
		st == StateType::CAKE_2 ||
		st == StateType::CAKE_3 ||
		st == StateType::BITE ||
		st == StateType::JII ||
		st == StateType::SAND ||
		st == StateType::STONE ||
		st == StateType::DISAPPEAR ||
		st == StateType::EVIFLY ||
		st == StateType::SANRAN ||
		st == StateType::AFTER_SANRAN;
;

}


/**
	継続してダメージを受ける状態
*/
bool GPlayer::isSlipDamageState(){
	int st = this->getState()->getState();
	return st == StateType::RESSHO ||
		st == StateType::POISON ||
		st == StateType::FLYDOWN_RESSHO ||
		st == StateType::BITE ||
		st == StateType::JII;
}

bool GPlayer::isJumpableState(){
	int st = this->getState()->getState();
	if(st == StateType::BETOBETO_NENNEKI ||
		this->isAlive() == false ||
		st == StateType::ZENRA ||
		st == StateType::JIGO ||
		st == StateType::ZUBUNURE ||
		this->isNoPlayerControllableState() == true ||
		st == StateType::BETOBETO_KUMONOITO
		){
			return false;
	}

	return true;
}


/**
	移動キーを押しても歩行グラフィックにならないパターン
*/
bool GPlayer::isNoChangeWhenWalk(){
	int st = this->getState()->getState();
	return st == StateType::BETOBETO_NENNEKI ||
		st == StateType::BETOBETO_KUMONOITO ||
		st == StateType::REITAI;
}

