#include "CS_SantaAi.h"
#include "CS_Santa.h"
#include "CS_Boss_ControlCore.h"
#include "CS_Boss_Puu.h"
CS_SantaAi::CS_SantaAi()
{
	el.name = CS_SANTAAI_CREATENAME;
}

void CS_SantaAi::Init(std::weak_ptr<Entity> self)
{
	auto watkZone = std::make_shared<CS_Ai_AtkZone>();
	atkZone = watkZone;
	//设置接触矩形框范围
	watkZone->cbRect.left = 5 * 16;
	watkZone->cbRect.right = 5 * 16;
	watkZone->cbRect.top = 10 * 16;
	watkZone->cbRect.bottom = 5 * 16;
	gameFunc->SetEntity(shared_from_this(), watkZone);
	CS_MyCharAi::Init(self);
}

void CS_SantaAi::Step()
{
	auto wattackParent = attackParent.lock();
	if (!wattackParent)
	{
		Destroy();
		return;
	}
	if (atk_interval_counter > 0)
		atk_interval_counter--;

	auto mychar = std::static_pointer_cast<CS_Santa>(wattackParent);
	if (!mychar)
	{
		InitControlTarget();
		return;
	}
	if (gameFunc->InBossFight)
	{
		if (stateID == 0)
		{
			if (gameFunc->InBossFight(gameFunc->game))
			{
				//隐藏图标
				if (gameFunc->ScriptIsRunning(gameFunc->gameScript))
					ani.sprite_index.clear();
				else
					ani.sprite_index = L"ai";
				//寻找地图上的Boss
				for (auto& e : entityLayer->Ls)
				{
					if (e->el.name == CS_BOSS_CONTROLCORE_CREATENAME)
					{
						controlCore = std::static_pointer_cast<CS_Boss_ControlCore>(e);
						SetState(L"fightboss_controlcore", 0);
						break;
					}
				}
				//寻找Puu&Tala
				if (stateID == 0)
				{
					for (auto& e : entityLayer->Am)
					{
						if (e->el.name == CS_BOSS_PUU_CREATENAME)
						{
							SetState(L"fightboss_puu&tala", 0);
							break;
						}
					}
				}
			}
		}
		else
		{
			if (!gameFunc->InBossFight(gameFunc->game))
			{
				//隐藏图标
				if (gameFunc->ScriptIsRunning(gameFunc->gameScript))
					ani.sprite_index.clear();
				else
					ani.sprite_index = L"ai";
				//退出boss战模式
				SetState(L"normal", 0);
			}
		}
	}
	switch (stateID)
	{
	case 0://通常模式
		//如果氧气过低，则关闭经验拾取功能
		bAutoPickUp = mychar->stateWater.o2 >= 50;
		CS_MyCharAi::Step();
		break;
	case 1://攻击boss蜂巢&魔花
		FightControlCore();
		break;
	case 2://攻击boss扑悠&塔拉
		FightPuuTala();
		break;
	}
	auto watkZone = atkZone.lock();
	if (watkZone)
	{
		//绑定攻击区域
		watkZone->x = mychar->x;
		watkZone->y = mychar->y;
		watkZone->last_x = mychar->last_x;
		watkZone->last_y = mychar->last_y;
		if (mychar->skillGhostFire.lock)
			watkZone->cbRect.top = 5 * 16;
		else
			watkZone->cbRect.top = 10 * 16;
		//跟随在目标头顶
		x = wattackParent->x;
		y = wattackParent->y - 16;
		last_x = wattackParent->last_x;
		last_y = wattackParent->last_y - 16;
	}
}

void CS_SantaAi::SetState(std::wstring stateName, int lr)
{
	if (stateName == L"normal")
	{
		stateID = 0;
	}
	else if (stateName == L"fightboss_controlcore")
	{
		stateID = 1;
	}
	else if (stateName == L"fightboss_puu&tala")
	{
		stateID = 2;
	}
}

void CS_SantaAi::Destroy()
{
	auto watkZone = atkZone.lock();
	if (watkZone)
	{
		watkZone->Destroy();
		atkZone.reset();
	}
	CS_MyCharAi::Destroy();
}

bool CS_SantaAi::AttackAround()
{
	if (!FilterEnemy())
		return false;
	return StaticAttack(enemyList.front());
}

