#include "SaveLoadDialog.hpp"
#include "../EditorApp.hpp"
#include "SaveLoadSystem.hpp"
#include <OgreLogManager.h>
#include <imgui.h>
#include <algorithm>

/* ===================================================================== */
/*  Static state                                                         */
/* ===================================================================== */

bool SaveLoadDialog::s_open = false;
SaveLoadDialog::Mode SaveLoadDialog::s_mode = SaveLoadDialog::Mode::Save;
std::vector<SaveLoadSystem::SaveInfo> SaveLoadDialog::s_saves;
int SaveLoadDialog::s_selectedIndex = -1;
char SaveLoadDialog::s_slotNameInput[256] = {};
bool SaveLoadDialog::s_needsRefresh = true;
bool SaveLoadDialog::s_showDeleteConfirm = false;
int SaveLoadDialog::s_deleteIndex = -1;

/* ===================================================================== */
/*  Public API                                                           */
/* ===================================================================== */

void SaveLoadDialog::show(EditorApp *editorApp, Mode mode)
{
	s_open = true;
	s_mode = mode;
	s_needsRefresh = true;
	s_selectedIndex = -1;
	s_showDeleteConfirm = false;
	s_deleteIndex = -1;
	memset(s_slotNameInput, 0, sizeof(s_slotNameInput));

	if (mode == Mode::Save) {
		/* Auto-suggest a slot name */
		auto saves = SaveLoadSystem::listSaves();
		int nextNum = (int)saves.size() + 1;
		snprintf(s_slotNameInput, sizeof(s_slotNameInput), "Save %d",
			 nextNum);
	}
}

bool SaveLoadDialog::isOpen()
{
	return s_open;
}

void SaveLoadDialog::close()
{
	s_open = false;
}

/* ===================================================================== */
/*  Internals                                                            */
/* ===================================================================== */

void SaveLoadDialog::refreshSaveList()
{
	s_saves = SaveLoadSystem::listSaves();
	s_needsRefresh = false;
}

void SaveLoadDialog::doSave(EditorApp *editorApp)
{
	if (!editorApp)
		return;
	std::string slotName(s_slotNameInput);
	/* Trim whitespace */
	slotName.erase(slotName.begin(),
		       std::find_if(slotName.begin(), slotName.end(),
				    [](unsigned char ch) {
					    return !std::isspace(ch);
				    }));
	slotName.erase(std::find_if(slotName.rbegin(), slotName.rend(),
				    [](unsigned char ch) {
					    return !std::isspace(ch);
				    }).base(),
		       slotName.end());
	if (slotName.empty()) {
		Ogre::LogManager::getSingleton().logMessage(
			"SaveLoadDialog: cannot save with empty name");
		return;
	}

	std::string path = SaveLoadSystem::generateSaveFilename();
	editorApp->saveGame(path, slotName);
	s_open = false;
}

void SaveLoadDialog::doLoad(EditorApp *editorApp, int index)
{
	if (!editorApp || index < 0 || index >= (int)s_saves.size())
		return;
	editorApp->loadGame(s_saves[index].path);
	s_open = false;
}

void SaveLoadDialog::render(EditorApp *editorApp)
{
	if (!s_open)
		return;

	if (s_needsRefresh)
		refreshSaveList();

	const char *title = (s_mode == Mode::Save) ? "Save Game" : "Load Game";
	ImGui::OpenPopup(title);

	ImVec2 center = ImGui::GetMainViewport()->GetCenter();
	ImGui::SetNextWindowPos(center, ImGuiCond_Appearing,
				ImVec2(0.5f, 0.5f));
	ImGui::SetNextWindowSize(ImVec2(500, 400), ImGuiCond_Appearing);

	if (ImGui::BeginPopupModal(title, &s_open,
				   ImGuiWindowFlags_NoResize)) {
		/* --- Slot name input (save mode only) --- */
		if (s_mode == Mode::Save) {
			ImGui::Text("Save Name:");
			ImGui::SameLine();
			ImGui::InputText("##SlotName", s_slotNameInput,
					 sizeof(s_slotNameInput));
			ImGui::Separator();
		}

		/* --- Save list --- */
		ImGui::Text("Existing Saves:");
		if (ImGui::BeginChild("SaveList", ImVec2(0, -60),
				      ImGuiChildFlags_Borders)) {
			for (int i = 0; i < (int)s_saves.size(); ++i) {
				const auto &save = s_saves[i];
				bool isSelected = (s_selectedIndex == i);

				ImGui::PushID(i);
				if (ImGui::Selectable(save.slotName.c_str(),
						      isSelected)) {
					s_selectedIndex = i;
					if (s_mode == Mode::Save) {
						snprintf(s_slotNameInput,
							 sizeof(s_slotNameInput), "%s",
							 save.slotName.c_str());
					}
				}
				ImGui::PopID();

				if (isSelected)
					ImGui::SetItemDefaultFocus();

				ImGui::SameLine();
				ImGui::TextDisabled("[%s] %s", save.timestamp.c_str(),
						    save.baseScene.c_str());
			}
			if (s_saves.empty()) {
				ImGui::TextDisabled("No saves found.");
			}
		}
		ImGui::EndChild();

		/* --- Delete confirmation --- */
		if (s_showDeleteConfirm && s_deleteIndex >= 0) {
			ImGui::TextColored(
				ImVec4(1.0f, 0.3f, 0.3f, 1.0f),
				"Are you sure you want to delete '%s'?",
				s_saves[s_deleteIndex].slotName.c_str());
			if (ImGui::Button("Yes, Delete")) {
				SaveLoadSystem::deleteSave(
					s_saves[s_deleteIndex].path);
				s_showDeleteConfirm = false;
				s_deleteIndex = -1;
				s_needsRefresh = true;
			}
			ImGui::SameLine();
			if (ImGui::Button("Cancel")) {
				s_showDeleteConfirm = false;
				s_deleteIndex = -1;
			}
			ImGui::Separator();
		}

		/* --- Action buttons --- */
		if (s_mode == Mode::Save) {
			if (ImGui::Button("Save", ImVec2(120, 0))) {
				doSave(editorApp);
			}
			ImGui::SameLine();
		} else {
			if (ImGui::Button("Load", ImVec2(120, 0)) &&
			    s_selectedIndex >= 0) {
				doLoad(editorApp, s_selectedIndex);
			}
			ImGui::SameLine();
		}

		if (s_selectedIndex >= 0 && !s_showDeleteConfirm) {
			if (ImGui::Button("Delete", ImVec2(120, 0))) {
				s_showDeleteConfirm = true;
				s_deleteIndex = s_selectedIndex;
			}
			ImGui::SameLine();
		}

		ImGui::SetCursorPosX(
			ImGui::GetWindowWidth() - 120 -
			ImGui::GetStyle().WindowPadding.x);
		if (ImGui::Button("Cancel", ImVec2(120, 0))) {
			s_open = false;
		}

		ImGui::EndPopup();
	}
}
