#include "CS_Quote.h"
#include "CS_PeSmoke.h"
#include "PeSmog.h"
#include "CS_Exp.h"
#include "CS_Heart.h"

CS_Quote::CS_Quote()
{
	type = 1;
	//初始动画设置
	ani.png = L"CS_CaveStoryMod";
	//启用碰撞
	cbRect.enableCbRect = true;
	cbRect.enableSoild = true;
	cbRect.lavaDmg = 10;
	//设置碰撞框
	cbRect.left = cbRect.right = 5;
	cbRect.top = 6;
	cbRect.bottom = 8;
	//初始数值
	uiName = L"quote";
	saveName = CS_QUOTE_CREATENAME;
	throwItem = 0;
	throwItem_max = 0;
	hp_max = hp = 55;
	mp_max = mp = 200;

	lastGun = &skillSpur;
	GunAnimate();
	//设置ai
	aiName = L"CS_actioncopy_ai";
}

void CS_Quote::Init(std::weak_ptr<Entity> self)
{
	//添加状态控制器（也是执行顺序）
	AddState(&stateFlash);
	AddState(&stateInvincible);
	AddState(&stateGravity);
	AddState(&stateWater);
	AddState(&stateDrown);
	AddState(&stateControl);
	AddState(&stateResist);//在stateControl后面
	AddState(&stateJump);
	AddState(&stateStand);
	AddState(&stateMove);
	AddState(&stateAir);
	AddState(&stateFaceToBack);
	AddState(&stateHurt);
	AddState(&stateBooster);
	AddState(&stateTeleport);
	//添加技能
	AddSkill(&skillFire);
	AddSkill(&skillSpur);
	AddSkill(&skillSuperMissile);
	AddSkill(&skillLock);
	//设置初始状态
	ChangeState(stateStand.GetStateID());
	//设置初始物理状态
	SetPhysice(false);
	//设置初始技能绑定
	SetSkillBindIndex(&skillFire, 0);
	skillFire.lock = false;
	SetSkillBindIndex(&skillSpur, 1);
	skillSpur.lock = false;
	SetSkillBindIndex(&skillSuperMissile, 2);
	skillSuperMissile.lock = false;
	SetSkillBindIndex(&skillLock, 3);
	skillLock.lock = false;
	MyCharEntity::Init(self);
}

