#include "CS_MyCharAi.h"
#include "CS_Exp.h"
#include "CS_Heart.h"
CS_MyCharAi::CS_MyCharAi()
{
	cbRect.bottom = 36;
	cbRect.left = cbRect.right = 6;
}

void CS_MyCharAi::Init(std::weak_ptr<Entity> self)
{
	InitControlTarget();
	auto wicon = std::make_shared<CS_MyCharAi_Icon>();
	icon = wicon;
	gameFunc->SetEntity(shared_from_this(), wicon);
	Entity::Init(self);
}

void CS_MyCharAi::Step()
{
	auto wattackParent = attackParent.lock();
	if (!wattackParent)
	{
		Destroy();
		return;
	}
	if (!wattackParent->enableAI)
	{
		Destroy();
		return;
	}
	//防止掉地图外面
	Entity::KeepInMap();
	//更新接触的实体
	GridTouch(aiLayer);
	wattackParent->GridTouch(aiLayer);
	//清空操作
	wattackParent->input.key &= GameInput::keybit_switchMc;
	//跟随在目标头顶
	x = wattackParent->x;
	y = wattackParent->y - 16;
	last_x = wattackParent->last_x;
	last_y = wattackParent->last_y - 16;
	//ai图标跟随
	IconFollow();
	//如果在平台边缘则禁止攻击
	bool bCareful = false;
	for (auto& e : touchList)
	{
		auto we = e.lock();
		if (we)
		{
			if (we->el.name == AIMOVEEND_CREATENAME)
			{
				bCareful = true;
				break;
			}
		}
	}
	if (!bCareful && AttackAround())
	{
		moveOpList.clear();
	}
	else
	{
		Control();
	}
	//清除ok和cancel
	wattackParent->input.key &= ~GameInput::keybit_ok;
	wattackParent->input.key &= ~GameInput::keybit_cancel;
}

void CS_MyCharAi::Destroy()
{
	//找到自己的控制目标，然后从它身上移除
	auto wattackParent = attackParent.lock();
	if (wattackParent)
		wattackParent->ai.reset();
	auto wicon = icon.lock();
	if (wicon)
		wicon->Destroy();
	Entity::Destroy();
}

void CS_MyCharAi::IconFollow()
{
	auto wattackParent = attackParent.lock();
	if (!wattackParent)
		return;
	//ai图标跟随
	auto wicon = icon.lock();
	if (wicon)
	{
		wicon->x = wattackParent->x + wicon->dx;
		wicon->y = wattackParent->y - 16 + wicon->dy;
		wicon->last_x = wattackParent->last_x + wicon->dx;
		wicon->last_y = wattackParent->last_y - 16 + wicon->dy;
		//隐藏图标
		if (gameFunc->ScriptIsRunning)
		{
			if (gameFunc->ScriptIsRunning(gameFunc->gameScript))
				wicon->ani.sprite_index.clear();
			else
				wicon->ani.sprite_index = L"ai";
		}
		//隐藏了
		if (wattackParent->hide)
		{
			wicon->ani.sprite_index.clear();
		}
	}
}

