#include "client/render/gui/GameMenu.h"
#include "client/render/gui/imgui/imgui.h"
#include "client/render/gui/ImGuiTeamColor.h"

#include "client/render/WorldRenderer.h"

#include "client/Client.h"
#include "server/Lobby.h"

namespace td {
namespace gui {

GameMenu::GameMenu(client::Client* client) : GuiWidget(client), m_SummonMenu(std::make_unique<SummonMenu>(client)) {
	m_Client->GetGame().BindListener(this);
}

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

	if (GetClient()->GetGame().GetGameState() == td::game::GameState::Lobby) {
		ImGui::Begin("Lobby");

		ShowTPS();
		ShowPlayers();
		ShowLobbyProgress();
		ShowTeamSelection();
		ImGui::Separator();
		DisconnectButton();

		ImGui::End();
	}
	if (GetClient()->GetGame().GetGameState() == td::game::GameState::Game) {
		ImGui::Begin("Game");

		ShowTPS();
		ShowStats();
		ShowPlayers();
		ImGui::Separator();
		DisconnectButton();

		ImGui::End();

		m_SummonMenu->Render();
	}
}

void GameMenu::ShowPlayers() {
	if (ImGui::TreeNode(std::string("Players (" + std::to_string(GetClient()->GetGame().GetPlayers().size()) + ")##player_list").c_str())) {
		for (auto pair : GetClient()->GetGame().GetPlayers()) {
			const td::game::Player& player = pair.second;
			ImGui::PushStyleColor(ImGuiCol_Text, render::GetImGuiTeamColor(player.GetTeamColor()));
			ImGui::Text("%s", player.GetName().c_str());
			ImGui::PopStyleColor();
		}
		ImGui::TreePop();
	}
}

void GameMenu::ShowTeamSelection() {
	if (GetClient()->GetGame().GetPlayer() == nullptr)
		return;
	td::game::TeamColor playerTeam = GetClient()->GetGame().GetPlayer()->GetTeamColor();

	if (ImGui::Button(std::string((playerTeam == td::game::TeamColor::Red ? "Leave" : "Join") + std::string(" Red Team")).c_str())) {
		if (playerTeam == td::game::TeamColor::Red)
			GetClient()->SelectTeam(td::game::TeamColor::None);
		else
			GetClient()->SelectTeam(td::game::TeamColor::Red);
	}
	ImGui::SameLine();
	if (ImGui::Button(std::string((playerTeam == td::game::TeamColor::Blue ? "Leave" : "Join") + std::string(" Blue Team")).c_str())) {
		if (playerTeam == td::game::TeamColor::Blue)
			GetClient()->SelectTeam(td::game::TeamColor::None);
		else
			GetClient()->SelectTeam(td::game::TeamColor::Blue);
	}
}

void GameMenu::ShowLobbyProgress() {
	const int timePassed = server::Lobby::LobbyWaitingTime - GetClient()->GetGame().GetLobbyTime();
	const float progress = (float)timePassed / (float)(server::Lobby::LobbyWaitingTime);
	if (progress > 0 && progress < 1) {
		ImGui::ProgressBar(progress, ImVec2(0.0f, 0.0f), std::string(std::to_string(GetClient()->GetGame().GetLobbyTime() / 1000) + "s").c_str());
		ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
		ImGui::Text("Time Remaining");
	} else {
		ImGui::Text("Waiting for players ...\n");
	}
}

void GameMenu::ShowTPS() {
	ImGui::Text("Server TPS : %.1f", GetClient()->GetConnexion().GetServerTPS());
	ImGui::Text("Server MSPT : %i", (int)GetClient()->GetConnexion().GetServerMSPT());
	ImGui::Text("Server Ping : %i", GetClient()->GetConnexion().GetServerPing());
}

void GameMenu::ShowStats() {
	ImGui::Text("Gold : %i", GetClient()->GetGame().GetPlayer()->GetGold());
	ImGui::Text("EXP: %i", GetClient()->GetGame().GetPlayer()->GetExp());
}

void GameMenu::DisconnectButton() {
	if (ImGui::Button("Disconnect")) {
		m_Client->CloseConnection();
	}
}

void GameMenu::OnGameBegin() {
	m_SummonMenu->SetCooldown(10);
}

} // namespace gui
} // namespace td
