#include "CS_TorokoAni.h"
#include <PeSmog.h>

CS_TorokoAni::CS_TorokoAni()
{
	ani.png = L"CS_CaveStoryMod";
	//启用碰撞
	cbRect.enableCbRect = true;
	cbRect.enableSoild = true;
	//设置碰撞框
	cbRect.left = cbRect.right = 5;
	cbRect.top = 6;
	cbRect.bottom = 8;
}

void CS_TorokoAni::Init(std::weak_ptr<Entity> self)
{
	stateGravity.Init(shared_from_this());
	stateSplash.Init(shared_from_this());
	Entity::Init(self);
}

void CS_TorokoAni::Step()
{
	//跟上移动平台
	Entity::BeginMovingPlatform();
	if (fishState)
	{
		switch (stateID)
		{
		default:
		case 0:
			//眨眼
			if (Random(0, 120) == 10)
			{
				wink_counter = 8;
			}
			if (wink_counter > 0)
			{
				wink_counter--;
				ani.image_index = 1;
			}
			else
			{
				ani.image_index = 0;
			}
			stateGravity.Step();
			stateSplash.State();
			break;
		case 7://跳入水中
			if (lr == 0)
				vx = -animation_moveSpeed;
			else
				vx = animation_moveSpeed;
			//重力
			stateGravity.State();
			stateSplash.State();
			break;
		case 8://上下浮动 鱼状态下的
			vx = 0;
			if (floatSrcY < y)
				vy -= 8 / ts;
			if (floatSrcY > y)
				vy += 8 / ts;
			if (vy > 0x100)
				vy = 0x100;
			if (vy < -0x100)
				vy = -0x100;
			break;
		case 9://水平直线游泳
			break;
		case 10://游向目标
			{
				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_torokofish_swim_l" : L"mc_torokofish_swim_r";
				}
			}
			break;
		case 11://环绕浮动 鱼状态下的
			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;
			break;
		case 12:
			if (vy < 0)
				stateGravity.SetGravityScale(0.4f);
			else
				stateGravity.SetGravityScale(1);
			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;
		}
	}
	else
	{
		stateGravity.Step();
		switch (stateID)
		{
		case 0://站立
			//眨眼
			if (Random(0, 120) == 10)
			{
				wink_counter = 8;
			}
			if (wink_counter > 0)
			{
				wink_counter--;
				ani.image_index = 1;
			}
			else
			{
				ani.image_index = 0;
			}
			break;
		case 3://跑步
			if (lr == 0)
			{
				vx -= 0x10 / ts;
			}
			else
			{
				vx += 0x10 / ts;
			}
			if (vx > 0x400 / ts)
				vx = 0x400 / ts;
			if (vx < -0x400 / ts)
				vx = -0x400 / ts;
			break;
		case 4://坐在椅子上
			vx = 0;
			vy = 0;
			//眨眼
			if (Random(0, 120) == 10)
			{
				wink_counter = 8;
			}
			if (wink_counter > 0)
			{
				wink_counter--;
				ani.image_index = 1;
			}
			else
			{
				ani.image_index = 0;
			}
			break;
		case 5://在床上睡觉
			vx = 0;
			vy = 0;
			break;
		case 13://抛高庆祝目标
			{
				auto wanimation_target = animation_target.lock();
				if (wanimation_target)
				{
					if (wanimation_target->y < y - 8)
						ani.sprite_index = lr == 0 ? L"mc_toroko_stand_lu" : L"mc_toroko_stand_ru";
					else
						ani.sprite_index = lr == 0 ? L"mc_toroko_stand_l" : L"mc_toroko_stand_r";
				}
			}
			break;
		}
	}
	//跟上移动平台
	Entity::EndMovingPlatform();
	//清除最后一次碰撞结果
	Entity::ClearCollisionResult();
	//动画延迟一帧
	if (animation_delay)
		animation_delay = false;
	else
		Entity::Step();//执行运动
	//执行碰撞
	Entity::Collision();
	//维持在斜坡上
	Entity::KeepOnSlopes();
}