void CS_SantaAi::FaceAtWind()
{
	auto wattackParent = attackParent.lock();
	if (!wattackParent)
		return;
	auto mychar = std::static_pointer_cast<CS_Santa>(wattackParent);
	if (!mychar->cbRect.inWind)
		return;
	switch (mychar->cbRect.windDir)
	{
	case 7:
	case 4:
	case 1:
		if (mychar->lr != 0)
			mychar->input.SetLeft(true);
		break;
	case 9:
	case 6:
	case 3:
		if (mychar->lr == 0)
			mychar->input.SetRight(true);
		break;
	case 8:
		mychar->input.SetUp(true);
		break;
	case 2:
		mychar->input.SetDown(true);
		break;
	}
}

void CS_SantaAi::FightControlCore()
{
	auto wcontrolCore = controlCore.lock();
	if (!wcontrolCore)
		return;
	auto wattackParent = attackParent.lock();
	if (!wattackParent)
		return;
	auto mychar = std::static_pointer_cast<CS_Santa>(wattackParent);

	auto& x = mychar->x;
	auto& y = mychar->y;
	mychar->input.key = 0;
	bool haveEnemy = FilterEnemy();
	if (wcontrolCore->demonflower_open)
	{
		//桑塔会走到魔花下跳跃攻击
		auto we = wcontrolCore->demonflower.lock();
		if (we)
		{
			float posX = we->x + (we->cbRect.left + we->cbRect.right) / 2;
			if (x > posX + 16)
				mychar->input.SetLeft(true);
			else if (x < posX - 16)
				mychar->input.SetRight(true);
			if (abs(mychar->x - posX) <= 32)
			{
				mychar->stateJump.jumped = false;
				mychar->stateJump.jump_disable = false;
				mychar->input.SetJump(true);
			}
		}
		if (haveEnemy && enemyList.front().lock() == wcontrolCore->demonflower.lock())
		{
			if (abs(mychar->y - we->y) <= 16 && abs(mychar->x - we->x) <= 32)
			{
				if (atk_interval_counter == 0)
				{
					atk_interval_counter = atk_interval_counter_max;
					mychar->input.SetUp(true);
					mychar->input.SetAtk(true);
				}
			}
		}
	}
	else if (!haveEnemy || (haveEnemy && enemyList.front().lock() == wcontrolCore->demonflower.lock()))
	{
		//接近玩家
		//往玩家方向跑
		auto wplayer = GetPlayer().lock();
		if (wplayer)
		{
			float posX = wplayer->x;
			if (x > posX + 16)
				mychar->input.SetLeft(true);
			else if (x < posX - 16)
				mychar->input.SetRight(true);
		}
	}
	MovingAttack(GetClosestEnemy());
}

void CS_SantaAi::FightPuuTala()
{
	auto wattackParent = attackParent.lock();
	if (!wattackParent)
		return;

	//使用影子模式
	auto mychar = std::static_pointer_cast<CS_Santa>(wattackParent);
	auto followTarget = mychar->attackParent.lock();
	if (followTarget)
	{
		//如果离跟随对象够近则将跟随对象操作送入模仿列表
		if (abs(mychar->x - followTarget->x) <= 96)
		{
			shadowOpList.push_back(followTarget->input);
			if (shadowOpList.size() >= 20)
			{
				DWORD targetKey = shadowOpList.front().key;
				shadowOpList.pop_front();
				mychar->input.key &= GameInput::keybit_switchMc;
				//取出一个作为现在输入的操作
				const DWORD mask =
					GameInput::keybit_atk |
					GameInput::keybit_jump |
					GameInput::keybit_left |
					GameInput::keybit_right |
					GameInput::keybit_up |
					GameInput::keybit_down |
					GameInput::keybit_skill_1 |
					GameInput::keybit_skill_2 |
					GameInput::keybit_skill_3 |
					GameInput::keybit_skill_4 |
					GameInput::keybit_skill_5 |
					GameInput::keybit_skill_6;
				mychar->input.key |= targetKey & mask;
			}
		}
		else
		{
			CS_MyCharAi::Step();
		}
	}
	else
	{
		mychar->attackParent = gameFunc->GetMyChar_Player1(gameFunc->entityRes);
	}
}

