#include "client/gui/Hud.h"

#include "client/Client.h"
#include "client/game/ClientGame.h"
#include "client/gui/ColorFulText.h"
#include "client/gui/GuiWidget.h"
#include "client/render/loader/TextureLoader.h"
#include <imgui.h>

namespace blitz {
namespace gui {

Hud::Hud(GuiWidget* parent, Client* client) : GuiWidget(parent, client) {
	m_GunTexture = TextureLoader::LoadGLTexture("fingergun.png");
	m_JPTexture = TextureLoader::LoadGLTexture("jp.png");
}

void Hud::Draw(const char* title, bool* p_open) {

	SetNextWindowFullScreen();
	ImGui::Begin(title, nullptr, GetWindowFullScreenFlags() | ImGuiWindowFlags_NoInputs);

	auto displaySize = ImGui::GetIO().DisplaySize;

	const static ImVec2 buttonSize = {300, 60};
	const static ImVec2 fingergunSize = {256, 134.5};
	const static ImVec2 jpSize = {256 / 2, 256 / 2};
	const static int paddingHeight = 40;
	const static ImVec2 pvBarPos = {displaySize.x / 2.2f, displaySize.y - 3 * paddingHeight};
	const static ImVec2 progressSize = {100.0f, 30.0f};
	const static ImVec2 currentWeaponPos = {
		displaySize.x - buttonSize.x - 3 * paddingHeight, displaySize.y - buttonSize.y - 1.5f * paddingHeight};
	const static ImVec2 currentWeaponPosImage = {
		displaySize.x - fingergunSize.x - paddingHeight, displaySize.y - fingergunSize.y + 1.0f / 2.5f * paddingHeight};
	ImVec2 spacing = ImGui::GetStyle().ItemInnerSpacing;

	std::string timeFormated = FormatString();
	ImVec2 center = ImGui::GetMainViewport()->GetCenter();
	const float timetextWidth = ImGui::CalcTextSize(timeFormated.c_str()).x;
	const float timetextHeight = ImGui::CalcTextSize(timeFormated.c_str()).y;
	RenderTime(center.x - timetextWidth / 2, timetextHeight / 2);

	ImGui::SetCursorPosX(3 * paddingHeight);
	ImGui::SetCursorPosY(pvBarPos.y - 2 * paddingHeight);
	ImGui::BeginGroup();
	ImGui::Image(reinterpret_cast<ImTextureID>(m_JPTexture), jpSize);

	ImGui::SameLine(0.0f, paddingHeight);

	ImGui::BeginGroup();
	{
		game::Player* player = m_Client->GetGame()->GetPlayerById(m_Client->GetPlayerID());

		if (player) {
			ImGui::Text("PV : %.0f", player->GetHP());

			ImGui::ProgressBar(static_cast<float>(player->GetHP() / 100.0f), progressSize, "");
		}
	}
	ImGui::EndGroup();
	ImGui::EndGroup();

	ImGui::SetCursorPosX(currentWeaponPos.x);
	ImGui::SetCursorPosY(currentWeaponPos.y);
	ImGui::BeginGroup();
	{
		ImGui::Text("FingerGun");
		ImGui::SameLine(0.0f, spacing.x * 50);
		ImGui::Text("3 | 9");

		ImGui::SetCursorPosX(currentWeaponPosImage.x);
		ImGui::SetCursorPosY(currentWeaponPosImage.y);
		ImGui::Image(reinterpret_cast<ImTextureID>(m_GunTexture), fingergunSize);
	}
	ImGui::EndGroup();

	ImGui::End();
}

std::string Hud::FormatString() {
	std::string timeFormated;

	std::uint64_t timeRemaining = m_Client->GetGame()->GetGameStateRemainingTime();

	if (timeRemaining == 0) {
		timeFormated = "En attente de joueurs ...";
	} else {
		timeRemaining += 1000;

		int seconds = timeRemaining / 1000 % 60;
		int minutes = static_cast<int>(timeRemaining) / 1000 / 60;

		timeFormated = (minutes < 10 ? "0" + std::to_string(minutes) : std::to_string(minutes)) + " : " +
					   (seconds < 10 ? "0" + std::to_string(seconds) : std::to_string(seconds));
	}

	return timeFormated;
}

void Hud::RenderTime(float positionX, float positionY) {
	std::string timeFormated = FormatString();

	ImGui::SetCursorPosX(positionX);
	ImGui::SetCursorPosY(positionY);
	ImGui::Text("%s", timeFormated.c_str());
}

void Hud::DrawFinishScreen(bool win) {
	SetNextWindowFullScreen();
	ImGui::Begin("FinishScreen", nullptr, GetWindowFullScreenFlags() | ImGuiWindowFlags_NoInputs);
	{
		std::string timeFormated = FormatString();
		ImVec2 center = ImGui::GetMainViewport()->GetCenter();
		const float timetextWidth = ImGui::CalcTextSize(timeFormated.c_str()).x;

		std::string nextPartyString = "Prochaine partie dans";
		const float nextPartyTextWidth = ImGui::CalcTextSize(nextPartyString.c_str()).x;

		std::string victoryString = "VICTOIRE";
		std::string defeatString = "DEFAITE";

		ImGui::SetCursorPos({center.x - nextPartyTextWidth / 2, (8.5f / 10.0f) * ImGui::GetIO().DisplaySize.y});
		ImGui::Text("%s", nextPartyString.c_str());

		RenderTime(center.x - timetextWidth / 2, (9.0f / 10.0f) * ImGui::GetIO().DisplaySize.y);

		if (!m_Timer.Update(ImGui::GetIO().DeltaTime)) {
			ImGui::SetWindowFontScale(3.0f);
			const float victoryTextWidth = ImGui::CalcTextSize(victoryString.c_str()).x;
			const float defeatTextWidth = ImGui::CalcTextSize(defeatString.c_str()).x;

			if (win) {
				ImGui::SetCursorPos({center.x - victoryTextWidth / 2, center.y - victoryTextWidth / 2});
				ImGui::TextColored(ImVec4(0.0f, 1.0f, 0.0f, 1.0f), "VICTOIRE");
			} else {
				ImGui::SetCursorPos({center.x - defeatTextWidth / 2, center.y - defeatTextWidth / 2});
				ImGui::TextColored(ImVec4(1.0f, 0.0f, 0.0f, 1.0f), "DEFAITE");
			}
			ImGui::SetWindowFontScale(1.0f);
		}
	}
	ImGui::End();
}

void Hud::Render() {
	if (!m_Client->IsConnected())
		return;

	switch (m_Client->GetGame()->GetGameState()) {
		case game::GameState::gsEnd: {
			game::Player* firstPlayer = m_Client->GetGame()->GetLeaderBoard().GetPlayers().front();
			if (!firstPlayer)
				return;
			DrawFinishScreen(firstPlayer->GetID() == m_Client->GetPlayerID());
			break;
		}
		default:
			Draw("Hud Blitz", nullptr);
			break;
	}
}
}  // namespace gui
}  // namespace blitz