void CS_Quote::Step()
{
	//防止掉地图外面
	Entity::KeepInMap();
	//跟上移动平台
	Entity::BeginMovingPlatform();
	//图层动画
	GunAnimate();
	//检测被移动平台压死
	CheckCrush();
	//状态机
	if (stateID == 0 && type == 1)
	{
		//玩家控制
		for (auto& p : stateList)
			p->Step();
		if (atkFeedBack > 0)
			atkFeedBack--;
		else if (action_timecounter > 0)
			action_timecounter--;
	}
	else if (type == 0 || stateID != 0)
	{
		//动画
		switch (stateID)
		{
		case 0://站立
			stateStand.State();
			vx = 0;
			//重力
			stateGravity.State();
			break;
		case 1://走路
			stateMove.State();
			stateGravity.State();
			break;
		case 2://背对着
			break;
		case 3://跳入水中
			vx = lr == 0 ? -animation_moveSpeed : animation_moveSpeed;
			stateMove.State();
			//重力
			stateGravity.State();
			stateWater.State();
			break;
		case 4://上下浮动 鱼状态下的
			vx = 0;
			if (floatSrcY < y)
				vy -= 8 / ts;
			if (floatSrcY > y)
				vy += 8 / ts;
			if (vy > 0x100)
				vy = 0x100;
			if (vy < -0x100)
				vy = -0x100;
			ani.sprite_index = lr == 0 ? L"mc_quotefish_swim_l" : L"mc_quotefish_swim_r";
			break;
		case 5://水平直线游泳
			vx = lr == 0 ? -animation_moveSpeed : animation_moveSpeed;
			ani.sprite_index = lr == 0 ? L"mc_quotefish_swim_l" : L"mc_quotefish_swim_r";
			break;
		case 6://游向目标
			{
				auto wtarget = animation_target.lock();
				if (wtarget)
				{
					float dx = wtarget->x - x;
					float dy = wtarget->y - y;
					if (dx * dx + dy * dy > 12 * 12)
					{
						float vec_x = wtarget->x - x;
						float vec_y = wtarget->y - y;
						auto vec = XMVector2Normalize(XMVectorSet(vec_x, vec_y, 0, 0));
						float dir_vx = XMVectorGetX(vec);
						float dir_vy = XMVectorGetY(vec);
						vx = dir_vx * animation_moveSpeed;
						vy = dir_vy * animation_moveSpeed;
						lr = x > wtarget->x ? 0 : 1;
					}
					else
					{
						vx = vy = 0;
					}
					ani.sprite_index = lr == 0 ? L"mc_quotefish_swim_l" : L"mc_quotefish_swim_r";
				}
			}
			break;
		case 7://环绕浮动 鱼状态下的
			if (floatSrcY < y)
				vy -= 8 / ts;
			if (floatSrcY > y)
				vy += 8 / ts;
			if (vy > 0x100)
				vy = 0x100;
			if (vy < -0x100)
				vy = -0x100;

			if (floatSrcX < x)
				vx -= 8 / ts;
			if (floatSrcX > x)
				vx += 8 / ts;
			if (vx > 0x100)
				vx = 0x100;
			if (vx < -0x100)
				vx = -0x100;
			ani.sprite_index = lr == 0 ? L"mc_quotefish_swim_l" : L"mc_quotefish_swim_r";
			break;
		case 8:
			if (vy < 0)
				stateGravity.gravity = stateGravity.gravity_default * 0.4f;
			else
				stateGravity.gravity = stateGravity.gravity_default;
			if (cbRect.cbBottom && bSetLanding)
			{
				bSetLanding = false;
				vx = 0; vy = 0;
				ani.image_counter_speed = 1;
				SetPeSmog(shared_from_this(), x, y, 1, 1, 135);
				SetPeSmog(shared_from_this(), x, y, 1, 1, 45);
				SetState(201, lr);
				SetState(0, lr);
			}
			stateGravity.Step();
			break;
		case 9://抛高庆祝目标
			{
				auto wanimation_target = animation_target.lock();
				if (wanimation_target)
				{
					if (wanimation_target->y < y - 8)
						ani.sprite_index = lr == 0 ? L"mc_quote_stand_lu" : L"mc_quote_stand_ru";
					else
						ani.sprite_index = lr == 0 ? L"mc_quote_stand_l" : L"mc_quote_stand_r";
				}
			}
			break;
		}
	}
	if (fishState_counter > 0)
	{
		fishState_counter--;
		if (fishState_counter == 0)
			SetState(L"transform_back", lr);
	}
	//传送
	if (stateTeleport.cutoff != 1)
	{
		vx = 0;
		vy = 0;
		stateControl.playLandingSound = false;
	}
	//更新UI
	MyCharEntity::UpdateUI();
	//风场
	Entity::Wind();
	//跟上移动平台
	Entity::EndMovingPlatform();
	//清除最后一次碰撞结果
	Entity::ClearCollisionResult();
	//动画延迟一帧
	if (animation_delay)
	{
		animation_delay = false;
	}
	else
	{
		bool bStep = true;
		if (enableAI)
		{
			auto wAI = ai.lock();
			if (wAI)
			{
				if (wAI->noDir)//是否启用坐标控制
					bStep = false;
			}
		}
		if (bStep)
			Entity::Step();//执行运动
	}
	//执行碰撞
	Entity::Collision();
	//维持在斜坡上
	Entity::KeepOnSlopes();
	//其他图像
	auto wairTankBubble = airTankBubble.lock();
	if (wairTankBubble)
	{
		//绑定坐标
		wairTankBubble->x = x;
		wairTankBubble->y = y;
		wairTankBubble->last_x = last_x;
		wairTankBubble->last_y = last_y;
	}
	else
	{
		wairTankBubble = std::make_shared<CS_PeAirTankBubble>();
		airTankBubble = wairTankBubble;
		gameFunc->SetEntity(shared_from_this(), wairTankBubble);
	}
}