void CS_MyCharAi::Control()
{
	auto wattackParent = attackParent.lock();
	if (!wattackParent)
		return;
	//强制操作
	if (Key())
		return;
	/*-----------------------------移动控制-------------------------------*/
	if (adjust_counter > 0)
	{
		adjust_counter--;
		if (adjust_counter == 0)
			adjustUpTarget.reset();
	}
	auto wadjustUpTarget = adjustUpTarget.lock();
	if (wadjustUpTarget)
	{
		
		//如果有移动调整目标，先接近调整目标
		if (abs(wattackParent->x - wadjustUpTarget->x) > 1)
		{
			if (wattackParent->x > wadjustUpTarget->x)
			{
				//往左移动调整
				wattackParent->input.SetLeft(true);
			}
			else
			{
				//往右移动调整
				wattackParent->input.SetRight(true);
			}
		}
		else
		{
			if (abs(wattackParent->vx) < 0.1f && wattackParent->cbRect.cbBottom)
				adjustUpTarget.reset();
		}
	}
	else if (!moveOpList.empty())
	{
		//如果有操作则使用操作指令
		wattackParent->input.key = moveOpList.front().key;
		moveOpList.pop_front();
	}
	else
	{
		bool usingStation = false;
		std::weak_ptr<Entity> followTarget;
		std::weak_ptr<AiStation> selfStation;
		std::weak_ptr<AiStation> followStation;
		std::weak_ptr<AiStation> targetStation;
		auto mychar = std::static_pointer_cast<MyCharEntity> (wattackParent);
		bool bPickUp = false;
		//去捡周围的生命
		if (followTarget.expired())
		{
			std::weak_ptr<Entity> heartItem;
			if (mychar->hp < mychar->hp_max)
				heartItem = PickUpHeart(mychar->x, mychar->y);
			if (!heartItem.expired())
			{
				bPickUp = true;
				followTarget = heartItem;
			}
		}
		//去捡周围的经验
		if (followTarget.expired())
		{
			std::weak_ptr<Entity> expItem;
			if (mychar->mp < mychar->mp_max)
				expItem = PickUpExp(mychar->x, mychar->y);
			if (!expItem.expired())
			{
				bPickUp = true;
				followTarget = expItem;
			}
		}
		//跟随这个目标
		if (followTarget.expired() && !mychar->attackParent.expired())
			followTarget = mychar->attackParent;
		//没有没有跟随目标，则跟随玩家
		if (followTarget.expired())
			followTarget = gameFunc->GetMyChar_Player1(gameFunc->entityRes);
		auto wfollowTarget = followTarget.lock();
		if (wfollowTarget)
		{
			mychar->attackParent = wfollowTarget;
			float dx_follow = abs(mychar->x - wfollowTarget->x);
			float dy_follow = abs(mychar->y - wfollowTarget->y);
			if (aiLayer && (dx_follow * dx_follow + dy_follow * dy_follow > 32 * 32))
			{
				//使用车站系统
				//搜索离自己最近的车站的距离来判断自己的方位
				selfStation = GetEntityStationPos(mychar->x, mychar->y);
				followStation = GetEntityStationPos(wfollowTarget->x, wfollowTarget->y);
				usingStation = true;
				//如果在同一个车站位置，则不需要引导
				if (selfStation.lock() == followStation.lock())
					usingStation = false;
			}
			//去目标地点
			if (usingStation && !selfStation.expired() && wfollowTarget)
			{
				followStation = targetStation = GoNextStation(selfStation, followStation);
				auto wf = followStation.lock();
				if (wf)
					wfollowTarget = wf;
			}
			//如果离目标垂直距离过远，则尝试跳跃到目标附近
			float ySearch = 16;
			if (bPickUp || usingStation)
				ySearch = 8;
			if (abs(mychar->y - wfollowTarget->y) > ySearch)
			{
				if (mychar->y > wfollowTarget->y)
				{
					if (mychar->x > wfollowTarget->x)
						Up(targetStation, false);//往上左走
					else
						Up(targetStation, true);//往上右走
				}
				else
				{
					if (mychar->x > wfollowTarget->x)
						Down(targetStation, false);//往下左走
					else
						Down(targetStation, true);//往下右走
				}
			}
			//如果离目标水平距离过远则尝试走到目标附近
			float xSearch = 24;
			if (bPickUp || usingStation)
				xSearch = 4;
			//如果心在自己正上方不远处则跳起
			if (wfollowTarget->el.name == CS_HEART_CREATENAME &&
				abs(mychar->x - wfollowTarget->x) < 12 &&
				mychar->y - wfollowTarget->y >= 12 &&
				mychar->y - wfollowTarget->y <= 50)
			{
				wattackParent->input.SetJump(true);
			}
			//左右移动
			else if (abs(mychar->x - wfollowTarget->x) > xSearch)
			{
				if (mychar->x > wfollowTarget->x)
					Move(targetStation, false);//往左走
				else
					Move(targetStation, true);//往右走
			}
		}
	}
}

