#include "client/gui/OptionsMenu.h"

#include "blitz/misc/Format.h"
#include "blitz/misc/Log.h"
#include "client/Client.h"
#include "client/display/InputManager.h"
#include "client/gui/FPSMenu.h"
#include <SDL2/SDL.h>
#include <imgui.h>

namespace blitz {
namespace gui {

static std::string ActionNames[kaMax] = {
	"Avancer",
	"Reculer",
	"Droite",
	"Gauche",
	"Fenetre Admin",
};





static std::string GetActionName(KeyAction action) {
	return ActionNames[action];
}





static std::string GetImGuiKeyName(int key) {
	if (key == ImGuiKey_None) {
		return "?";
	}
	return ImGui::GetKeyName(static_cast<ImGuiKey>(key));
}





void OptionsMenu::HotkeyBindingButton() {
	for (std::size_t i = 0; i < m_Client->GetConfig()->GetKeys().size(); i++) {
		if (ImGui::Button(utils::Format("%s##%i", GetKeyActionCodeName(KeyAction(i)).c_str(), i).c_str())) {
			m_IsKeyPopupOpen = true;
			m_CurrentAction = KeyAction(i);
			ImGui::OpenPopup("Changer de touche");
		}
		ImGui::SameLine();
		ImGui::Text("%s", GetActionName(KeyAction(i)).c_str());
	}
}





void OptionsMenu::HotkeyBindingPopUp() {
	// Always center this window when appearing
	ImVec2 center = ImGui::GetMainViewport()->GetCenter();
	ImGui::SetNextWindowPos(center, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));

