#include "CS_JackAi.h"
#include "CS_Jack.h"
#include "CS_Boss_ControlCore.h"
#include "CS_Enemy_Firefly.h"
#include "CS_FallingSpike.h"
#include "CS_Boss_Puu.h"
CS_JackAi::CS_JackAi()
{
	el.name = CS_JACKAI_CREATENAME;
}

void CS_JackAi::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 = 14 * 16;
	watkZone->cbRect.bottom = 5 * 16;
	gameFunc->SetEntity(shared_from_this(), watkZone);
	CS_MyCharAi::Init(self);
}

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

	auto mychar = std::static_pointer_cast<CS_Jack>(wattackParent);
	if (!mychar)
	{
		InitControlTarget();
		return;
	}
	if (gameFunc->InBossFight)
	{
		if (stateID == 0)
		{
			if (gameFunc->InBossFight(gameFunc->game) ||
				gameFunc->flagSet->find(L"AIBossFight") != gameFunc->flagSet->end())
			{
				bool bFound = false;
				//寻找地图上的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);
						bFound = true;
						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);
							bFound = true;
							break;
						}
					}
				}
				//如果没用找到则使用默认模式
				if (!bFound)
				{
					SetState(L"fightboss_puu&tala", 0);
				}
			}
		}
		else
		{
			if (!gameFunc->InBossFight(gameFunc->game))
			{
				//退出boss战模式
				SetState(L"normal", 0);
			}
		}
	}
	switch (stateID)
	{
	case 0://通常模式
		//如果氧气过低，则关闭经验拾取功能
		bAutoPickUp = mychar->stateWater.o2 >= 50;
		CS_MyCharAi::Step();
		break;
	case 1://攻击boss蜂巢&魔花
		FightControlCore();
		IconFollow();//ai图标跟随
		break;
	case 2://攻击boss扑悠&塔拉
		FightPuuTala();
		IconFollow();//ai图标跟随
		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;
		//跟随在目标头顶
		x = wattackParent->x;
		y = wattackParent->y - 16;
		last_x = wattackParent->last_x;
		last_y = wattackParent->last_y - 16;
	}
}

void CS_JackAi::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_JackAi::Destroy()
{
	auto watkZone = atkZone.lock();
	if (watkZone)
	{
		watkZone->Destroy();
		atkZone.reset();
	}
	CS_MyCharAi::Destroy();
}

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

