#include "RenderableEditor.hpp"
#include <imgui.h>
#include "../components/Transform.hpp"
#include <OgreResourceGroupManager.h>
#include <algorithm>

char RenderableEditor::s_meshNameBuffer[256] = { 0 };
char RenderableEditor::s_searchBuffer[256] = { 0 };
bool RenderableEditor::s_showMeshBrowser = false;

RenderableEditor::RenderableEditor(Ogre::SceneManager *sceneMgr)
	: m_sceneMgr(sceneMgr)
{
}

void RenderableEditor::scanMeshFiles()
{
	if (m_meshesScanned)
		return;

	m_meshFiles.clear();

	// Get all resource groups
	Ogre::ResourceGroupManager &rgm = Ogre::ResourceGroupManager::getSingleton();
	Ogre::StringVector groups = rgm.getResourceGroups();

	for (const auto &group : groups) {
		// Get file info for this group
		Ogre::FileInfoListPtr fileList = rgm.findResourceFileInfo(group, "*");

		if (fileList) {
			for (const auto &fileInfo : *fileList) {
				const std::string &filename = fileInfo.filename;
				// Check for supported extensions
				if (filename.size() > 5) {
					std::string ext = filename.substr(filename.find_last_of('.') + 1);
					// Convert to lowercase
					std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
					
					if (ext == "mesh" || ext == "glb" || ext == "gltf") {
						m_meshFiles.push_back(filename);
					}
				}
			}
		}
	}

	// Sort and remove duplicates
	std::sort(m_meshFiles.begin(), m_meshFiles.end());
	m_meshFiles.erase(std::unique(m_meshFiles.begin(), m_meshFiles.end()),
			  m_meshFiles.end());

	m_meshesScanned = true;
}

bool RenderableEditor::matchesSearch(const std::string &meshName,
				     const std::string &search)
{
	if (search.empty())
		return true;

	std::string lowerMesh = meshName;
	std::string lowerSearch = search;
	std::transform(lowerMesh.begin(), lowerMesh.end(), lowerMesh.begin(),
		       ::tolower);
	std::transform(lowerSearch.begin(), lowerSearch.end(), lowerSearch.begin(),
		       ::tolower);

	return lowerMesh.find(lowerSearch) != std::string::npos;
}

void RenderableEditor::loadMesh(RenderableComponent &renderable,
				flecs::entity entity)
{
	if (renderable.meshName.empty() || !m_sceneMgr)
		return;

	try {
		// Destroy old entity if exists
		if (renderable.entity) {
			m_sceneMgr->destroyEntity(renderable.entity);
			renderable.entity = nullptr;
		}

		// Create new entity
		renderable.entity = m_sceneMgr->createEntity(renderable.meshName);

		// Attach to transform node if available
		if (entity.has<TransformComponent>()) {
			auto &transform = entity.get_mut<TransformComponent>();
			if (transform.node && renderable.entity) {
				transform.node->attachObject(renderable.entity);
			}
		}
	} catch (const std::exception &e) {
		// Error will be displayed in UI
	}
}

bool RenderableEditor::renderComponent(flecs::entity entity,
				       RenderableComponent &renderable)
{
	bool modified = false;

	if (ImGui::CollapsingHeader("Renderable",
				    ImGuiTreeNodeFlags_DefaultOpen)) {
		ImGui::Indent();

		// Mesh name input
		strcpy(s_meshNameBuffer, renderable.meshName.c_str());
		if (ImGui::InputText("Mesh Name", s_meshNameBuffer,
				     sizeof(s_meshNameBuffer))) {
			renderable.meshName = s_meshNameBuffer;
		}

		ImGui::SameLine();
		if (ImGui::Button("Browse...")) {
			scanMeshFiles();
			s_showMeshBrowser = true;
			strcpy(s_searchBuffer, "");
		}

		// Mesh Browser Popup
		if (s_showMeshBrowser) {
			ImGui::OpenPopup("Mesh Browser");
		}

		if (ImGui::BeginPopupModal("Mesh Browser", &s_showMeshBrowser,
					   ImGuiWindowFlags_AlwaysAutoResize)) {
			ImGui::Text("Search:");
			ImGui::SameLine();
			ImGui::InputText("##search", s_searchBuffer,
					 sizeof(s_searchBuffer));

			ImGui::Separator();

			// Show filtered mesh list
			ImGui::BeginChild("MeshList", ImVec2(400, 300), true);

			std::string searchStr(s_searchBuffer);

			for (const auto &meshName : m_meshFiles) {
				if (!matchesSearch(meshName, searchStr))
					continue;

				// Highlight current selection
				bool isCurrent = (renderable.meshName == meshName);
				if (isCurrent) {
					ImGui::PushStyleColor(
						ImGuiCol_Text,
						ImVec4(0.2f, 0.8f, 0.2f, 1.0f));
				}

				if (ImGui::Selectable(meshName.c_str(), isCurrent)) {
					renderable.meshName = meshName;
					strcpy(s_meshNameBuffer, meshName.c_str());
				}

				if (isCurrent) {
					ImGui::PopStyleColor();
				}
			}

			if (m_meshFiles.empty()) {
				ImGui::TextDisabled("No mesh files found");
			}

			ImGui::EndChild();

			ImGui::Separator();

			// Show count
			int visibleCount = 0;
			for (const auto &meshName : m_meshFiles) {
				if (matchesSearch(meshName, searchStr))
					visibleCount++;
			}
			ImGui::Text("Showing %d of %zu meshes", visibleCount,
				    m_meshFiles.size());

			// Buttons
			if (ImGui::Button("Load", ImVec2(120, 0))) {
				loadMesh(renderable, entity);
				modified = true;
				s_showMeshBrowser = false;
				ImGui::CloseCurrentPopup();
			}

			ImGui::SameLine();

			if (ImGui::Button("Cancel", ImVec2(120, 0))) {
				s_showMeshBrowser = false;
				ImGui::CloseCurrentPopup();
			}

			ImGui::SameLine();

			if (ImGui::Button("Refresh", ImVec2(120, 0))) {
				m_meshesScanned = false;
				scanMeshFiles();
			}

			ImGui::EndPopup();
		}

		// Load mesh button
		if (ImGui::Button("Load Mesh")) {
			loadMesh(renderable, entity);
			modified = true;
		}

		// Visibility toggle
		if (renderable.entity) {
			bool visible = renderable.entity->getVisible();
			if (ImGui::Checkbox("Visible", &visible)) {
				renderable.entity->setVisible(visible);
				renderable.visible = visible;
				modified = true;
			}
		}

		// Entity info
		if (renderable.entity) {
			ImGui::Text("Entity: %p", renderable.entity);
		} else {
			ImGui::TextDisabled("No entity loaded");
		}

		ImGui::Unindent();
	}

	return modified;
}
