#include "PauseMenuSystem.hpp"
#include "../EditorApp.hpp"
#include "../components/StartupMenu.hpp"
#include "SaveLoadDialog.hpp"
#include <flecs.h>
#include <functional>
#include <imgui.h>
#include <OgreFontManager.h>
#include <OgreImGuiOverlay.h>
#include <OgreLogManager.h>
#include <OgreOverlayManager.h>
#include <OgreRoot.h>
#include <vector>

PauseMenuSystem::PauseMenuSystem()
	: m_editorApp(nullptr)
{
}

PauseMenuSystem::~PauseMenuSystem() = default;

PauseMenuSystem &PauseMenuSystem::getInstance()
{
	static PauseMenuSystem instance;
	return instance;
}

void PauseMenuSystem::init(EditorApp *editorApp)
{
	m_editorApp = editorApp;
}

void PauseMenuSystem::ensureFontLoaded(const Ogre::String &fontName,
				       float fontSize)
{
	if (m_fontLoaded && m_currentFontName == fontName &&
	    m_currentFontSize == fontSize)
		return;

	Ogre::ImGuiOverlay *overlay = m_editorApp->getImGuiOverlay();
	if (!overlay)
		return;

	Ogre::FontPtr font;
	try {
		if (Ogre::FontManager::getSingleton().resourceExists(
			    "PauseMenuFont", "General")) {
			Ogre::FontManager::getSingleton().remove("PauseMenuFont",
								 "General");
		}
		font = Ogre::FontManager::getSingleton().create("PauseMenuFont",
								"General");
		font->setType(Ogre::FontType::FT_TRUETYPE);
		font->setSource(fontName);
		font->setTrueTypeSize(fontSize);
		font->setTrueTypeResolution(75);
		font->addCodePointRange(Ogre::Font::CodePointRange(32, 255));
		font->load();
	} catch (...) {
		Ogre::LogManager::getSingleton().logMessage(
			"PauseMenuSystem: Failed to load font " + fontName);
		m_menuFont = nullptr;
		m_fontLoaded = false;
		return;
	}

	m_menuFont = overlay->addFont("PauseMenuFont", "General");
	m_currentFontName = fontName;
	m_currentFontSize = fontSize;
	m_fontLoaded = true;
}

void PauseMenuSystem::prepareFont()
{
	if (!m_editorApp)
		return;

	flecs::world *world = m_editorApp->getWorld();
	if (!world)
		return;

	flecs::entity menuEntity = flecs::entity::null();
	world->query<StartupMenuComponent>().each(
		[&](flecs::entity e, StartupMenuComponent &) {
			if (!menuEntity.is_alive())
				menuEntity = e;
		});

	if (menuEntity.is_alive()) {
		auto &sm = menuEntity.get<StartupMenuComponent>();
		Ogre::LogManager::getSingleton().logMessage(
			"PauseMenuSystem: Using font=" + sm.fontName +
			", size=" + Ogre::StringConverter::toString(sm.fontSize));
		ensureFontLoaded(sm.fontName, sm.fontSize);
	} else {
		Ogre::LogManager::getSingleton().logMessage(
			"PauseMenuSystem: No StartupMenuComponent found, using defaults");
		ensureFontLoaded("Kenney Bold.ttf", 36.0f);
	}
}

void PauseMenuSystem::update(float deltaTime)
{
	(void)deltaTime;

	if (!m_editorApp || m_editorApp->getGamePlayState() !=
				    EditorApp::GamePlayState::Paused)
		return;

	renderMenu();
}

void PauseMenuSystem::renderMenu()
{
	ImVec2 size = ImGui::GetMainViewport()->Size;
	ImGui::SetNextWindowPos(ImVec2(0, 0), ImGuiCond_Always);
	ImGui::SetNextWindowSize(ImVec2(size.x, size.y), ImGuiCond_Always);

	ImVec4 bgColor = ImVec4(0.0f, 0.0f, 0.0f, 0.85f);
	ImGui::PushStyleColor(ImGuiCol_WindowBg, bgColor);

	ImGui::Begin("PauseMenu", nullptr,
		     ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoDecoration |
			     ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove |
			     ImGuiWindowFlags_NoCollapse |
			     ImGuiWindowFlags_NoFocusOnAppearing);

	if (m_menuFont)
		ImGui::PushFont(m_menuFont);

	struct ButtonData {
		const char *label;
		std::function<void()> action;
	};

	std::vector<ButtonData> buttons;
	buttons.push_back({ "RETURN TO GAME", [&]() {
				   m_editorApp->setGamePlayState(
					   EditorApp::GamePlayState::Playing);
			   } });
	buttons.push_back({ "SAVE GAME", [&]() {
				   SaveLoadDialog::show(m_editorApp,
							SaveLoadDialog::Mode::Save);
			   } });
	buttons.push_back({ "OPTIONS", [&]() {
				   Ogre::LogManager::getSingleton().logMessage(
					   "Options not implemented");
			   } });
	buttons.push_back({ "QUIT", [&]() {
				   Ogre::Root::getSingleton().queueEndRendering();
			   } });

	float buttonWidth = 0.0f;
	float buttonsHeight = 0.0f;
	float extraPixels = 20.0f;
	for (const auto &b : buttons) {
		ImVec2 textSize = ImGui::CalcTextSize(b.label);
		float bwidth = textSize.x +
			       (ImGui::GetStyle().FramePadding.x * 2.0f) +
			       extraPixels;
		float bheight =
			textSize.y + (ImGui::GetStyle().FramePadding.y * 2.0f);
		if (buttonWidth < bwidth)
			buttonWidth = bwidth;
		buttonsHeight += bheight + ImGui::GetStyle().ItemSpacing.y;
	}
	if (!buttons.empty())
		buttonsHeight -= ImGui::GetStyle().ItemSpacing.y;

	ImGui::SetCursorPosY((size.y - buttonsHeight) * 0.5f);
	for (const auto &b : buttons) {
		ImGui::SetCursorPosX((size.x - buttonWidth) * 0.5f);
		if (ImGui::Button(b.label, ImVec2(buttonWidth, 0)))
			b.action();
	}

	if (m_menuFont)
		ImGui::PopFont();

	SaveLoadDialog::render(m_editorApp);

	ImGui::End();
	ImGui::PopStyleColor();
}