void CS_MyCharAi::InitControlTarget()
{
	//寻找控制对象
	if (gameFunc->GetGlobalEntityTable)
	{
		auto& allPlayer = *gameFunc->GetGlobalEntityTable(gameFunc->game);
		for (auto& p : allPlayer)
		{
			auto we = p.second.lock();
			if (we)
			{
				auto wplayer = std::dynamic_pointer_cast<MyCharEntity>(we);
				if (wplayer)
				{
					if (wplayer->ai.expired())
						continue;
					if (wplayer->ai.lock() == shared_from_this())
					{
						attackParent = wplayer;
						//载入跟随目标
						if (wplayer->lastAI_followTarget.length())
						{
							for (auto& t : allPlayer)
							{
								auto wtarget = t.second.lock();
								if (wtarget)
								{
									if (wplayer->lastAI_followTarget == wtarget->globalEntityID)
									{
										wplayer->attackParent = wtarget;
										break;
									}
								}
							}
						}
						break;
					}
				}
			}
		}
	}
	if (attackParent.expired())
		Destroy();
	//寻找ai记录层
	auto& allRes = *gameFunc->GetLoadedEntity(gameFunc->entityRes);
	for (auto& p : allRes)
	{
		if (p.first->layerName == L"ai_record")
		{
			aiLayer = &p.second;
			break;
		}
	}
}

void CS_MyCharAi::Move(std::weak_ptr<AiStation> targetStation, bool lr)
{
	auto wattackParent = attackParent.lock();
	if (!wattackParent)
		return;

	if (!moveOpList.empty())
		return;
	if (lr == 0)
		wattackParent->input.SetLeft(true);
	else
		wattackParent->input.SetRight(true);
	//查看附近的移动记录
	for (auto& e : wattackParent->touchList)
	{
		auto we = e.lock();
		if (we)
		{
			//方向必须是左侧
			if (we->el.flag.lr == lr)
			{
				//使用移动记录
				if (IsTargetStation(targetStation, we, AIMOVERECORD_CREATENAME))
				{
					auto rE = std::static_pointer_cast<AiRecord>(we);
					for (auto& op : rE->record)
						moveOpList.push_back(op);
					return;
				}
				//使用调整跳跃
				else if (IsTargetStation(targetStation, we, AIMOVEEND_CREATENAME))
				{
					adjustUpTarget = we;
					adjust_counter = adjust_counter_max;
					auto rE = std::static_pointer_cast<AiRecord>(we);
					moveOpList.clear();
					for (auto& op : rE->record)
						moveOpList.push_back(op);
					return;
				}
			}
		}
	}
}

void CS_MyCharAi::Up(std::weak_ptr<AiStation> targetStation, bool lr)
{
	if (!moveOpList.empty())
		return;
	//查看上方的移动记录
	for (auto& e : touchList)
	{
		auto we = e.lock();
		if (we)
		{
			//方向必须是右侧
			if (we->el.flag.lr == lr)
			{
				//使用右侧的那个跳跃
				if (IsTargetStation(targetStation, we, AIUPRECORD_CREATENAME))
				{
					auto rE = std::static_pointer_cast<AiRecord>(we);
					for (auto& op : rE->record)
						moveOpList.push_back(op);
				}
				//使用调整右侧跳跃
				else if (IsTargetStation(targetStation, we, AIADJUSTUP_CREATENAME))
				{
					adjustUpTarget = we;
					adjust_counter = adjust_counter_max;
					auto rE = std::static_pointer_cast<AiRecord>(we);
					moveOpList.clear();
					for (auto& op : rE->record)
						moveOpList.push_back(op);
				}
			}
		}
	}
}