bool CS_SantaAi::StaticAttack(std::weak_ptr<Entity> e)
{
	auto wattackParent = attackParent.lock();
	if (!wattackParent)
		return false;
	auto mychar = std::static_pointer_cast<CS_Santa>(wattackParent);
	auto we = e.lock();
	if (!we)
		return false;

	//如果敌人在自己头顶上方不远处，则向上攻击
	if (we->y < mychar->y - 20 && abs(mychar->x - we->x) <= 8)
	{
		mychar->input.SetUp(true);
		//转身
		if (we->x > mychar->x && mychar->lr == 0)
			mychar->input.SetRight(true);
		else if (we->x < mychar->x && mychar->lr == 1)
			mychar->input.SetLeft(true);
		SkillAttack(mychar);
		//停下动作攻击
		if (atk_interval_counter == 0)
		{
			atk_interval_counter = atk_interval_counter_max;
			mychar->input.SetAtk(true);
		}
		return true;
	}
	if (we->y >= mychar->y)
	{
		//转身
		if (we->x > mychar->x && mychar->lr == 0)
			mychar->input.SetRight(true);
		else if (we->x < mychar->x && mychar->lr == 1)
			mychar->input.SetLeft(true);
		SkillAttack(mychar);
		//停下动作攻击
		if (atk_interval_counter == 0)
		{
			atk_interval_counter = atk_interval_counter_max;
			mychar->input.SetAtk(true);
		}
		return true;
	}
	//直接攻击
	if (atk_interval_counter == 0)
	{
		atk_interval_counter = atk_interval_counter_max;
		mychar->input.SetAtk(true);
	}
	return false;
}

bool CS_SantaAi::MovingAttack(std::weak_ptr<Entity> e)
{
	auto wattackParent = attackParent.lock();
	if (!wattackParent)
		return false;
	auto mychar = std::static_pointer_cast<CS_Santa>(wattackParent);
	auto we = e.lock();
	if (!we)
		return false;

	auto& x = mychar->x;
	auto& y = mychar->y;
	//攻击下方敌人
	if (we->y > mychar->y - 4 && abs(mychar->x - we->x) <= 16)
	{
		//往下方向攻击
		if (atk_interval_counter == 0)
		{
			//攻击
			atk_interval_counter = atk_interval_counter_max;
			mychar->input.SetDown(true);
			mychar->input.SetAtk(true);
		}
		SkillAttack(mychar);
	}
	else if (we->x > x)
	{
		SkillAttack(mychar);
		//往右方向攻击
		if (atk_interval_counter == 0)
		{
			//攻击
			atk_interval_counter = atk_interval_counter_max;
			//默认向上攻击
			if (abs(mychar->x - we->x) < 64)
				mychar->input.SetUp(true);
			else
				mychar->input.SetRight(true);
			mychar->input.SetAtk(true);
		}
		else
		{
			bool bFlee = false;
			//逃跑
			if (abs(mychar->x - we->x) <= 4 && abs(mychar->x - we->x) <= 4)
			{
				//往玩家方向跑
				auto wplayer = GetPlayer().lock();
				if (wplayer)
				{
					if (x > wplayer->x)
						mychar->input.SetLeft(true);
					else
						mychar->input.SetRight(true);
					bFlee = true;
				}

			}
			if(!bFlee)
			{
				//往左移动
				mychar->input.SetLeft(true);
			}
		}
	}
	else
	{
		SkillAttack(mychar);
		//往左方向攻击
		if (atk_interval_counter == 0)
		{
			//攻击
			atk_interval_counter = atk_interval_counter_max;
			//默认向上攻击
			if (abs(mychar->x - we->x) < 64)
				mychar->input.SetUp(true);
			else
				mychar->input.SetLeft(true);
			mychar->input.SetAtk(true);
		}
		else
		{
			bool bFlee = false;
			//逃跑
			if (abs(mychar->x - we->x) <= 4 && abs(mychar->x - we->x) <= 4)
			{
				//往玩家方向跑
				auto wplayer = GetPlayer().lock();
				if (wplayer)
				{
					if (x > wplayer->x)
						mychar->input.SetLeft(true);
					else
						mychar->input.SetRight(true);
					bFlee = true;
				}

			}
			if (!bFlee)
			{
				//往右移动
				mychar->input.SetRight(true);
			}
		}
	}
	return false;
}

