#include "UiBossHpBar.h"
#include "Entity.h"
#include "EntityRes.h"
#include "main.h"
void UiBossHpBar::Init(MyDX11Renderer* pRenderer, MyView* pView)
{
	this->pRenderer = pRenderer;
	this->pView = pView;
	texture_bossHpBar = GetSysTexture(L"bosshpbar");
	texture_bossdmgbar = GetSysTexture(L"bossdmgbar");
}

void UiBossHpBar::Draw()
{
	auto wboss = boss.lock();
	if (wboss == nullptr)
		return;
	DrawAll(wboss->hp);
}

void UiBossHpBar::Step()
{
	auto wboss = boss.lock();
	if (wboss == nullptr)
		return;
	if (wboss->hp == 0)
		Reset();
	//检测掉血
	if (last_hp > 0 && wboss->hp < last_hp)
	{
		//拆解成多段掉血
		int hpSrc = last_hp;
		int hpDst = wboss->hp;
		int temp = 0;
		//分解到直到同一行
		while (!HpInSameLine(hpSrc, hpDst))
		{
			temp = hpSrc / lineSize * lineSize;
			if (temp == hpSrc)
				temp -= lineSize;
			SetDamageAni(hpSrc, temp);
			hpSrc = temp;
		}
		SetDamageAni(hpSrc, hpDst);
		last_hp = wboss->hp;
	}
	if (bossHpbar_damageList.empty())
		return;
	//伤害动画流逝
	for (auto& b : bossHpbar_damageList)
		if (b.alpha > 0)
		{
			b.alpha -= dmgSpeed;
			if (b.alpha < 0)
				b.alpha = 0;
		}
}

void UiBossHpBar::BossReady(std::weak_ptr<Entity> boss, int lineSize)
{
	this->boss = boss;
	this->lineSize = lineSize;
	auto wboss = boss.lock();
	if (wboss)
	{
		last_hp = wboss->hp;
	}
}

void UiBossHpBar::Reset()
{
	boss.reset();
	lineSize = 0;
	bossHpbar_damageList.clear();
	dmgSpeed = 4;
	last_hp = 0;
}

bool UiBossHpBar::InBossFight()
{
	return !boss.expired();
}

void UiBossHpBar::DrawBar(int c, float hpPercent, bool last)
{
	auto& view = *pView;
	MyRect src, dst, clip;
	float srcX, srcY, srcW, srcH;
	float dstX, dstY, dstW, dstH;
	float clipX, clipY, clipW, clipH;
	if (last)
	{
		srcX = 0;
		srcH = 9;
		srcY = c * srcH;
		srcW = 384;
		dstW = srcW * view.scale;
		dstH = srcH * view.scale;
		dstX = (view.window_w - dstW) / 2;
		dstY = view.window_h - 20 * view.scale;
		src.Set1(srcX, srcY, srcW, srcH);
		dst.Set1(dstX, dstY, dstW, dstH);
		pRenderer->SetTPenDraw(texture_bossHpBar->pSRV);
		pRenderer->AddRenderCopy(&src, &dst);
		pRenderer->DrawRenderCopy();

		srcX = 48;
		srcY += 63;
		srcW = 336;
		dstX += srcX * view.scale;
		dstW = srcW * view.scale;
		clipX = dstX;
		clipY = dstY;
		clipW = dstW;
		clipH = dstH;
		clipW *= hpPercent;
		src.Set1(srcX, srcY, srcW, srcH);
		dst.Set1(dstX, dstY, dstW, dstH);
		clip.Set1(clipX, clipY, clipW, clipH);
		pRenderer->SetScissorRect(&clip);
		pRenderer->SetTPenDraw(texture_bossHpBar->pSRV);
		pRenderer->AddRenderCopy(&src, &dst);
		pRenderer->DrawRenderCopy();
		pRenderer->SetScissorRect(nullptr);

	}
	else
	{
		clipX = (view.window_w - 384 * view.scale) / 2;
		clipY = view.window_h - 20 * view.scale;
		clipW = 48 * view.scale + 336 * view.scale * hpPercent;
		clipH = 9 * view.scale;
		clip.Set1(clipX, clipY, clipW, clipH);
		pRenderer->SetScissorRect(&clip);

		srcX = 0;
		srcH = 9;
		srcY = c * srcH;
		srcW = 384;
		dstW = srcW * view.scale;
		dstH = srcH * view.scale;
		dstX = (view.window_w - dstW) / 2;
		dstY = view.window_h - 20 * view.scale;
		src.Set1(srcX, srcY, srcW, srcH);
		dst.Set1(dstX, dstY, dstW, dstH);
		pRenderer->SetTPenDraw(texture_bossHpBar->pSRV);
		pRenderer->AddRenderCopy(&src, &dst);
		pRenderer->DrawRenderCopy();

		srcX = 48;
		srcY += 63;
		srcW = 336;
		dstX += srcX * view.scale;
		dstW = srcW * view.scale;
		src.Set1(srcX, srcY, srcW, srcH);
		dst.Set1(dstX, dstY, dstW, dstH);
		pRenderer->SetTPenDraw(texture_bossHpBar->pSRV);
		pRenderer->AddRenderCopy(&src, &dst);
		pRenderer->DrawRenderCopy();
		pRenderer->SetScissorRect(nullptr);
	}
}