void CS_JackAi::FaceAtWind()
{
	auto wattackParent = attackParent.lock();
	if (!wattackParent)
		return;
	auto mychar = std::static_pointer_cast<CS_Jack>(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_JackAi::FightControlCore()
{
	auto wcontrolCore = controlCore.lock();
	if (!wcontrolCore)
		return;
	auto wattackParent = attackParent.lock();
	if (!wattackParent)
		return;
	auto mychar = std::static_pointer_cast<CS_Jack>(wattackParent);

	auto& x = mychar->x;
	auto& y = mychar->y;
	mychar->input.key = 0;
	mychar->stateJump.jumped = false;
	mychar->stateJump.jump_disable = false;
	bool attackBoss = wcontrolCore->honeycomb_open;
	bool haveEnemy = FilterEnemy();
	if (wcontrolCore->honeycomb_open)
	{
		//杰克会走到蜂巢下攻击
		auto we = wcontrolCore->honeycomb.lock();
		if (we)
		{
			float posX = we->x;
			if (x > posX + 16)
				mychar->input.SetLeft(true);
			else if (x < posX - 16)
				mychar->input.SetRight(true);
		}
		if (abs(mychar->x - we->x) <= 32)
		{
			AttackStep();
			mychar->input.SetUp(true);
		}
	}
	else if (!haveEnemy || (haveEnemy && enemyList.front().lock() == wcontrolCore->honeycomb.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_JackAi::FightPuuTala()
{
	auto wattackParent = attackParent.lock();
	if (!wattackParent)
		return;

	//使用影子模式
	auto mychar = std::static_pointer_cast<CS_Jack>(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_JackAi::StaticAttack(std::weak_ptr<Entity> e)
{
	//取泡泡枪等级
	auto wattackParent = attackParent.lock();
	if (!wattackParent)
		return false;
	auto mychar = std::static_pointer_cast<CS_Jack>(wattackParent);
	auto we = e.lock();
	if (!we)
		return false;

	int level = mychar->skillBubbler.level;
	if (level == 0)
	{
		//如果敌人在自己头顶上方不远处，则向上攻击
		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);
			//停下动作攻击
			AttackStep();
			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);
			//停下动作攻击
			AttackStep();
			return true;
		}
		//直接攻击
		AttackStep();
	}
	else
	{
		//随机蓄力攻击
		//如果敌人在自己头顶上方不远处，则向上攻击
		if (we->y < mychar->y - 20 && abs(mychar->x - we->x) <= 32)
		{
			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);
			//停下动作攻击
			AttackStep();
			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);
			//停下动作攻击
			AttackStep();
			return true;
		}
		//直接攻击
		AttackStep();
	}
	return false;
}

bool CS_JackAi::MovingAttack(std::weak_ptr<Entity> e)
{
	//取泡泡枪等级
	auto wattackParent = attackParent.lock();
	if (!wattackParent)
		return false;

	auto mychar = std::static_pointer_cast<CS_Jack>(wattackParent);
	auto we = e.lock();
	if (!we)
		return false;

	auto& x = mychar->x;
	auto& y = mychar->y;
	if (we->x > x)
	{
		//直接攻击
		bool bFlee = !AttackStep();
		if (bFlee)
		{
			//往玩家方向跑
			auto wplayer = GetPlayer().lock();
			if (wplayer)
			{
				if (x > wplayer->x)
					mychar->input.SetLeft(true);
				else
					mychar->input.SetRight(true);
			}
		}
		else
		{
			mychar->input.SetUp(true);
			mychar->input.SetLeft(true);
		}
	}
	else
	{
		//直接攻击
		bool bFlee = !AttackStep();
		if (bFlee)
		{
			//往玩家方向跑
			auto wplayer = GetPlayer().lock();
			if (wplayer)
			{
				if (x > wplayer->x)
					mychar->input.SetLeft(true);
				else
					mychar->input.SetRight(true);
			}
		}
		else
		{
			mychar->input.SetUp(true);
			mychar->input.SetRight(true);
		}
	}
	return false;
}

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

	auto wattackParent = attackParent.lock();
	if (!wattackParent)
		return false;
	auto mychar = std::static_pointer_cast<CS_Jack>(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_JackAi::GetClosestEnemy(float* outDis)
{
	//筛出最有威胁的那个
	//在30回合内离自己最近的抛射物
	auto wattackParent = attackParent.lock();
	if (!wattackParent)
		return std::weak_ptr<Entity>();

	auto mychar = std::static_pointer_cast<CS_Jack>(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)
		{
			//排除恶魔花
			auto wcontrolCore = controlCore.lock();
			if (wcontrolCore)
			{
				if (we == wcontrolCore->demonflower.lock())
					continue;
			}
			if (abs(we->x - mychar->x) <= 8 && abs(we->y - mychar->y) <= 8)
			{
				if (outDis)
					*outDis = 7;
				return e;
			}
			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_JackAi::GetPlayer()
{
	auto wattackParent = attackParent.lock();
	if (!wattackParent)
		return std::weak_ptr<Entity>();
	auto mychar = std::static_pointer_cast<CS_Jack>(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>();
}

bool CS_JackAi::AttackStep()
{
	auto wattackParent = attackParent.lock();
	if (!wattackParent)
		return false;

	auto mychar = std::static_pointer_cast<CS_Jack>(wattackParent);
	SkillAttack(mychar);
	if (enableAttack)
	{
		if (mychar->skillBubbler.level == 0)
		{
			if (atk_interval_counter == 0)
			{
				atk_interval_counter = atk_interval_counter_max;
				mychar->input.SetAtk(true);
			}
		}
		else
		{
			//直接攻击
			if (atk_interval_counter == 0)
				atk_interval_counter = atk_interval_counter_max;
			else
				mychar->input.SetAtk(true);
		}
	}
	if (mychar->skillBubbler.ammo_count == 0)
	{
		enableAttack = false;
	}
	else if (mychar->skillBubbler.ammo_count >= 20)
	{
		enableAttack = true;
	}
	return enableAttack;
}

void CS_JackAi::SkillAttack(std::shared_ptr<CS_Jack>& mychar)
{
	mychar->input.key |= mychar->skillCatcher.keyMask;
}

void CS_JackAi::CatchSpecialTarget()
{
	auto watkZone = atkZone.lock();
	if (!watkZone)
		return;
	auto wattackParent = attackParent.lock();
	if (!wattackParent)
		return;
	auto mychar = std::static_pointer_cast<CS_Jack>(wattackParent);
	//如果有萤火虫在自己的正上方或者正左右则使用捕获者开枪
	for (auto& e : watkZone->touchList)
	{
		auto we = e.lock();
		if (we)
		{
			if (gameFunc->LineTest(mychar, mychar->x / 16, mychar->y / 16, we->x / 16, we->y / 16))
				continue;
			if (we->el.name == CS_ENEMY_FIREFLY_CREATENAME)
			{
				//向上捕捉
				if (abs(mychar->x - we->x) <= 8 && we->y < mychar->y)
				{
					mychar->input.SetUp(true);
					SkillAttack(mychar);
				}
				//向左捕捉
				else if (abs(mychar->y - we->y) <= 8 && mychar->x > we->x && mychar->lr == 0)
				{
					SkillAttack(mychar);
				}
				//向右捕捉
				else if (abs(mychar->y - we->y) <= 8 && we->x > mychar->x && mychar->lr == 1)
				{
					SkillAttack(mychar);
				}
			}
			else if (we->el.name == CS_FALLINGSPIKE_CREATENAME)
			{
				if (we->cbRect.cbBottom)
					return;
				//向上捕捉
				if (abs(mychar->x - we->x) <= 8 && we->y < mychar->y)
				{
					mychar->input.SetUp(true);
					SkillAttack(mychar);
				}
			}
		}
	}
}

std::shared_ptr<Entity> CreateCS_JackAi()
{
	return std::make_shared<CS_JackAi>();
}