void CS_TorokoAni::SetState(int stateID, int lr)
{
	if (stateID < 200)
	{
		this->lr = lr;
		this->stateID = stateID;
		//设置动画
		switch (stateID)
		{
		case 0://站立
			vx = 0;
			if (fishState)
				ani.sprite_index = lr == 0 ? L"mc_torokofish_stand_l" : L"mc_torokofish_stand_r";
			else
				ani.sprite_index = lr == 0 ? L"mc_toroko_stand_l" : L"mc_toroko_stand_r";
			if (ud == -1)
				ani.sprite_index.append(L"u");
			break;
		case 1://走路
			{
				animation_delay = true;
				if (lr == 0)
					vx = -animation_moveSpeed;
				else
					vx = animation_moveSpeed;
				if (fishState)
				{
					const wchar_t* move = L"";
					if (ud == -1)
						move = lr == 0 ? L"mc_torokofish_swim_lu" : L"mc_torokofish_swim_ru";
					else
						move = lr == 0 ? L"mc_torokofish_swim_l" : L"mc_torokofish_swim_r";
					ani.sprite_index = move;
				}
				else
				{
					const wchar_t* move = L"";
					if (ud == -1)
						move = lr == 0 ? L"mc_toroko_move_lu" : L"mc_toroko_move_ru";
					else
						move = lr == 0 ? L"mc_toroko_move_l" : L"mc_toroko_move_r";
					ani.sprite_index = move;
				}
			}
			break;
		case 2://背对着
			vx = 0;
			ani.sprite_index = lr == 0 ? L"mc_toroko_back_l" : L"mc_toroko_back_r";
			break;
		case 3://跑步
			ani.sprite_index = lr == 0 ? L"mc_toroko_run_l" : L"mc_toroko_run_r";
			break;
		case 4://坐在椅子上
			vx = 0;
			y -= 3;
			ani.sprite_index = lr == 0 ? L"mc_toroko_sit_l" : L"mc_toroko_sit_r";
			break;
		case 5://在床上睡觉
			y -= 6;
			x -= 9;
			vx = 0;
			vy = 0;
			ani.sprite_index = lr == 0 ? L"mc_toroko_sleep_l" : L"mc_toroko_sleep_r";
			break;
		case 6://最大速度跑步
			if(lr == 0)
				vx = -0x400 / ts;
			else
				vx = 0x400 / ts;
			ani.sprite_index = lr == 0 ? L"mc_toroko_run_l" : L"mc_toroko_run_r";
			stateID = 3;
			break;
		case 7://跳入水中
			vy = -0x400 / ts;
			vx = lr == 0 ? vx = -0x200 / ts : vx = 0x200 / ts;
			gameFunc->PlaySound(L"CS_fishjump");
			break;
		case 8://上下浮动 鱼状态下的
			floatSrcX = x;
			floatSrcY = y + Random(-8, 8);
			vy = 0x100 / ts;
			ani.image_counter_speed = 1;
			ani.sprite_index = lr == 0 ? L"mc_torokofish_swim_l" : L"mc_torokofish_swim_r";
			break;
		case 9://水平直线游泳
			animation_delay = true;
			vx = lr == 0 ? -animation_moveSpeed : animation_moveSpeed;
			vy = 0;
			ani.sprite_index = lr == 0 ? L"mc_torokofish_swim_l" : L"mc_torokofish_swim_r";
			break;
		case 10://游向目标
			break;
		case 11://环绕浮动 鱼状态下的
			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;
			ani.sprite_index = lr == 0 ? L"mc_torokofish_swim_l" : L"mc_torokofish_swim_r";
			break;
		case 12:
			vy = -0xc00 / ts - Random(0, 0x200) / ts;
			vx = lr == 0 ? vx = -animation_moveSpeed : vx = animation_moveSpeed;
			vx *= 1.5f;
			bSetLanding = true;
			break;
		case 13://抛高庆祝目标
			break;
		}
	}
	else
	{
		switch (stateID)
		{
		case 200://变成鱼
			this->stateID = stateID;
			fishState = true;
			cbRect.left = cbRect.right = 5;
			cbRect.top = 4;
			cbRect.bottom = 4;
			cbRect.fullWaterBlock = true;
			ani.sprite_index = this->lr == 0 ? L"mc_torokofish_stand_l" : L"mc_torokofish_stand_r";
			SetPeSmog(shared_from_this(), x, y, 3);
			break;
		case 201://变回来
			fishState = false;
			cbRect.left = cbRect.right = 5;
			cbRect.top = 6;
			cbRect.bottom = 8;
			cbRect.fullWaterBlock = false;
			ani.sprite_index = lr == 0 ? L"mc_toroko_stand_l" : L"mc_toroko_stand_r";
			this->stateID = 0;
			SetPeSmog(shared_from_this(), x, y, 3);
			break;
		}
	}
}

void CS_TorokoAni::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"run")
			SetState(3, lr);
		else if (stateName == L"jump")
			vy = -0x300 / ts;
		else if (stateName == L"sit_on_chair")
			SetState(4, lr);
		else if (stateName == L"sleep_on_bed")
			SetState(5, lr);
		else if (stateName == L"big_jump")
		{
			if(fishState)
				SetState(12, lr);
			else
				vy = -0x700 / ts;
		}
		else if (stateName == L"run_max_speed")
			SetState(6, lr);
		else if (stateName == L"jump_to_water")
			SetState(7, lr);
		else if (stateName == L"float")
		{
			this->lr = lr;
			if (stateID != 8)
				SetState(8, lr);
			else
				ani.sprite_index = lr == 0 ? L"mc_torokofish_swim_l" : L"mc_torokofish_swim_r";
		}
		else if (stateName == L"swim")
			SetState(9, lr);
		else if (stateName == L"set_target")
			bSetTarget = true;
		else if (stateName == L"swim_target")
			SetState(10, lr);
		else if (stateName == L"float_around")
		{
			this->lr = lr;
			if (stateID != 11)
				SetState(11, lr);
			else
				ani.sprite_index = lr == 0 ? L"mc_torokofish_swim_l" : L"mc_torokofish_swim_r";
		}	
		else if (stateName == L"cheer_target")
			SetState(13, lr);
		else if (stateName == L"ignoreMovePlatform")
			cbRect.ignoreMovePlatform = lr != 0;
		else if (stateName == L"no_gravity")
		{
			vy = 0;
			stateGravity.SetEnable(lr != 0);
		}
		else if (stateName == L"transform_fish")
			SetState(200, lr);
		else if (stateName == L"transform_back")
			SetState(201, lr);
		else if (stateName == L"dx")
			x += lr;
		else if (stateName == L"ud")
			ud = lr;
	}
}

std::shared_ptr<Entity> CreateCS_TorokoAni()
{
	return std::make_shared<CS_TorokoAni>();
}