	if (ImGui::BeginPopupModal("Changer de touche", NULL, ImGuiWindowFlags_AlwaysAutoResize)) {
		ImGui::Text("Entrez la touche pour : ");
		ImGui::SameLine();
		ImGui::TextColored(ImVec4(1.0f, 1.0f, 0.0f, 1.0f), "%s", GetActionName(m_CurrentAction).c_str());
		ImGui::Text("Si vous voulez annulez cette action, appuyez sur Echap !");
		ImGui::Dummy({0, 40});
		ImGui::Text("La touche pour ");
		ImGui::TextColored(ImVec4(1.0f, 1.0f, 0.0f, 1.0f), "%s", GetActionName(m_CurrentAction).c_str());
		ImGui::SameLine();
		ImGui::Text(" est : ");
		ImGui::SameLine();
		ImGui::TextColored(ImVec4(1.0f, 1.0f, 0.0f, 1.0f), "%s", GetKeyActionCodeName(m_CurrentAction).c_str());

		if (m_KeyPopupShouldClose && m_Timer.Update(static_cast<std::uint64_t>(ImGui::GetIO().DeltaTime * 1000.0f))) {
			m_KeyPopupShouldClose = false;
			m_IsKeyPopupOpen = false;
			ImGui::CloseCurrentPopup();
		}

		ImGui::EndPopup();
	}
}





OptionsMenu::OptionsMenu(GuiWidget* parent, Client* client) :
	GuiWidget(parent, client), m_IsKeyPopupOpen(false), m_KeyPopupShouldClose(false) {
	AddWidget(std::make_unique<FPSMenu>(this, client));
	InputManager::BindKeyDownCallback(std::bind(&OptionsMenu::OnKeyEvent, this, std::placeholders::_1));

	m_ShowFPS = m_Client->GetConfig()->IsFPSDisplayEnabled();
	m_SubWidgets[0]->SetState(m_ShowFPS);

	m_VSync = m_Client->GetConfig()->IsVSyncEnabled();
	SDL_GL_SetSwapInterval(m_VSync);
}





void OptionsMenu::OnKeyEvent(int key) {
	if (!m_IsKeyPopupOpen)
		return;

	if (key == ImGuiKey_Escape) {
		m_KeyPopupShouldClose = true;
		ImGui::GetIO().ClearInputKeys();  // releases the Escape key
		return;
	}

	m_Client->GetConfig()->GetKeys()[static_cast<std::size_t>(m_CurrentAction)] = key;
	m_KeyPopupShouldClose = true;

	utils::LOG(std::to_string(key));
}





std::string OptionsMenu::GetKeyActionCodeName(KeyAction act) {
	return GetImGuiKeyName(static_cast<int>(m_Client->GetConfig()->GetKeys()[act]));
}





void OptionsMenu::Render() {
	GuiWidget::Render();

	if (ImGui::IsKeyPressed(ImGuiKey_Escape) && m_Client->IsConnected() && !IsEnabled()) {
		Enable();
		ImGui::GetIO().ClearInputKeys();  // releases the Escape key
		InputManager::GrabMouse(false);
	}

	if (!IsEnabled())
		return;

	const static ImVec2 buttonSize = {300, 60};
	auto displaySize = ImGui::GetIO().DisplaySize;
	const static int paddingHeight = 40;
	const static int startPos = 15;

	SetNextWindowFullScreen();

	ImGui::Begin("OptionsWindow", nullptr, GetWindowFullScreenFlags());
	{
		ImGui::SetCursorPosX(startPos);

		ImGui::Text("Options");

		ImGui::NewLine();

		ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_None;
		if (ImGui::BeginTabBar("OPTIONS", tab_bar_flags)) {
			if (ImGui::BeginTabItem("CONTROLES")) {
				HotkeyBindingButton();
				HotkeyBindingPopUp();
				float sensitivity = m_Client->GetConfig()->GetMouseSpeed() * 200.0f;
				ImGui::SetNextItemWidth(300.0f);
				if (ImGui::DragFloat("Sensibilite", &sensitivity, 0.005f, 0.001f, 10.0f, "%.3f")) {
					sensitivity = std::clamp(sensitivity, 0.001f, 10.0f);
					m_Client->GetConfig()->SetMouseSpeed(sensitivity / 200.0f);
				}
				ImGui::EndTabItem();
			}
			if (ImGui::BeginTabItem("GRAPHISMES")) {
				if (ImGui::Checkbox("AFFICHER LES FPS", &m_ShowFPS)) {
					m_SubWidgets[0]->SetState(m_ShowFPS);
					m_Client->GetConfig()->SetFPSDisplay(m_ShowFPS);
				}

				if (ImGui::Checkbox("VSync", &m_VSync)) {
					SDL_GL_SetSwapInterval(m_VSync);
					m_Client->GetConfig()->SetVSync(m_VSync);
				}
				ImGui::EndTabItem();
			}
			if (ImGui::BeginTabItem("AUDIO")) {
				ImGui::EndTabItem();
			}
			ImGui::EndTabBar();

			if (m_Client->IsConnected()) {
				ImGui::SetCursorPosX(displaySize.x - buttonSize.x - paddingHeight);
				ImGui::SetCursorPosY(displaySize.y - 2 * buttonSize.y - paddingHeight);
			} else {
				ImGui::SetCursorPosX(displaySize.x - buttonSize.x - paddingHeight);
				ImGui::SetCursorPosY(displaySize.y - buttonSize.y - paddingHeight);
			}
			ImGui::BeginGroup();
			{
				if (ImGui::Button("Retour", buttonSize) || ImGui::IsKeyPressed(ImGuiKey_Escape)) {
					Disable();
					if (m_Client->IsConnected()) {
						InputManager::GrabMouse(true);
					} else {
						m_Parent->Enable();
					}
				}
				if (m_Client->IsConnected()) {
					if (ImGui::Button("Quitter la partie", buttonSize)) {
						m_Client->Disconnect();
						Disable();
						m_Parent->Enable();
					}
				}
			}
			ImGui::EndGroup();
		}
	}
	ImGui::End();
}

}  // namespace gui
}  // namespace blitz