void CS_MyCharAi::Down(std::weak_ptr<AiStation> targetStation, bool lr)
{
	auto wattackParent = attackParent.lock();
	if (!wattackParent)
		return;

	if (!moveOpList.empty())
		return;
	if (lr == 0)
		wattackParent->input.SetLeft(true);
	else
		wattackParent->input.SetRight(true);
	//查看上方的移动记录
	for (auto& e : touchList)
	{
		auto we = e.lock();
		if (we)
		{
			//方向必须是右侧
			if (we->el.flag.lr == lr)
			{
				//使用右侧的那个跳跃
				if (IsTargetStation(targetStation, we, AIDOWNRECORD_CREATENAME))
				{
					auto rE = std::static_pointer_cast<AiRecord>(we);
					for (auto& op : rE->record)
						moveOpList.push_back(op);
				}
			}
		}
	}
}

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

	auto mychar = std::static_pointer_cast<MyCharEntity> (wattackParent);
	bool ret = false;
	//查看上方的移动记录
	for (auto& p : touchList)
	{
		auto we = p.lock();
		if (we)
		{
			if (!we->inUsing)
				continue;
			//使用强制键
			if (we->el.name == AIKEY_CREATENAME)
			{
				auto k = std::static_pointer_cast<AiKey>(we);
				mychar->input.key |= k->key.key;
				ret = true;
			}
		}
	}
	return ret;
}

bool CS_MyCharAi::IsTargetStation(std::weak_ptr<AiStation> targetStation, std::weak_ptr<Entity> e, const wchar_t* stationType)
{
	//使用移动记录
	auto we = e.lock();
	if (!we)
		return false;
	bool usingRecord = false;
	if (we->el.name == stationType)
	{
		auto rE = std::static_pointer_cast<AiRecord>(we);
		if (!rE->parentStation.expired() && !targetStation.expired())
		{
			if (rE->parentStation.lock() == targetStation.lock())
				usingRecord = true;
		}
		else
		{
			usingRecord = true;
		}
	}
	return usingRecord;
}

bool CS_MyCharAi::AttackAround()
{
	return false;
}

std::weak_ptr<Entity> CS_MyCharAi::PickUpExp(float x, float y)
{
	if (!bAutoPickUp)
		return std::weak_ptr<Entity>();
	auto wattackParent = attackParent.lock();
	if (!wattackParent)
		return std::weak_ptr<Entity>();

	auto mychar = std::static_pointer_cast<MyCharEntity> (wattackParent);
	float minDis = MAX_DISTANCE;
	std::weak_ptr<Entity> expItem;
	//查看自己周围有没有散落的经验
	if (mychar->entityLayer)
	{
		auto& Ls = ((EntityLayer*)mychar->entityLayer)->Ls;
		for (auto& p : Ls)
		{
			if (p->el.name == CS_EXP_CREATENAME)
			{
				//经验必须在安全区域
				auto wstation = GetEntityStationPos(p->x, p->y).lock();
				if (wstation)
				{
					if (wstation->stationType != 0)
						continue;//跳过非安全区域
					//计算平方最小距离
					float dx = abs(x - p->x);
					float dy = abs(y - p->y);
					float disSq = dx * dx + dy * dy;
					if (disSq < minDis)
					{
						minDis = disSq;
						expItem = p;
					}
				}
			}
		}
	}
	return expItem;
}

std::weak_ptr<Entity> CS_MyCharAi::PickUpHeart(float x, float y)
{
	if (!bAutoPickUp)
		return std::weak_ptr<Entity>();
	auto wattackParent = attackParent.lock();
	if (!wattackParent)
		return std::weak_ptr<Entity>();

	auto mychar = std::static_pointer_cast<MyCharEntity> (wattackParent);
	float minDis = MAX_DISTANCE;
	std::weak_ptr<Entity> heartItem;
	//查看自己周围有没有散落的经验
	if (mychar->entityLayer)
	{
		auto& Ls = ((EntityLayer*)mychar->entityLayer)->Ls;
		for (auto& p : Ls)
		{
			if (p->el.name == CS_HEART_CREATENAME)
			{
				//生命到地面的距离必须小于48
				float height = 0;//距离地面高度
				for (int i = 1; i < 4; i++)
				{
					if (gameFunc->LineTest(p, p->x / 16, p->y / 16, p->x / 16, p->y / 16 + i))
						break;
					height += 16;
					if (height > 50)
						break;
				}
				//这个生命太高捡不到
				if (height > 50)
					continue;
				//生命必须在安全区域
				auto wstation = GetEntityStationPos(p->x, p->y + height).lock();
				if (wstation)
				{
					if (wstation->stationType != 0)
						continue;//跳过非安全区域
					//计算平方最小距离
					float dx = abs(x - p->x);
					float dy = abs(y - (p->y + height));
					float disSq = dx * dx + dy * dy;
					if (disSq < minDis)
					{
						minDis = disSq;
						heartItem = p;
					}
				}
				else
				{
					//计算平方最小距离
					float dx = abs(x - p->x);
					float dy = abs(y - (p->y + height));
					float disSq = dx * dx + dy * dy;
					if (disSq < minDis)
					{
						minDis = disSq;
						heartItem = p;
					}
				}
			}
		}
	}
	return heartItem;
}