void CS_Quote::SetState(int stateID, int lr)
{
	if (stateID < 200)
	{
		this->stateID = stateID;
		this->lr = lr;
		switch (stateID)
		{
		case -1:
		case 0://没有动画（恢复玩家控制）
			faceToBack = false;
			vx = 0;
			break;
		case 1://走路
			animation_delay = true;
			vx = lr == 0 ? -animation_moveSpeed : animation_moveSpeed;
			stateMove.State();
			//重力
			stateGravity.State();
			break;
		case 2://背对着
			vx = 0;
			ani.sprite_index = lr == 0 ? L"mc_quote_back_l" : L"mc_quote_back_r";
			break;
		case 3://跳入水中
			vy = -0x400 / ts;
			vx = lr == 0 ? vx = -0x200 / ts : vx = 0x200 / ts;
			gameFunc->PlaySound(L"CS_fishjump");
			break;
		case 4://上下浮动 鱼状态下的
			floatSrcX = x;
			floatSrcY = y + Random(-8, 8);
			vy = 0x100 / ts;
			ani.image_counter_speed = 1;
			break;
		case 5://水平直线游泳
			animation_delay = true;
			vx = lr == 0 ? -animation_moveSpeed : animation_moveSpeed;
			vy = 0;
			break;
		case 6://游向目标
			break;
		case 7://环绕浮动 鱼状态下的
			floatSrcX = x + (lr == 0 ? Random(-8, 0) : Random(0, 8));
			floatSrcY = y + Random(-8, 8);
			vy = 0x80 / ts;
			vx = lr == 0 ? -0x80 / ts : 0x80 / ts;
			ani.image_counter_speed = 2;
			break;
		case 8:
			vy = -0xc00 / ts - Random(0x100, 0x200) / ts;
			vx = lr == 0 ? vx = -animation_moveSpeed : vx = animation_moveSpeed;
			vx *= 2;
			bSetLanding = true;
			break;
		case 9://抛高庆祝目标
			break;
		}
	}
	else
	{
		switch (stateID)
		{
		case 200:
			cbRect.left = cbRect.right = 5;
			cbRect.top = 4;
			cbRect.bottom = 4;
			cbRect.fullWaterBlock = true;
			fishState = true;
			fishState_counter = lr;
			SetPeSmog(shared_from_this(), x, y, 3);
			break;
		case 201:
			cbRect.left = cbRect.right = 5;
			cbRect.top = 6;
			cbRect.bottom = 8;
			cbRect.fullWaterBlock = false;
			fishState = false;
			fishState_counter = 0;
			SetPeSmog(shared_from_this(), x, y, 3);
			break;
		case 202:
			shock_counter = 120;
			stateTeleport.SetTeleportOut();
			break;
		case 203:
			shock_counter = 120;
			stateTeleport.SetTeleportIn();
			break;
		case 204:
			this->stateID = -1;
			ud = lr;
			ani.sprite_index = this->lr == 0 ? L"mc_quote_stand_l" : L"mc_quote_stand_r";
			if (ud == -1)
				ani.sprite_index.append(L"u");
			break;
		case 205:
			ani.hideLayerList.insert(2);
			ani.hideLayerList.insert(3);
			ani.hideLayerList.insert(4);
			ani.hideLayerList.insert(5);
			ani.hideLayerList.insert(6);
			ani.hideLayerList.insert(7);
			ani.hideLayerList.insert(8);
			ani.hideLayerList.insert(9);
			ani.hideLayerList.insert(10);
			lastGun = nullptr;
			break;
		}
	}
}

