#include "CS_SantaFish.h"
#include "CS_PeSmoke.h"
#include "CS_Exp.h"
#include "CS_Heart.h"
#include "CS_PeLevelUp.h"

CS_SantaFish::CS_SantaFish()
{
	type = 1;
	//初始动画设置
	ani.png = L"CS_CaveStoryMod";
	//启用碰撞
	cbRect.enableCbRect = true;
	cbRect.enableSoild = true;
	//设置碰撞框
	cbRect.left = cbRect.right = 5;
	cbRect.top = 4;
	cbRect.bottom = 4;
	//初始数值
	uiName = L"fish";
	saveName = CS_SANTAFISH_CREATENAME;
	throwItem = 0;
	throwItem_max = 0;
	throwItem_type = 1;
	hp_max = 20;
	hp = 20;
	mp_max = 50;
	mp = 0;
	cbRect.fullWaterBlock = true;
	//设置ai
	aiName = L"CS_myfish_ai";
}

void CS_SantaFish::Init(std::weak_ptr<Entity> self)
{
	//添加状态控制器（也是执行顺序）
	AddState(&stateFlash);
	AddState(&stateInvincible);
	AddState(&stateGravity);
	AddState(&stateWater);
	AddState(&stateControl);
	AddState(&stateResist);//在stateControl后面
	AddState(&stateJump);
	AddState(&stateStand);
	AddState(&stateSwim);
	AddState(&stateFaceToBack);
	AddState(&stateHurt);
	//添加技能
	AddSkill(&skillBubbleBeam);
	//设置初始状态
	ChangeState(stateStand.GetStateID());
	//设置初始物理状态
	SetPhysice(true);
	//设置初始技能绑定
	SetSkillBindIndex(&skillBubbleBeam, 0);
	skillBubbleBeam.lock = false;
	stateStand.Step();
	MyCharEntity::Init(self);
}

void CS_SantaFish::Step()
{
	//防止掉地图外面
	Entity::KeepInMap();
	//跟上移动平台
	Entity::BeginMovingPlatform();
	//检测被移动平台压死
	if (CheckCrush(&crushEvent))
		CrushDeath();
	//状态机
	if (stateID == 0 && type == 1)
	{
		//玩家控制
		for (auto& p : stateList)
			p->Step();
		if (atkFeedBack > 0)
			atkFeedBack--;
		else if (action_timecounter > 0)
			action_timecounter--;
		//AI接管时是透明色
		if (enableAI)
		{
			if (gameFunc->ScriptIsRunning)
			{
				if (!gameFunc->ScriptIsRunning(gameFunc->gameScript))
					color = color & RGBA(0xff, 0xff, 0xff, 0x80);
			}
			//面朝方向和最近的玩家一致
			if (gameFunc->GetGlobalEntityTable)
			{
				float r = 100000;
				std::shared_ptr<Entity> ret;
				auto& allPlayer = *gameFunc->GetGlobalEntityTable(gameFunc->game);
				for (auto& p : allPlayer)
				{
					auto we = p.second.lock();
					if (we)
					{
						if (we->el.name == L"null")
							continue;
						if (we->enableAI)
							continue;
						if (we->hide)
							continue;
						float dx = we->x - x;
						float dy = we->y - y;
						float sq = dx * dx + dy * dy;
						if (sq < r)
						{
							r = sq;
							ret = we;
						}
					}
				}
				if (ret)
				{
					lr = ret->lr;
					ani.sprite_index = lr == 0 ? L"mc_santafish_swim_l" : L"mc_santafish_swim_r";
				}
			}
		}
	}
	else if (type == 0 || stateID != 0)
	{
		color = 0xffffffff;
		//动画
		switch (stateID)
		{
		case 0://站立
			stateStand.State();
			vx = 0;
			//重力
			stateGravity.State();
			break;
		case 1://在原地上下浮动
			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_santafish_swim_l" : L"mc_santafish_swim_r";
			break;
		case 2://趴在地上
			vx = 0;
			//重力
			stateGravity.State();
			ani.sprite_index = lr == 0 ? L"mc_santafish_lie_l" : L"mc_santafish_lie_r";
			break;
		case 3://站立
			stateStand.State();
			vx = 0;
			//重力
			stateGravity.State();
			break;
		case 4://游泳
			if (action_timecounter == 0)
				ani.sprite_index = lr == 0 ? L"mc_santafish_swim_l" : L"mc_santafish_swim_r";
			break;
		case 10://移动到触发事件的玩家附近
			if (gameFunc->GetCheckEventPlayer)
			{
				auto wplayer = gameFunc->GetCheckEventPlayer(gameFunc->game).lock();
				if (wplayer)
				{
					if (abs(x - wplayer->x) <= 2 && abs(y - wplayer->y) <= 2 || wplayer == shared_from_this())
					{
						vx = 0;
						vy = 0;
					}
					else
					{
						XMVECTOR vec = XMVector2Normalize(XMVectorSet(wplayer->x - x, wplayer->y - y, 0, 0));
						vx = animation_moveSpeed * XMVectorGetX(vec);
						vy = animation_moveSpeed * XMVectorGetY(vec);
					}
					ani.image_counter_speed = 1;
					lr = x > wplayer->x ? 0 : 1;
					ani.sprite_index = lr == 0 ? L"mc_santafish_swim_l" : L"mc_santafish_swim_r";
				}
			}
			break;
		}
	}
	//更新UI
	MyCharEntity::UpdateUI();
	//风场
	Entity::Wind();
	//跟上移动平台
	Entity::EndMovingPlatform();
	//清除最后一次碰撞结果
	Entity::ClearCollisionResult();
	//动画延迟一帧
	if (animation_delay)
		animation_delay = false;
	else
		Entity::Step();//执行运动
	//执行碰撞
	Entity::Collision();
	//维持在斜坡上
	Entity::KeepOnSlopes();
}