std::weak_ptr<AiStation> CS_MyCharAi::GetEntityStationPos(float x, float y)
{
	if (!aiLayer)
		return std::weak_ptr<AiStation>();
	float minDis = MAX_DISTANCE;
	std::weak_ptr<AiStation> minStation;
	//使用车站矩形
	for (auto& p : aiLayer->Ls)
	{
		if (p->el.name != AISTATION_CREATENAME)
			continue;
		if (x > p->x - p->cbRect.left && x <= p->x + p->cbRect.right)
		{
			if (y > p->y - p->cbRect.top && y <= p->y + p->cbRect.bottom)
			{
				auto s = std::static_pointer_cast<AiStation>(p);
				if (!s->coreStation.expired())
					return s->coreStation;
				else
					return s;
			}
		}
	}
	//如果都没满足则用距离法
	for (auto& p : aiLayer->Ls)
	{
		if (p->el.name != AISTATION_CREATENAME)
			continue;
		float dx = abs(x - p->x);
		float dy = abs(y - p->y);
		float disSq = dx * dx + dy * dy;
		if (disSq < minDis)
		{
			minDis = disSq;
			minStation = std::static_pointer_cast<AiStation>(p);
		}
	}
	auto wminStation = minStation.lock();
	if (wminStation && !wminStation->coreStation.expired())
		return wminStation->coreStation;
	else
		return minStation;
}

std::weak_ptr<AiStation> CS_MyCharAi::GoNextStation(std::weak_ptr<AiStation> srcStation, std::weak_ptr<AiStation> dstStation)
{
	auto wsrcStation = srcStation.lock();
	auto wdstStation = dstStation.lock();
	if (!wsrcStation || !wdstStation)
		return std::weak_ptr<AiStation>();

	std::vector<int>& src = wsrcStation->stationID;
	std::vector<int>& dst = wdstStation->stationID;
	std::vector<int> temp = src;
	int equalLevel = 0;
	while (true)
	{
		if (src.at(equalLevel) == dst.at(equalLevel))
		{
			//则比较下一层
			equalLevel++;
			if (src.size() - 1 < equalLevel)//去岔路
			{
				temp.push_back(0);
				return IDGetStation(&temp);
			}
			else if (dst.size() - 1 < equalLevel)
			{
				//往根处走
				if (temp.back() == 0)
					temp.pop_back();
				else
					temp.back()--;
				return IDGetStation(&temp);
			}
		}
		else
		{
			if (src.size() - 1 == equalLevel)
			{
				if (src.at(equalLevel) > dst.at(equalLevel))//逆乘
					temp.back()--;
				else//顺乘
					temp.back()++;
				return IDGetStation(&temp);
			}
			//往根处走
			if (temp.back() == 0)
				temp.pop_back();
			else
				temp.back()--;
			return IDGetStation(&temp);
		}
	}
}

std::weak_ptr<AiStation> CS_MyCharAi::IDGetStation(std::vector<int>* stationID)
{
	for (auto& p : aiLayer->Ls)
	{
		if (p->el.name != AISTATION_CREATENAME)
			continue;
		auto minStation = std::static_pointer_cast<AiStation>(p);
		if (minStation->stationID == *stationID)
			return minStation;
	}
	return std::weak_ptr<AiStation>();
}

std::shared_ptr<Entity> CreateCS_MyCharAi()
{
	return std::make_shared<CS_MyCharAi>();
}
