#include "MyCamera.h"
#include "Entity.h"
#include "MyView.h"
#include "main.h"
void MyCamera::Init(MyView* pView, int* pMapW, int* pMapH)
{
	this->pView = pView;
	this->pMapW = pMapW;
	this->pMapH = pMapH;
}

void MyCamera::SetTarget(std::weak_ptr<Entity> target, float focusTimes)
{
	this->target = target;
	this->focusTimes = focusTimes;
	if (focusTimes <= 0)
		focusTimes = 1;
}

void MyCamera::SetTarget2(std::weak_ptr<Entity> target2)
{
	this->target2 = target2;
}

void MyCamera::SwapTarget()
{
	auto temp = target;
	target = target2;
	target2 = temp;
}

void MyCamera::EnableLRUD(bool bEnbale)
{
	enableLRUD = bEnbale;
}

void MyCamera::Step()
{
	if (LocalCameraStep())
		return;
	if (bLockCamera)
	{
		camera_last_offx = camera_offx;
		camera_last_offy = camera_offy;
		return;
	}
	auto& view = *pView;
	int mapW = *pMapW, mapH = *pMapH;
	camera_last_offx = camera_offx;
	camera_last_offy = camera_offy;
	camera_offx = quakeCenterX;
	camera_offy = quakeCenterY;
	//双目标
	auto wtarget = target.lock();
	auto wtarget2 = target2.lock();
	if (wtarget)
	{
		if (wtarget2 && wtarget2->el.name != L"null" && !wtarget2->enableAI)
		{
			float dx;
			float dy;
			if (enableLRUD)
			{
				float range_x = view.window_w / view.scale / 8;
				float range_y = view.window_h / view.scale / 4;
				//目标1
				switch (wtarget->lr)
				{
				case 0:
					if (focus_lr_counter_target1 > -range_x)
						focus_lr_counter_target1--;
					break;
				default:
				case 1:
					if (focus_lr_counter_target1 < range_x)
						focus_lr_counter_target1++;
					break;
				}
				switch (wtarget->ud)
				{
				case -1:
					if (focus_ud_counter_target1 > -range_y)
						focus_ud_counter_target1--;
					break;
				default:
				case 0:
					if (focus_ud_counter_target1 > 1)
						focus_ud_counter_target1--;
					if (focus_ud_counter_target1 < -1)
						focus_ud_counter_target1++;
					break;
				case 1:
					if (focus_ud_counter_target1 < range_y)
						focus_ud_counter_target1++;
					break;
				}
				//目标2
				switch (wtarget2->lr)
				{
				case 0:
					if (focus_lr_counter_target2 > -range_x)
						focus_lr_counter_target2--;
					break;
				default:
				case 1:
					if (focus_lr_counter_target2 < range_x)
						focus_lr_counter_target2++;
					break;
				}
				switch (wtarget2->ud)
				{
				case -1:
					if (focus_ud_counter_target2 > -range_y)
						focus_ud_counter_target2--;
					break;
				default:
				case 0:
					if (focus_ud_counter_target2 > 1)
						focus_ud_counter_target2--;
					if (focus_ud_counter_target2 < -1)
						focus_ud_counter_target2++;
					break;
				case 1:
					if (focus_ud_counter_target2 < range_y)
						focus_ud_counter_target2++;
					break;
				}
				float t1x, t1y, t2x, t2y;
				wtarget->GetCameraPos(&t1x, &t1y);
				wtarget2->GetCameraPos(&t2x, &t2y);
				dx = (t1x + t2x) / 2 +
					(focus_lr_counter_target1 + focus_lr_counter_target2) / 2 -
					view.window_w / view.scale / 2;
				dy = (t1y + t2y) / 2 +
					(focus_ud_counter_target1 + focus_ud_counter_target2) / 2 -
					view.window_h / view.scale / 2;
			}
			else
			{
				float t1x, t1y, t2x, t2y;
				wtarget->GetCameraPos(&t1x, &t1y);
				wtarget2->GetCameraPos(&t2x, &t2y);
				dx = (t1x + t2x) / 2 -
					view.window_w / view.scale / 2;
				dy = (t1y + t2y) / 2 -
					view.window_h / view.scale / 2;
			}
			camera_offx += (dx - camera_offx) / focusTimes;
			camera_offy += (dy - camera_offy) / focusTimes;
		}
		//单目标
		else if (wtarget)
		{
			float dx;
			float dy;
			if (enableLRUD)
			{
				float range_x = view.window_w / view.scale / 8;
				float range_y = view.window_h / view.scale / 4;
				//单目标
				switch (wtarget->lr)
				{
				case 0:
					if (focus_lr_counter_target1 > -range_x)
						focus_lr_counter_target1--;
					break;
				default:
				case 1:
					if (focus_lr_counter_target1 < range_x)
						focus_lr_counter_target1++;
					break;
				}
				switch (wtarget->ud)
				{
				case -1:
					if (focus_ud_counter_target1 > -range_y)
						focus_ud_counter_target1--;
					break;
				default:
				case 0:
					if (focus_ud_counter_target1 > 1)
						focus_ud_counter_target1--;
					if (focus_ud_counter_target1 < -1)
						focus_ud_counter_target1++;
					break;
				case 1:
					if (focus_ud_counter_target1 < range_y)
						focus_ud_counter_target1++;
					break;
				}
				float t1x, t1y;
				wtarget->GetCameraPos(&t1x, &t1y);
				dx = t1x + focus_lr_counter_target1 - view.window_w / view.scale / 2;
				dy = t1y + focus_ud_counter_target1 - view.window_h / view.scale / 2;
			}
			else
			{
				float t1x, t1y;
				wtarget->GetCameraPos(&t1x, &t1y);
				dx = t1x - view.window_w / view.scale / 2;
				dy = t1y - view.window_h / view.scale / 2;
			}
			camera_offx += (dx - camera_offx) / focusTimes;
			camera_offy += (dy - camera_offy) / focusTimes;
		}
	}
	//屏幕区域限制
	float dw = view.window_w / (view.grid_w * view.scale);
	float dh = view.window_h / (view.grid_h * view.scale);
	if (camera_offx > view.grid_w * (mapW - dw))
		camera_offx = view.grid_w * (mapW - dw);
	if (camera_offy > view.grid_h * (mapH - dh) - 8)//不让23高度的房间上下晃动
		camera_offy = view.grid_h * (mapH - dh) - 8;
	if (camera_offx < 0)
		camera_offx = 0;
	if (camera_offy < 0)
		camera_offy = 0;
	//如果显示范围比房间要大
	if (mapW * view.grid_w * view.scale < view.window_w)
		camera_offx = -(view.window_w - mapW * view.grid_w * view.scale) / 2 / view.scale;
	if (mapH * view.grid_h * view.scale < view.window_h)
		camera_offy = -(view.window_h - mapH * view.grid_h * view.scale) / 2 / view.scale;
	quakeCenterX = camera_offx;
	quakeCenterY = camera_offy;
	QuakeStep();
}