void CS_Quote::SetState(std::wstring stateName, int lr)
{
	if (bSetTarget)
	{
		bSetTarget = false;
		auto& allRes = *gameFunc->GetLoadedEntity(gameFunc->entityRes);
		EntityLayer* eLayer = nullptr;
		for (auto& res : allRes)
		{
			if (res.first->layerType == 0)
			{
				eLayer = &res.second;
				break;
			}
		}
		if (eLayer)
		{
			bool bFound = false;
			//在全局实体里寻找
			auto& allPlayer = *gameFunc->GetGlobalEntityTable(gameFunc->game);
			for (auto& p : allPlayer)
			{
				auto wplayer = p.second.lock();
				if (wplayer && wplayer->el.name == stateName)
				{
					animation_target = wplayer;
					bFound = true;
					break;
				}
			}
			//在地图实体层里寻找
			if (!bFound)
			{
				for (auto& e : eLayer->Ls)
				{
					if (e->el.eventName == stateName)
					{
						animation_target = e;
						break;
					}
				}
			}
		}
	}
	else
	{
		if (stateName == L"normal")
			SetState(0, lr);
		else if (stateName == L"walk")
			SetState(1, lr);
		else if (stateName == L"back")
			SetState(2, lr);
		else if (stateName == L"jump_to_water")
			SetState(3, lr);
		else if (stateName == L"float")
		{
			if (stateID != 4)
				SetState(4, lr);
			else
				this->lr = lr;
		}
		else if (stateName == L"swim")
			SetState(5, lr);
		else if (stateName == L"set_target")
			bSetTarget = true;
		else if (stateName == L"swim_target")
			SetState(6, lr);
		else if (stateName == L"float_around")
		{
			this->lr = lr;
			if (stateID != 7)
				SetState(7, lr);
			else
				this->lr = lr;
		}
		else if (stateName == L"big_jump")
			SetState(8, lr);
		else if (stateName == L"cheer_target")
			SetState(9, lr);
		else if (stateName == L"transform_fish")
			SetState(200, lr);
		else if (stateName == L"transform_back")
			SetState(201, lr);
		else if (stateName == L"teleport_out")
			SetState(202, lr);
		else if (stateName == L"teleport_in")
			SetState(203, lr);
		else if (stateName == L"switch_supermissile")
			ChangeState(skillSuperMissile.GetStateID());
		else if (stateName == L"set_levelreset_pos")
		{
			levelResetPos_x = x;
			levelResetPos_y = y;
		}
		else if (stateName == L"move_levelreset_pos")
		{
			x = levelResetPos_x;
			y = levelResetPos_y;
		}
		else if (stateName == L"dx")
			x += lr;
		else if (stateName == L"ud")
			SetState(204, lr);
		else if (stateName == L"hide_weapon")
			SetState(205, lr);
	}
}

void CS_Quote::LoadSaveData()
{
	MyCharEntity::LoadSaveData();
}

void CS_Quote::WriteSaveData()
{
	MyCharEntity::WriteSaveData();
}

bool CS_Quote::Hurt(std::weak_ptr<Entity> src, int getDamage, float angle, bool bTakedown, int elemType, float shockForce, float heavy, int* outRealDamage)
{
	//运行AI时也是无敌的
	if (enableAI)
		return false;
	//运行事件时，无敌状态
	if (gameFunc->ScriptIsRunning)
	{
		if (gameFunc->ScriptIsRunning(gameFunc->gameScript))
			return false;
	}
	//状态处理
	for (auto& p : stateList)
	{
		bool retVal = true;
		if (p->Hurt(src, &getDamage, &angle, &bTakedown, &elemType, &shockForce, &heavy, outRealDamage, &retVal))
			return retVal;
	}
	//技能处理
	for (auto& p : skillList)
	{
		bool retVal = true;
		if (p->Hurt(src, &getDamage, &angle, &bTakedown, &elemType, &shockForce, &heavy, outRealDamage, &retVal))
			return retVal;
	}
	if (getDamage == 0)
		return false;
	*outRealDamage = getDamage;
	stateInvincible.SetDamage(getDamage);
	hp -= getDamage;
	if (hp > 0)
	{
		gameFunc->PlaySound(L"CS_016_quote_hurt");
	}
	else
	{
		//创建云团
		SetCS_PeSmokeMedium(shared_from_this(), x, y);
		hp = 0;
		UpdateUI();
		//游戏结束
		hide = true;
		//设置
		if (gameFunc->StartEvent)
		{
			gameFunc->PlaySound(L"CS_017_quote_die");
			gameFunc->StopMusic();
			gameFunc->StartEvent(gameFunc->gameScript, L"Died", L"tDeath");
		}
	}
	//伤害冲击处理
	if (shockForce > 0)
	{
		//被攻击弹反
		float radian = angle * deg2rad;
		vx = shockForce * cosf(radian);
		vy = shockForce * sinf(radian);
		vy -= 1;
	}
	//设置闪光
	stateFlash.flash_counter = 5;
	//显示伤害值
	if (gameFunc->dmgNum)
		gameFunc->SetDmgNum(gameFunc->dmgNum, getDamage, x, y - 16, 1, shared_from_this());
	//转换状态
	ChangeState(stateHurt.GetStateID());
	return true;
}