void UiBossHpBar::DrawDmgBar(float percentSrc, float percentDst, Uint8 alpha)
{
	auto& view = *pView;
	MyRect src, dst, clip;
	float srcX, srcY, srcW, srcH;
	float dstX, dstY, dstW, dstH;
	float clipX, clipY, clipW, clipH;

	clipX = (view.window_w - 384 * view.scale) / 2 + ((48 + 336 * percentSrc) * view.scale);
	clipY = view.window_h - 20 * view.scale;
	clipW = (336 * view.scale * percentDst) - (336 * view.scale * percentSrc);
	clipH = 9 * view.scale;
	clip.Set1(clipX, clipY, clipW, clipH);
	pRenderer->SetScissorRect(&clip);

	srcW = 336;
	srcH = 9;
	srcX = srcY = 0;

	dstW = srcW * view.scale;
	dstH = srcH * view.scale;
	dstX = (view.window_w - 384 * view.scale) / 2 + 48 * view.scale;
	dstY = clipY;
	src.Set1(srcX, srcY, srcW, srcH);
	dst.Set1(dstX, dstY, dstW, dstH);
	pRenderer->SetTPenDraw(texture_bossdmgbar->pSRV);
	pRenderer->AddRenderCopy(&src, &dst, RGBA(0xff, 0xff, 0xff, alpha));
	pRenderer->DrawRenderCopy();
	pRenderer->SetScissorRect(nullptr);
}

void UiBossHpBar::DrawNumLine(int numLine)
{
	auto& view = *pView;
	MyRect src, dst;
	float srcX, srcY, srcW, srcH;
	float dstX, dstY, dstW, dstH;

	char num[MAX_PATH];
	sprintf_s(num, "%d", numLine);
	int len = strlen(num);
	int begin = len * 4;
	const char* ch = num;

	srcY = 75;
	srcW = 3;
	srcH = 5;
	dstW = srcW * view.scale;
	dstH = srcH * view.scale;
	int dx = (view.window_w - 384 * view.scale) / 2;
	int time = 0;
	pRenderer->SetTPenDraw(texture_bossHpBar->pSRV);
	for (int i = 0; i < len; i++)
	{
		srcX = (ch[i] - '0') * 3;
		dstX = dx + (36 + time + begin) * view.scale;
		dstY = view.window_h - 17 * view.scale;
		src.Set1(srcX, srcY, srcW, srcH);
		dst.Set1(dstX, dstY, dstW, dstH);
		pRenderer->AddRenderCopy(&src, &dst);
		time += 4;
	}
	pRenderer->DrawRenderCopy();
}

void UiBossHpBar::DrawDamageAni()
{
	if (bossHpbar_damageList.empty())
		return;
	float percentSrc, percentDst;
	for (auto& b : bossHpbar_damageList)
	{
		if (b.alpha == 0)
			continue;
		HpCalcPercent(&b, &percentSrc, &percentDst);
		if (percentSrc > percentDst)
			percentSrc = 0;
		DrawDmgBar(percentSrc, percentDst, b.alpha);
	}
}

void UiBossHpBar::DrawAll(int hp)
{
	//绘制Boss血条
	int numLine = H2L(hp);
	float hpPercent = H2P(hp);
	if (numLine <= 1)
		DrawBar((numLine - 1) % 7, hpPercent, true);
	else
		DrawBar((numLine - 2) % 7, 1, true);
	DrawBar((numLine - 1) % 7, hpPercent);
	//绘制血条数
	if (hp > 0)
		DrawNumLine(numLine);
	else
		DrawNumLine(0);
	//绘制伤害动画
	DrawDamageAni();
}

float UiBossHpBar::H2P(float v) const
{
	if (v <= 0)
		return 0;
	int lines = v / lineSize;
	if (v - lines * lineSize == 0)
		return 1;
	else
		return (v - lines * lineSize) / (float)lineSize;
}

int UiBossHpBar::H2L(float v) const
{
	if (v <= 0)
		return 1;
	int hp = v;
	if (hp)
		return  hp % lineSize == 0 ? hp / lineSize : (hp / lineSize + 1);
	else
		return 1;
}

void UiBossHpBar::HpCalcPercent(BossHpBarDamageUnit* b, float* out_percentSrc, float* out_percentDst)
{
	*out_percentSrc = H2P(b->to);
	*out_percentDst = H2P(b->from);
}

void UiBossHpBar::SetDamageAni(int hpFrom, int hpTo)
{
	auto wboss = boss.lock();
	if (wboss == nullptr)
		return;
	BossHpBarDamageUnit b;
	b.alpha = 255;
	if (hpTo <= lineSize)
		b.c = 0;
	else
		b.c = H2L(hpTo);
	b.from = hpFrom;
	b.to = hpTo;
	bossHpbar_damageList.push_back(b);
}

bool UiBossHpBar::HpInSameLine(int hpSrc, int hpDst)
{
	if (hpSrc / lineSize == hpDst / lineSize)
		return true;
	if (hpSrc % lineSize == 0 && hpSrc - hpDst <= lineSize)
		return true;
	return false;
}