void CS_SantaFish::SetState(int stateID, int lr)
{
	this->stateID = stateID;
	this->lr = lr;
	switch (stateID)
	{
	case 0://没有动画（恢复玩家控制）
	case 3:
		faceToBack = false;
		vx = 0;
		ud = 0;
		break;
	case 1://在原地上下浮动
		floatSrcX = x;
		floatSrcY = y;
		vy = 0x100 / ts;
		ani.image_counter_speed = 1;
		ani.sprite_index = lr == 0 ? L"mc_santafish_swim_l" : L"mc_santafish_swim_r";
		break;
	case 2://趴在地上
		ani.sprite_index = lr == 0 ? L"mc_santafish_lie_l" : L"mc_santafish_lie_r";
		break;
	case 4://水平直线游泳
		animation_delay = true;
		if (lr == 0)
			vx = -animation_moveSpeed;
		else
			vx = animation_moveSpeed;
		vy = 0;
		if (action_timecounter == 0)
			ani.sprite_index = lr == 0 ? L"mc_santafish_swim_l" : L"mc_santafish_swim_r";
		break;
	case 5://背对着
		vx = 0;
		ud = 0;
		ani.sprite_index = lr == 0 ? L"mc_santafish_back_l" : L"mc_santafish_back_r";
		break;
	case 6://上浮
		animation_delay = true;
		vy = -animation_moveSpeed;
		ani.sprite_index = lr == 0 ? L"mc_santafish_swim_l" : L"mc_santafish_swim_r";
		break;
	case 7://向目标游去
		{
			auto wtarget = animation_target.lock();
			if (wtarget)
			{
				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;
				ani.sprite_index = lr == 0 ? L"mc_santafish_swim_l" : L"mc_santafish_swim_r";
			}
		}
		break;
	case 8://水平直线倒车
		animation_delay = true;
		if (lr == 0)
			vx = animation_moveSpeed;
		else
			vx = -animation_moveSpeed;
		vy = 0;
		if (action_timecounter == 0)
			ani.sprite_index = lr == 0 ? L"mc_santafish_swim_l" : L"mc_santafish_swim_r";
		break;
	case 9://受伤
		vx = 0;
		vy = 0;
		ani.sprite_index = lr == 0 ? L"mc_santafish_hurt_l" : L"mc_santafish_hurt_r";
		break;
	case 10://移动到触发事件的玩家附近
		break;
	}
}

void CS_SantaFish::SetState(std::wstring stateName, int lr)
{
	MyCharEntity::SetState(stateName, 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"float")
		{
			if (stateID != 1)
				SetState(1, lr);
			else
				this->lr = lr;
		}
		else if (stateName == L"lie")
			SetState(2, lr);
		else if (stateName == L"stand")
			SetState(3, lr);
		else if (stateName == L"swim")
			SetState(4, lr);
		else if (stateName == L"look_up")
			ud = -1;
		else if (stateName == L"back")
			SetState(5, lr);
		else if (stateName == L"float_up")
			SetState(6, lr);
		else if (stateName == L"set_target")
			bSetTarget = true;
		else if (stateName == L"swim_target")
			SetState(7, lr);
		else if (stateName == L"swim_back")
			SetState(8, lr);
		else if (stateName == L"hurt")
			SetState(9, lr);
		else if (stateName == L"close_to_player")
			SetState(10, lr);
	}
}

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

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

bool CS_SantaFish::Hurt(std::weak_ptr<Entity> src, int getDamage, float angle, bool bTakedown, int elemType, float shockForce, float heavy, int* outRealDamage)
{
	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_050_mimiga_squeak");
		//触发等级下降
		if ((mp >= 30 && mp - 2 * getDamage < 30) ||
			(mp >= 10 && mp - 2 * getDamage < 10))
			SetCS_PeLevelDown(shared_from_this(), x, y);
	}
	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");
		}
	}
	//掉经验
	mp -= 2 * getDamage;
	if (mp < 0)
		mp = 0;
	//伤害冲击处理
	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_SantaFish::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;
			}
		}
		//触发等级上升
		if ((mp < 10 && mp + witem->dropExp >= 10) ||
			(mp < 30 && mp + witem->dropExp >= 30))
			SetCS_PeLevelUp(shared_from_this(), x, y);
		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 (!enableAI || hp < hp_max)
	{
		//拾取到了生命
		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_SantaFish::Destroy()
{
	MyCharEntity::Destroy();
}

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

void CS_SantaFish::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_SantaFish::CopyFrom(std::shared_ptr<Entity>& another)
{
	MyCharEntity::CopyFrom(another);
}

std::shared_ptr<Entity> CreateCS_SantaFish()
{
	return std::make_shared<CS_SantaFish>();
}