void CS_Quote::Gain(std::weak_ptr<Entity> item)
{
	//拾取到了经验
	auto witem = item.lock();
	if (!witem)
		return;
	if (witem->el.name == CS_EXP_CREATENAME && witem->inUsing)
	{
		//Mp条闪烁
		if (gameFunc->GetPlayerIndex)
		{
			int playerIndex = gameFunc->GetPlayerIndex(gameFunc->game, shared_from_this());
			if (playerIndex >= 0)
			{
				auto& ui = *gameFunc->GetPlayerUIData(gameFunc->gameUI, playerIndex);
				ui.MpBar_flash_counter = 30;
			}
		}
		mp += witem->dropExp;
		if (mp > mp_max)
			mp = mp_max;
		gameFunc->PlaySound(L"CS_014_get_xp");
		//显示经验值
		if (gameFunc->dmgNum)
			gameFunc->SetDmgNum(gameFunc->dmgNum, witem->dropExp, x, y - 16, 3, shared_from_this());
		witem->Destroy();
	}
	//拾取到了生命
	else if (witem->el.name == CS_HEART_CREATENAME && witem->inUsing)
	{
		//生命恢复
		hp += witem->hp;
		if (hp > hp_max)
			hp = hp_max;
		gameFunc->PlaySound(L"CS_020_health_refill");
		witem->Destroy();
	}
}

void CS_Quote::Destroy()
{
	auto wairTankBubble = airTankBubble.lock();
	if (wairTankBubble)
		wairTankBubble->Destroy();
	MyCharEntity::Destroy();
}

void CS_Quote::GetIcon(std::wstring& png, std::wstring& sprite_index, int& image_index, std::set<int>& hideLayerList)
{
	png = L"CS_CaveStoryMod";
	sprite_index = L"mc_quote_stand_r";
	image_index = 0;
	hideLayerList = ani.hideLayerList;
}

void CS_Quote::CrushDeath()
{
	//创建云团
	SetCS_PeSmokeMedium(shared_from_this(), x, y);
	hp = 0;
	UpdateUI();
	//游戏结束
	hide = true;
	//游戏结束
	if (gameFunc->StartEvent)
	{
		gameFunc->PlaySound(L"CS_017_quote_die");
		gameFunc->StopMusic();
		if (crushEvent.length())
			gameFunc->StartEvent(gameFunc->gameScript, crushEvent.c_str(), L"tCrush");
		else
			gameFunc->StartEvent(gameFunc->gameScript, L"DeathByMovingPlatform", L"tCrush");
	}
}

void CS_Quote::GunAnimate()
{
	ani.hideLayerList.insert(2);
	ani.hideLayerList.insert(3);
	ani.hideLayerList.insert(4);
	ani.hideLayerList.insert(5);
	ani.hideLayerList.insert(6);
	ani.hideLayerList.insert(7);
	ani.hideLayerList.insert(8);
	ani.hideLayerList.insert(9);
	ani.hideLayerList.insert(10);
	//显示北极星
	if (lastGun == &skillSpur)
		ani.hideLayerList.erase(10);
	else if(lastGun == &skillSuperMissile)
		ani.hideLayerList.erase(8);
}

std::shared_ptr<Entity> CreateCS_Quote()
{
	return std::make_shared<CS_Quote>();
}