bool CS_SantaAi::FilterEnemy()
{
	auto watkZone = atkZone.lock();
	if (!watkZone)
		return false;

	auto wattackParent = attackParent.lock();
	if (!wattackParent)
		return false;
	auto mychar = std::static_pointer_cast<CS_Santa>(wattackParent);
	//查看敌人是否在自己周围
	enemyList.clear();
	for (auto& e : watkZone->touchList)
	{
		auto we = e.lock();
		if (we)
		{
			//跳过不是抛射物
			if (we->type != 2)
				continue;
			//跳过陷阱
			if (we->isTrap)
				continue;
			if (we->hp == 0)
				continue;
			//跳过玩家发射的抛射物
			auto we_attackParent = we->attackParent.lock();
			if (we_attackParent && we_attackParent->type == 1)
				continue;
			auto cell = gameFunc->GetPath(mychar, we->x / 16, we->y / 16, mychar->x / 16, mychar->y / 16);
			//直线测试
			if (gameFunc->LineTest(mychar, mychar->x / 16, mychar->y / 16, we->x / 16, we->y / 16))
				continue;
			//寻路距离过远则忽略这个敌人
			if (cell->dis > 10)
				continue;
			enemyList.push_back(we);
		}
	}
	return !enemyList.empty();
}

std::weak_ptr<Entity> CS_SantaAi::GetClosestEnemy(float* outDis)
{
	//筛出最有威胁的那个
	//在30回合内离自己最近的抛射物
	auto wattackParent = attackParent.lock();
	if (!wattackParent)
		return std::weak_ptr<Entity>();
	auto mychar = std::static_pointer_cast<CS_Santa>(wattackParent);
	auto& x = mychar->x;
	auto& y = mychar->y;
	int turn = 30;
	float minDis = 9999;
	std::weak_ptr<Entity> minEntity;
	
	for (auto& e : enemyList)
	{
		auto we = e.lock();
		if (we)
		{
			if (abs(we->x - mychar->x) <= 8 && abs(we->y - mychar->y) <= 8)
			{
				if (outDis)
					*outDis = 7;
				return we;
			}
			if (abs(we->vx) < 0.001f && abs(we->vy) < 0.001f)
				continue;
			//计算速度向量
			XMVECTOR vec_1Size = XMVector2Normalize(XMVectorSet(we->vx, we->vy, 0, 0));
			float vecX = XMVectorGetX(vec_1Size);
			float vecY = XMVectorGetY(vec_1Size);
			auto& x0 = we->x;
			auto& y0 = we->y;
			auto& x1 = x;
			auto& y1 = y;
			//计算最近点
			float dis = abs((x1 - x0) * vecY - (y1 - y0) * vecX);
			//跳过不会经过自己的直线
			if (dis >= 32)
				continue;
			//计算垂足坐标
			float v = (x1 - x0) * vecX + (y1 - y0) * vecY;
			float xp = x0 + vecX * v;
			float yp = y0 + vecY * v;
			//计算到垂足坐标花费的回合
			XMVECTOR vec = XMVectorSet(we->vx, we->vy, 0, 0);
			float vec_model = XMVectorGetX(XMVector2Length(vec));
			float vecP_model = XMVectorGetX(XMVector2Length(XMVectorSet(xp - x0, yp - y0, 0, 0)));
			float comp_dis;
			if (vec_model * turn >= vecP_model)
			{
				//已经经过了垂足，最近距离就是dis
				comp_dis = dis;
			}
			else
			{
				//没过垂足，最近距离就是30回合后的坐标距离
				//计算30回合后的坐标
				auto turnedVec = vec * (float)turn + XMVectorSet(we->x, we->y, 0, 0);
				//计算那个的距离
				comp_dis = XMVectorGetX(XMVector2Length(turnedVec - XMVectorSet(x, y, 0, 0)));
			}
			//看哪个在30回合内最先接近自己的抛射物
			if (comp_dis < minDis)
			{
				minDis = comp_dis;
				minEntity = e;
			}
		}
	}
	if (outDis)
		*outDis = minDis;
	return minEntity;
}

std::weak_ptr<Entity> CS_SantaAi::GetPlayer()
{
	auto wattackParent = attackParent.lock();
	if (!wattackParent)
		return std::weak_ptr<Entity>();
	auto mychar = std::static_pointer_cast<CS_Santa>(wattackParent);
	auto wplayer = gameFunc->GetMyChar_Player1(gameFunc->entityRes).lock();
	if (wplayer != mychar)
		return wplayer;
	wplayer = gameFunc->GetMyChar_Player2(gameFunc->entityRes).lock();
	if (wplayer != mychar)
		return wplayer;
	return std::weak_ptr<Entity>();
}

void CS_SantaAi::SkillAttack(std::shared_ptr<CS_Santa>& mychar)
{
	mychar->input.key |= mychar->skillGhostFire.keyMask;
}

std::shared_ptr<Entity> CreateCS_SantaAi()
{
	return std::make_shared<CS_SantaAi>();
}