void MyCamera::DeltaTime(float deltaTime)
{
	auto& view = *pView;
	view.offX = lerp(camera_last_offx, camera_offx, deltaTime);
	view.offY = lerp(camera_last_offy, camera_offy, deltaTime);
}

void MyCamera::FocusOnce()
{
	auto focusTimes_last = max(focusTimes, 1);
	focusTimes = 1;
	auto& view = *pView;
	float offX_last = -1, offY_last = -1;
	while (!(abs(offX_last - camera_offx) < 0.1f &&
		abs(offY_last - camera_offy) < 0.1f))
	{
		offX_last = camera_offx;
		offY_last = camera_offy;
		Step();
	}
		
	focusTimes = focusTimes_last;
}

void MyCamera::Reset()
{
	target2.reset();
	ResetQuake();
}

void MyCamera::SetQuake(int times, int mode)
{
	if (mode == 0)
	{
		quake = times;
	}
	else
	{
		quake2 = times;
	}
}

void MyCamera::QuakeStep()
{
	auto& view = *pView;
	//晃动
	if (quake2 > 0)
	{
		quake2--;
		camera_offx += Random(-5, 5);
		camera_offy += Random(-3, 3);
	}
	else if (quake > 0)
	{
		camera_offx += Random(-1, 1);
		camera_offy += Random(-1, 1);
		quake--;
	}
}

void MyCamera::ResetQuake()
{
	quake = quake2 = 0;
}

void MyCamera::SetLocalCamera(std::weak_ptr<Entity> localTarget, float focusTimes)
{
	target_local = localTarget;
	focusTimes_local = focusTimes;
}

void MyCamera::UnsetLocalCamera(std::weak_ptr<Entity> e)
{
	auto we = e.lock();
	auto wtarget_local = target_local.lock();
	if (we == wtarget_local)
		target_local.reset();
}

bool MyCamera::LocalCameraStep()
{
	auto wtarget_local = target_local.lock();
	if (!wtarget_local)
		return false;
	float usingfocusTimes = max(1, focusTimes_local);

	if (bLockCamera)
	{
		camera_last_offx = camera_offx;
		camera_last_offy = camera_offy;
		return true;
	}
	auto& view = *pView;
	int mapW = *pMapW, mapH = *pMapH;
	camera_last_offx = camera_offx;
	camera_last_offy = camera_offy;
	camera_offx = quakeCenterX;
	camera_offy = quakeCenterY;

	float t1x, t1y;
	wtarget_local->GetCameraPos(&t1x, &t1y);
	float dx = t1x - view.window_w / view.scale / 2;
	float dy = t1y - view.window_h / view.scale / 2;
	camera_offx += (dx - camera_offx) / focusTimes;
	camera_offy += (dy - camera_offy) / focusTimes;
	//屏幕区域限制
	float dw = view.window_w / (view.grid_w * view.scale);
	float dh = view.window_h / (view.grid_h * view.scale);
	if (camera_offx > view.grid_w * (mapW - dw))
		camera_offx = view.grid_w * (mapW - dw);
	if (camera_offy > view.grid_h * (mapH - dh) - 8)//不让23高度的房间上下晃动
		camera_offy = view.grid_h * (mapH - dh) - 8;
	if (camera_offx < 0)
		camera_offx = 0;
	if (camera_offy < 0)
		camera_offy = 0;
	//如果显示范围比房间要大
	if (mapW * view.grid_w * view.scale < view.window_w)
		camera_offx = -(view.window_w - mapW * view.grid_w * view.scale) / 2 / view.scale;
	if (mapH * view.grid_h * view.scale < view.window_h)
		camera_offy = -(view.window_h - mapH * view.grid_h * view.scale) / 2 / view.scale;
	quakeCenterX = camera_offx;
	quakeCenterY = camera_offy;
	QuakeStep();
	return true;
}
