#include "../components/GeneratedPhysicsTag.hpp"
#include "EditorUISystem.hpp"
#include "DialogueSystem.hpp"
#include "PrefabSystem.hpp"
#include "ItemRegistry.hpp"
#include "../camera/EditorCamera.hpp"
#include "../components/EntityName.hpp"
#include "../components/Transform.hpp"
#include "../components/Renderable.hpp"
#include "../components/EditorMarker.hpp"
#include "../components/PhysicsCollider.hpp"
#include "../components/RigidBody.hpp"
#include "../components/BuoyancyInfo.hpp"
#include "../components/WaterPhysics.hpp"
#include "../components/WaterPlane.hpp"
#include "../components/Sun.hpp"
#include "../components/Skybox.hpp"
#include "../components/Light.hpp"
#include "../components/Camera.hpp"
#include "../components/Lod.hpp"
#include "../components/StaticGeometry.hpp"
#include "../components/StaticGeometryMember.hpp"
#include "../components/ProceduralTexture.hpp"
#include "../components/ProceduralMaterial.hpp"
#include "../components/Primitive.hpp"
#include "../components/TriangleBuffer.hpp"
#include "../components/LodSettings.hpp"
#include "../components/CharacterSlots.hpp"
#include "../components/CharacterIdentity.hpp"
#include "../components/CharacterSpawner.hpp"
#include "../components/Character.hpp"
#include "../components/AnimationTree.hpp"
#include "../components/AnimationTreeTemplate.hpp"
#include "../components/StartupMenu.hpp"
#include "../components/PlayerController.hpp"
#include "../components/CellGrid.hpp"
#include "../components/ActionDatabase.hpp"
#include "../components/ActionDebug.hpp"
#include "../components/BehaviorTree.hpp"
#include "../components/GoapBlackboard.hpp"
#include "../components/NavMesh.hpp"
#include "../components/SmartObject.hpp"
#include "../components/GoapPlanner.hpp"
#include "../components/GoapRunner.hpp"
#include "../components/PathFollowing.hpp"
#include "../components/Actuator.hpp"
#include "../components/EventHandler.hpp"
#include "../components/PrefabInstance.hpp"
#include "../components/Item.hpp"
#include "../components/Inventory.hpp"
#include "CharacterClassSystem.hpp"

#include "../ui/TransformEditor.hpp"
#include "../ui/RenderableEditor.hpp"
#include "../ui/PhysicsColliderEditor.hpp"
#include "../ui/RigidBodyEditor.hpp"
#include "../ui/ComponentRegistration.hpp"
#include "../ui/CharacterIdentityEditor.hpp"
#include "../ui/PrefabInstanceEditor.hpp"
#include "PhysicsSystem.hpp"
#include "BuoyancySystem.hpp"
#include "NavMeshSystem.hpp"
#include "NormalDebugSystem.hpp"
#include <imgui.h>
#include <algorithm>
#include <filesystem>
#include <cstring>
#include <sstream>
#include <string>

EditorUISystem::EditorUISystem(flecs::world &world,
			       Ogre::SceneManager *sceneMgr,
			       Ogre::RenderWindow *renderWindow)
	: m_world(world)
	, m_sceneMgr(sceneMgr)
	, m_renderWindow(renderWindow)
	, m_selectedEntity(flecs::entity::null())
	, m_nameQuery(world.query<EntityNameComponent>())
{
	registerComponentEditors();
	m_gizmo = std::make_unique<Gizmo>(m_sceneMgr);
	m_cursor3D = std::make_unique<Cursor3D>(m_sceneMgr);
	m_serializer = std::make_unique<SceneSerializer>(m_world, m_sceneMgr);

	m_characterRegistry.setWorld(&m_world);
	m_characterRegistry.setSceneManager(m_sceneMgr);
	m_characterRegistry.setEditorUISystem(this);
	m_characterRegistry.initialize();
}

EditorUISystem::~EditorUISystem() = default;

void EditorUISystem::shutdown()
{
	// Shutdown gizmo and cursor before SceneManager is destroyed
	if (m_gizmo) {
		m_gizmo->shutdown();
	}
	if (m_cursor3D) {
		m_cursor3D->shutdown();
	}
}

bool EditorUISystem::onMousePressed(const Ogre::Ray &mouseRay)
{
	// Try gizmo first
	if (m_gizmo && m_gizmo->onMousePressed(mouseRay)) {
		return true;
	}

	// Skip if ImGui wants the mouse
	if (ImGui::GetIO().WantCaptureMouse)
		return false;

	if (!m_cursor3D || !m_cursor3D->isVisible())
		return false;

	// Cursor place mode: raycast and place cursor on surface
	if (m_cursorMode == CursorInteractionMode::Place && m_physicsSystem &&
	    m_physicsSystem->isInitialized()) {
		JoltPhysicsWrapper *physics =
			m_physicsSystem->getPhysicsWrapper();
		if (physics) {
			Ogre::Vector3 start = mouseRay.getOrigin();
			Ogre::Vector3 end =
				start + mouseRay.getDirection() * 1000.0f;
			Ogre::Vector3 hitPos;
			JPH::BodyID hitBody;
			if (physics->raycastQuery(start, end, hitPos,
						  hitBody)) {
				m_cursor3D->setPosition(hitPos);
				m_cursorMode = CursorInteractionMode::None;
				return true;
			}
		}
	}

	// Cursor translate/rotate: delegate to Cursor3D axis-based interaction
	if (m_cursorMode == CursorInteractionMode::Translate) {
		m_cursor3D->setMode(Cursor3D::Mode::Translate);
		Ogre::Camera *cam =
			m_editorCamera ? m_editorCamera->getCamera() : nullptr;
		if (m_cursor3D->onMousePressed(mouseRay, cam))
			return true;
	} else if (m_cursorMode == CursorInteractionMode::Rotate) {
		m_cursor3D->setMode(Cursor3D::Mode::Rotate);
		Ogre::Camera *cam =
			m_editorCamera ? m_editorCamera->getCamera() : nullptr;
		if (m_cursor3D->onMousePressed(mouseRay, cam))
			return true;
	}

	return false;
}

bool EditorUISystem::onMouseMoved(const Ogre::Ray &mouseRay,
				  const Ogre::Vector2 &mouseDelta)
{
	// Gizmo gets first shot
	if (m_gizmo && m_gizmo->onMouseMoved(mouseRay, mouseDelta)) {
		return true;
	}

	// Cursor translate/rotate drag
	if (m_cursor3D && (m_cursorMode == CursorInteractionMode::Translate ||
			   m_cursorMode == CursorInteractionMode::Rotate)) {
		if (m_cursor3D->onMouseMoved(mouseRay, mouseDelta))
			return true;
	}

	return false;
}

bool EditorUISystem::onMouseReleased()
{
	// Gizmo gets first shot
	if (m_gizmo && m_gizmo->onMouseReleased()) {
		return true;
	}

	// Cursor translate/rotate release
	if (m_cursor3D && (m_cursorMode == CursorInteractionMode::Translate ||
			   m_cursorMode == CursorInteractionMode::Rotate)) {
		if (m_cursor3D->onMouseReleased())
			return true;
	}

	return false;
}

void EditorUISystem::registerComponentEditors()
{
	// Register Transform component
	auto transformEditor = std::make_unique<TransformEditor>();
	m_componentRegistry.registerComponent<TransformComponent>(
		"Transform", "Transform", std::move(transformEditor),
		// Adder
		[this](flecs::entity e) {
			if (!e.has<TransformComponent>()) {
				TransformComponent transform;
				transform.node =
					m_sceneMgr->getRootSceneNode()
						->createChildSceneNode();
				transform.position = Ogre::Vector3::ZERO;
				transform.rotation = Ogre::Quaternion::IDENTITY;
				transform.scale = Ogre::Vector3::UNIT_SCALE;
				e.set<TransformComponent>(transform);
			}
		},
		// Remover
		[this](flecs::entity e) {
			if (e.has<TransformComponent>()) {
				auto &transform =
					e.get_mut<TransformComponent>();
				if (transform.node) {
					m_sceneMgr->destroySceneNode(
						transform.node);
					transform.node = nullptr;
				}
				e.remove<TransformComponent>();
			}
		});

	// Register Renderable component
	auto renderableEditor = std::make_unique<RenderableEditor>(m_sceneMgr);
	m_componentRegistry.registerComponent<RenderableComponent>(
		"Renderable", "Rendering", std::move(renderableEditor),
		// Adder
		[this](flecs::entity e) {
			if (!e.has<RenderableComponent>()) {
				e.set<RenderableComponent>({});
			}
		},
		// Remover
		[this](flecs::entity e) {
			if (e.has<RenderableComponent>()) {
				auto &renderable =
					e.get_mut<RenderableComponent>();
				if (renderable.entity) {
					m_sceneMgr->destroyEntity(
						renderable.entity);
					renderable.entity = nullptr;
				}
				e.remove<RenderableComponent>();
			}
		});

	// Register RigidBody component
	auto rigidBodyEditor = std::make_unique<RigidBodyEditor>();
	m_componentRegistry.registerComponent<RigidBodyComponent>(
		"Rigid Body", "Physics", std::move(rigidBodyEditor),
		// Adder
		[this](flecs::entity e) {
			if (!e.has<RigidBodyComponent>()) {
				e.set<RigidBodyComponent>({});
			}
		},
		// Remover
		[this](flecs::entity e) {
			if (e.has<RigidBodyComponent>()) {
				e.remove<RigidBodyComponent>();
			}
		});

	// Register PhysicsCollider component
	auto colliderEditor =
		std::make_unique<PhysicsColliderEditor>(m_sceneMgr);
	m_componentRegistry.registerComponent<PhysicsColliderComponent>(
		"Physics Collider", "Physics", std::move(colliderEditor),
		// Adder
		[this](flecs::entity e) {
			if (!e.has<PhysicsColliderComponent>()) {
				e.set<PhysicsColliderComponent>({});
			}
		},
		// Remover
		[this](flecs::entity e) {
			if (e.has<PhysicsColliderComponent>()) {
				e.remove<PhysicsColliderComponent>();
			}
		});

	// Register PrefabInstance component
	auto prefabEditor = std::make_unique<PrefabInstanceEditor>();
	m_componentRegistry.registerComponent<PrefabInstanceComponent>(
		"Prefab Instance", "Scene", std::move(prefabEditor),
		// Adder
		[this](flecs::entity e) {
			if (!e.has<PrefabInstanceComponent>()) {
				e.set<PrefabInstanceComponent>({});
			}
		},
		// Remover
		[this](flecs::entity e) {
			if (e.has<PrefabInstanceComponent>()) {
				e.remove<PrefabInstanceComponent>();
			}
		});

	// Register CharacterIdentity component
	auto characterIdentityEditor =
		std::make_unique<CharacterIdentityEditor>();
	m_componentRegistry.registerComponent<CharacterIdentityComponent>(
		"Character Identity", "Character",
		std::move(characterIdentityEditor),
		[](flecs::entity e) {
			if (!e.has<CharacterIdentityComponent>())
				e.set<CharacterIdentityComponent>(
					CharacterIdentityComponent{});
		},
		[](flecs::entity e) {
			if (e.has<CharacterIdentityComponent>())
				e.remove<CharacterIdentityComponent>();
		});

	// Register modular components (Light, Camera, etc.)
	registerModularComponents();
}

void EditorUISystem::registerModularComponents()
{
	// This calls all component modules registered via REGISTER_COMPONENT macro
	ComponentRegistration::registerAll(m_componentRegistry, m_sceneMgr,
					   m_physicsSystem, m_renderWindow);
}

void EditorUISystem::update(float deltaTime)
{
	if (!m_editorUIEnabled) {
		// Only render FPS overlay when editor UI is disabled
		renderFPSOverlay(deltaTime);
		return;
	}

	// Render UI windows
	// Note: NewFrame() is called by ImGuiRenderListener::preViewportUpdate
	renderHierarchyWindow();
	renderPropertyWindow();

	// Update gizmo position to match selected entity
	if (m_gizmo && m_gizmo->isAttached()) {
		m_gizmo->update();
	}

	// Render file dialog if open
	if (m_showFileDialog) {
		renderFileDialog();
	}

	// Render prefab dialogs
	if (m_showCreatePrefabDialog) {
		showCreatePrefabDialog(m_prefabSourceEntity);
	}

	renderPrefabBrowser();
	renderCursorPanel();

	// Render Action Database singleton editor window
	if (m_showActionDatabaseSingleton) {
		m_actionDatabaseSingletonEditor.render(
			&m_showActionDatabaseSingleton);
	}

	// Render Dialogue settings window
	if (m_showDialogueSettings) {
		renderDialogueSettingsWindow();
	}

	// Render Character Class Database editor
	if (m_showCharacterClassDatabase) {
		m_characterClassDatabaseEditor.render(
			&m_showCharacterClassDatabase);
	}

	// Render Character registry window
	if (m_showCharacterRegistry) {
		m_characterRegistry.drawEditor(&m_showCharacterRegistry);
	}

	// Render Item registry window
	if (m_showItemRegistry) {
		ItemRegistry::getSingleton().drawEditor(&m_showItemRegistry);
	}

	// Render Inventory Dialog Config window
	if (m_showInventoryConfig) {
		renderInventoryConfigWindow();
	}

	// Render FPS overlay
	renderFPSOverlay(deltaTime);
}

void EditorUISystem::setSelectedEntity(flecs::entity entity)
{
	m_selectedEntity = entity;

	// Update gizmo attachment
	if (m_gizmo) {
		if (entity.is_alive() && entity.has<TransformComponent>()) {
			m_gizmo->attachTo(entity);
		} else {
			m_gizmo->detach();
		}
	}
}

void EditorUISystem::renderHierarchyWindow()
{
	ImVec2 viewportSize = ImGui::GetMainViewport()->Size;

	// Left window - fixed to left side
	ImGui::SetNextWindowPos(ImVec2(0, 0), ImGuiCond_Always);
	ImGui::SetNextWindowSize(ImVec2(LEFT_PANEL_WIDTH, viewportSize.y),
				 ImGuiCond_Always);

	ImGuiWindowFlags windowFlags =
		ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoMove |
		ImGuiWindowFlags_NoResize | ImGuiWindowFlags_MenuBar |
		ImGuiWindowFlags_HorizontalScrollbar;

	if (ImGui::Begin("Entity Hierarchy", nullptr, windowFlags)) {
		// Menu bar
		if (ImGui::BeginMenuBar()) {
			// File menu
			if (ImGui::BeginMenu("File")) {
				if (ImGui::MenuItem("Save Scene...",
						    "Ctrl+S")) {
					showFileDialog(true);
				}
				if (ImGui::MenuItem("Load Scene...",
						    "Ctrl+O")) {
					showFileDialog(false);
				}
				ImGui::Separator();
				if (ImGui::MenuItem("Save Action DB",
						    nullptr)) {
					ActionDatabase::saveToJson(
						"actions.json");
				}
				if (ImGui::MenuItem("Load Action DB",
						    nullptr)) {
					ActionDatabase::loadFromJson(
						"actions.json");
				}
				if (ImGui::MenuItem("Reload Action DB",
						    nullptr)) {
					// Reload from file, then re-sync
					// scene components on top
					ActionDatabase::getSingleton().clear();
					ActionDatabase::loadFromJson(
						"actions.json");
					ActionDatabase::reloadFromSceneComponents(
						m_world);
				}
				ImGui::EndMenu();
			}

			// Prefabs menu
			if (ImGui::BeginMenu("Prefabs")) {
				if (ImGui::MenuItem("Show Prefab Browser")) {
					m_showPrefabBrowser = true;
					m_refreshPrefabList = true;
				}
				ImGui::EndMenu();
			}

			// Tools menu
			if (ImGui::BeginMenu("Tools")) {
				if (ImGui::MenuItem("3D Cursor")) {
					m_showCursorPanel = true;
				}
				ImGui::Separator();
				if (ImGui::MenuItem(
					    "Action Database (Singleton)")) {
					m_showActionDatabaseSingleton = true;
				}
				ImGui::Separator();
				if (ImGui::MenuItem("Dialogue Settings")) {
					m_showDialogueSettings = true;
				}
				ImGui::Separator();
				if (ImGui::MenuItem(
					    "Character Class Database")) {
					m_showCharacterClassDatabase = true;
				}
				if (ImGui::MenuItem("Character Registry")) {
					m_showCharacterRegistry = true;
				}
				if (ImGui::MenuItem("Item Registry")) {
					m_showItemRegistry = true;
				}
				ImGui::Separator();
				if (ImGui::MenuItem(
					    "Inventory Dialog Config")) {
					m_showInventoryConfig = true;
				}
				ImGui::EndMenu();
			}

			// Entity menu
			if (ImGui::BeginMenu("Entity")) {
				if (ImGui::MenuItem("New Entity", "Ctrl+N")) {
					createNewEntity();
				}
				if (ImGui::MenuItem("New Child Entity")) {
					if (m_selectedEntity.is_alive()) {
						createChildEntity(
							m_selectedEntity);
					}
				}
				ImGui::Separator();
				if (ImGui::MenuItem(
					    "Duplicate", "Ctrl+D", false,
					    m_selectedEntity.is_alive())) {
					duplicateEntity(m_selectedEntity);
				}
				ImGui::Separator();
				if (ImGui::MenuItem(
					    "Delete", "Delete", false,
					    m_selectedEntity.is_alive())) {
					deleteEntity(m_selectedEntity);
				}
				ImGui::EndMenu();
			}

			// Settings menu
			if (ImGui::BeginMenu("Settings")) {
				if (ImGui::Checkbox("Parent SceneNodes",
						    &m_parentSceneNodes)) {
					// Toggle applied immediately to new entities
				}
				if (ImGui::IsItemHovered()) {
					ImGui::SetTooltip(
						"When enabled, child entities' SceneNodes are parented to their parent's SceneNode, inheriting transforms. When disabled, SceneNodes are created at root level.");
				}

				// Physics stepping toggle
				if (m_physicsSystem) {
					bool physicsEnabled =
						m_physicsSystem
							->isPhysicsEnabled();
					if (ImGui::Checkbox("Physics Stepping",
							    &physicsEnabled)) {
						m_physicsSystem
							->setPhysicsEnabled(
								physicsEnabled);
					}
					if (ImGui::IsItemHovered()) {
						ImGui::SetTooltip(
							"Enable/disable physics simulation stepping. Disable to edit prefabs with physics (e.g. characters) without them falling or moving.");
					}
				}

				// Physics debug draw toggle
				if (m_physicsSystem) {
					bool debugDraw =
						m_physicsSystem
							->isDebugDrawEnabled();
					if (ImGui::Checkbox("Physics Debug Draw",
							    &debugDraw)) {
						m_physicsSystem->setDebugDraw(
							debugDraw);
					}
					if (ImGui::IsItemHovered()) {
						ImGui::SetTooltip(
							"Show physics collision shapes and constraints");
					}
				}

				// Normal debug visualization toggle
				if (m_normalDebugSystem) {
					bool normalDebug =
						m_normalDebugSystem->isEnabled();
					if (ImGui::Checkbox(
						    "Show Polygon Normals",
						    &normalDebug)) {
						m_normalDebugSystem->setEnabled(
							normalDebug);
					}
					if (ImGui::IsItemHovered()) {
						ImGui::SetTooltip(
							"Show vertex normals for plaza and lot base geometry");
					}
				}

				ImGui::EndMenu();
			}
			ImGui::EndMenuBar();
		}

		// Create Entity button
		if (ImGui::Button("+ New Entity", ImVec2(120, 0))) {
			createNewEntity();
		}
		ImGui::SameLine();
		if (ImGui::Button("+ New Child", ImVec2(120, 0))) {
			if (m_selectedEntity.is_alive()) {
				createChildEntity(m_selectedEntity);
			}
		}

		ImGui::Separator();

		// Root entities query - entities without a parent
		std::vector<flecs::entity> rootEntities;
		m_world.query_builder<>()
			.with<EditorMarkerComponent>()
			.build()
			.each([&](flecs::entity entity) {
				// Check if entity has no parent (flecs::ChildOf)
				bool isRoot = true;
				entity.children([&](flecs::entity child) {
					// Just checking if we can iterate children
				});
				// Alternative: use parent() function
				if (entity.parent().is_valid() &&
				    entity.parent() != 0) {
					isRoot = false;
				}
				if (isRoot) {
					rootEntities.push_back(entity);
				}
			});

		// Render tree for each root entity
		for (auto &entity : rootEntities) {
			renderEntityNode(entity, 0);
		}

		// If no entities, show message
		if (rootEntities.empty()) {
			ImGui::TextDisabled("No entities in scene");
		}
	}
	ImGui::End();
}

void EditorUISystem::renderInventoryConfigWindow()
{
	ImGui::SetNextWindowPos(ImVec2(LEFT_PANEL_WIDTH, 100),
				ImGuiCond_FirstUseEver);
	ImGui::SetNextWindowSize(ImVec2(350, 200), ImGuiCond_FirstUseEver);

	ImGuiWindowFlags flags = ImGuiWindowFlags_NoCollapse;
	if (!ImGui::Begin("Inventory Dialog Config", &m_showInventoryConfig,
			  flags)) {
		ImGui::End();
		return;
	}

	ImGui::TextWrapped(
		"Configure the character sheet / inventory dialog font.");
	ImGui::TextWrapped("Settings are persisted to inventory_config.json.");

	ImGui::Separator();

	// Local copy for editing, loaded from file
	static InventoryDialogConfig editConfig;
	static bool initialized = false;
	if (!initialized) {
		editConfig.loadFromFile("inventory_config.json");
		initialized = true;
	}

	char fontPathBuf[256];
	std::strncpy(fontPathBuf, editConfig.fontPath.c_str(),
		     sizeof(fontPathBuf) - 1);
	fontPathBuf[sizeof(fontPathBuf) - 1] = '\0';
	if (ImGui::InputText("Font Path", fontPathBuf, sizeof(fontPathBuf))) {
		editConfig.fontPath = fontPathBuf;
	}

	if (ImGui::DragFloat("Font Size", &editConfig.fontSize, 0.5f, 8.0f,
			     72.0f)) {
	}

	ImGui::Separator();

	if (ImGui::Button("Save to inventory_config.json")) {
		if (editConfig.saveToFile("inventory_config.json")) {
			Ogre::LogManager::getSingleton().logMessage(
				"Inventory dialog config saved.");
		}
	}
	ImGui::SameLine();
	if (ImGui::Button("Load from inventory_config.json")) {
		if (editConfig.loadFromFile("inventory_config.json")) {
			Ogre::LogManager::getSingleton().logMessage(
				"Inventory dialog config loaded.");
		}
	}

	ImGui::End();
}

void EditorUISystem::renderEntityNode(flecs::entity entity, int depth)
{
	if (!entity.is_alive())
		return;

	// Get entity name
	std::string name = "Unnamed";
	if (entity.has<EntityNameComponent>()) {
		name = entity.get<EntityNameComponent>().name;
	}

	// Collect children using flecs::ChildOf relationship
	// (skip auto-generated physics entities)
	std::vector<flecs::entity> children;
	entity.children([&](flecs::entity child) {
		if (!child.has<GeneratedPhysicsTag>()) {
			children.push_back(child);
		}
	});
	bool hasChildren = !children.empty();

	// Tree node flags
	ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_OpenOnArrow |
				   ImGuiTreeNodeFlags_OpenOnDoubleClick |
				   ImGuiTreeNodeFlags_SpanAvailWidth;

	// Leaf nodes (no children) have bullet style
	if (!hasChildren) {
		flags |= ImGuiTreeNodeFlags_Leaf |
			 ImGuiTreeNodeFlags_NoTreePushOnOpen;
	}

	// Highlight selected
	if (m_selectedEntity == entity) {
		flags |= ImGuiTreeNodeFlags_Selected;
	}

	// Create label with optional component indicators
	char label[256];
	std::string indicators;
	if (entity.has<TransformComponent>())
		indicators += " [T]";
	if (entity.has<RenderableComponent>())
		indicators += " [R]";
	if (entity.has<LightComponent>())
		indicators += " [L]";
	if (entity.has<CameraComponent>())
		indicators += " [Cam]";
	if (entity.has<RigidBodyComponent>())
		indicators += " [RB]";
	if (entity.has<PhysicsColliderComponent>())
		indicators += " [C]";
	if (entity.has<LodSettingsComponent>())
		indicators += " [LODS]";
	if (entity.has<LodComponent>())
		indicators += " [LOD]";
	// Town/District/Lot/CellGrid components
	if (entity.has<TownComponent>())
		indicators += " [Town]";
	if (entity.has<DistrictComponent>())
		indicators += " [Dist]";
	if (entity.has<LotComponent>())
		indicators += " [Lot]";
	if (entity.has<CellGridComponent>())
		indicators += " [Grid]";
	if (entity.has<RoofComponent>())
		indicators += " [Roof]";
	if (entity.has<RoomComponent>())
		indicators += " [Room]";
	if (entity.has<FurnitureTemplateComponent>())
		indicators += " [Furn]";
	if (entity.has<ProceduralTextureComponent>())
		indicators += " [Tex]";
	if (entity.has<ProceduralMaterialComponent>())
		indicators += " [Mat]";
	if (entity.has<AnimationTreeComponent>())
		indicators += " [Anim]";
	if (entity.has<ActionDatabaseComponent>())
		indicators += " [ActDB]";
	if (entity.has<ActionDebug>())
		indicators += " [Debug]";

	if (entity.has<BehaviorTreeComponent>())
		indicators += " [BT]";
	if (entity.has<GoapBlackboard>())
		indicators += " [BB]";
	if (entity.has<NavMeshComponent>())
		indicators += " [Nav]";
	if (entity.has<NavMeshGeometrySource>())
		indicators += " [NavSrc]";
	if (entity.has<SmartObjectComponent>())
		indicators += " [SO]";
	if (entity.has<GoapPlannerComponent>())
		indicators += " [Planner]";

	snprintf(label, sizeof(label), "%s%s##%llu", name.c_str(),
		 indicators.c_str(), (unsigned long long)entity.id());

	// Draw tree node
	bool isOpen = ImGui::TreeNodeEx(label, flags);

	// Handle selection on click
	if (ImGui::IsItemClicked()) {
		setSelectedEntity(entity);
	}

	// Context menu
	if (ImGui::BeginPopupContextItem()) {
		renderEntityContextMenu(entity);
		ImGui::EndPopup();
	}

	// Render children recursively
	if (isOpen && hasChildren) {
		for (auto &child : children) {
			renderEntityNode(child, depth + 1);
		}
		ImGui::TreePop();
	}
}

void EditorUISystem::renderEntityContextMenu(flecs::entity entity)
{
	if (ImGui::MenuItem("New Child Entity")) {
		createChildEntity(entity);
	}
	ImGui::Separator();
	if (ImGui::MenuItem("Duplicate")) {
		duplicateEntity(entity);
	}
	if (ImGui::MenuItem("Create Prefab")) {
		m_prefabSourceEntity = entity;
		m_showCreatePrefabDialog = true;
		m_prefabNameBuffer[0] = '\0';
	}
	ImGui::Separator();
	if (ImGui::MenuItem("Delete")) {
		deleteEntity(entity);
	}
}

void EditorUISystem::renderPropertyWindow()
{
	ImVec2 viewportSize = ImGui::GetMainViewport()->Size;

	// Right window - fixed to right side
	ImGui::SetNextWindowPos(ImVec2(viewportSize.x - RIGHT_PANEL_WIDTH, 0),
				ImGuiCond_Always);
	ImGui::SetNextWindowSize(ImVec2(RIGHT_PANEL_WIDTH, viewportSize.y),
				 ImGuiCond_Always);

	ImGuiWindowFlags windowFlags =
		ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoMove |
		ImGuiWindowFlags_NoResize | ImGuiWindowFlags_MenuBar;

	if (ImGui::Begin("Property Editor", nullptr, windowFlags)) {
		if (m_selectedEntity.is_alive()) {
			// Entity name header
			if (m_selectedEntity.has<EntityNameComponent>()) {
				auto &nameComp =
					m_selectedEntity
						.get_mut<EntityNameComponent>();
				char nameBuffer[256];
				strcpy(nameBuffer, nameComp.name.c_str());
				if (ImGui::InputText("Name", nameBuffer,
						     sizeof(nameBuffer))) {
					nameComp.name = nameBuffer;
				}
			}

			// Entity ID
			ImGui::TextDisabled(
				"ID: %llu",
				(unsigned long long)m_selectedEntity.id());

			ImGui::Separator();

			// Component operations
			renderComponentList(m_selectedEntity);
		} else {
			ImGui::TextDisabled("No entity selected");
			ImGui::Text("Select an entity from the hierarchy");
		}
	}
	ImGui::End();
}

void EditorUISystem::renderComponentList(flecs::entity entity)
{
	// Component operations menu bar
	if (ImGui::Button("Add Component")) {
		ImGui::OpenPopup("AddComponentMenu");
	}
	renderAddComponentMenu(entity);

	ImGui::SameLine();

	if (ImGui::Button("Remove Component")) {
		ImGui::OpenPopup("RemoveComponentMenu");
	}
	renderRemoveComponentMenu(entity);

	ImGui::Separator();

	// Render component editors
	ImGui::BeginChild("Components", ImVec2(0, 0), true);

	// Dynamically render all components the entity has
	int componentCount = 0;

	// Render Transform first if present (it's the base component)
	if (entity.has<TransformComponent>()) {
		auto &transform = entity.get_mut<TransformComponent>();
		if (m_componentRegistry.render<TransformComponent>(entity,
								   transform)) {
			// Transform changed - mark StaticGeometryMember dirty if present
			if (entity.has<StaticGeometryMemberComponent>()) {
				entity.get_mut<StaticGeometryMemberComponent>()
					.markDirty();
			}
		}
		componentCount++;
	}

	// Render Renderable
	if (entity.has<RenderableComponent>()) {
		auto &renderable = entity.get_mut<RenderableComponent>();
		m_componentRegistry.render<RenderableComponent>(entity,
								renderable);
		componentCount++;
	}

	// Render Light if present
	if (entity.has<LightComponent>()) {
		auto &light = entity.get_mut<LightComponent>();
		m_componentRegistry.render<LightComponent>(entity, light);
		componentCount++;
	}

	// Render Camera if present
	if (entity.has<CameraComponent>()) {
		auto &camera = entity.get_mut<CameraComponent>();
		m_componentRegistry.render<CameraComponent>(entity, camera);
		componentCount++;
	}

	// Render RigidBody
	if (entity.has<RigidBodyComponent>()) {
		auto &rigidBody = entity.get_mut<RigidBodyComponent>();
		m_componentRegistry.render<RigidBodyComponent>(entity,
							       rigidBody);
		componentCount++;
	}

	// Render PhysicsCollider
	if (entity.has<PhysicsColliderComponent>()) {
		auto &collider = entity.get_mut<PhysicsColliderComponent>();
		m_componentRegistry.render<PhysicsColliderComponent>(entity,
								     collider);
		componentCount++;
	}

	// Render BuoyancyInfo if present
	if (entity.has<BuoyancyInfo>()) {
		auto &buoyancy = entity.get_mut<BuoyancyInfo>();
		m_componentRegistry.render<BuoyancyInfo>(entity, buoyancy);
		componentCount++;
	}

	// Render WaterPhysics if present
	if (entity.has<WaterPhysics>()) {
		auto &wp = entity.get_mut<WaterPhysics>();
		m_componentRegistry.render<WaterPhysics>(entity, wp);
		componentCount++;
	}

	// Render Sun if present
	if (entity.has<SunComponent>()) {
		auto &sun = entity.get_mut<SunComponent>();
		if (m_componentRegistry.render<SunComponent>(entity, sun)) {
			sun.markDirty();
		}
		componentCount++;
	}

	// Render Skybox if present
	if (entity.has<SkyboxComponent>()) {
		auto &sky = entity.get_mut<SkyboxComponent>();
		if (m_componentRegistry.render<SkyboxComponent>(entity, sky)) {
			sky.markDirty();
		}
		componentCount++;
	}

	// Render WaterPlane if present
	if (entity.has<WaterPlane>()) {
		auto &wp = entity.get_mut<WaterPlane>();
		if (m_componentRegistry.render<WaterPlane>(entity, wp)) {
			wp.markDirty();
		}
		componentCount++;
	}

	// Render LOD Settings if present
	if (entity.has<LodSettingsComponent>()) {
		auto &lodSettings = entity.get_mut<LodSettingsComponent>();
		m_componentRegistry.render<LodSettingsComponent>(entity,
								 lodSettings);
		componentCount++;
	}

	// Render LOD if present
	if (entity.has<LodComponent>()) {
		auto &lod = entity.get_mut<LodComponent>();
		m_componentRegistry.render<LodComponent>(entity, lod);
		componentCount++;
	}

	// Render StaticGeometry Region if present
	if (entity.has<StaticGeometryComponent>()) {
		auto &region = entity.get_mut<StaticGeometryComponent>();
		m_componentRegistry.render<StaticGeometryComponent>(entity,
								    region);
		componentCount++;
	}

	// Render StaticGeometry Member if present
	if (entity.has<StaticGeometryMemberComponent>()) {
		auto &member = entity.get_mut<StaticGeometryMemberComponent>();
		m_componentRegistry.render<StaticGeometryMemberComponent>(
			entity, member);
		componentCount++;
	}

	// Render ProceduralTexture if present
	if (entity.has<ProceduralTextureComponent>()) {
		auto &texture = entity.get_mut<ProceduralTextureComponent>();
		m_componentRegistry.render<ProceduralTextureComponent>(entity,
								       texture);
		componentCount++;
	}

	// Render ProceduralMaterial if present
	if (entity.has<ProceduralMaterialComponent>()) {
		auto &material = entity.get_mut<ProceduralMaterialComponent>();
		m_componentRegistry.render<ProceduralMaterialComponent>(
			entity, material);
		componentCount++;
	}

	// Render Primitive if present
	if (entity.has<PrimitiveComponent>()) {
		auto &primitive = entity.get_mut<PrimitiveComponent>();
		m_componentRegistry.render<PrimitiveComponent>(entity,
							       primitive);
		componentCount++;
	}

	// Render TriangleBuffer if present
	if (entity.has<TriangleBufferComponent>()) {
		auto &tb = entity.get_mut<TriangleBufferComponent>();
		m_componentRegistry.render<TriangleBufferComponent>(entity, tb);
		componentCount++;
	}

	// Render Character if present
	if (entity.has<CharacterComponent>()) {
		auto &cc = entity.get_mut<CharacterComponent>();
		m_componentRegistry.render<CharacterComponent>(entity, cc);
		componentCount++;
	}

	// Render CharacterSlots if present
	if (entity.has<CharacterSlotsComponent>()) {
		/* CharacterSlotsComponent is now an empty tag; get_mut is illegal
		 * for zero-sized types in flecs. */
		CharacterSlotsComponent cs;
		m_componentRegistry.render<CharacterSlotsComponent>(entity, cs);
		componentCount++;
	}

	// Render CharacterIdentity if present
	if (entity.has<CharacterIdentityComponent>()) {
		auto &ci = entity.get_mut<CharacterIdentityComponent>();
		m_componentRegistry.render<CharacterIdentityComponent>(entity,
								       ci);
		componentCount++;
	}

	// Render CharacterSpawner if present
	if (entity.has<CharacterSpawnerComponent>()) {
		auto &spawner = entity.get_mut<CharacterSpawnerComponent>();
		m_componentRegistry.render<CharacterSpawnerComponent>(entity,
							      spawner);
		componentCount++;
	}

	// Render AnimationTree if present
	if (entity.has<AnimationTreeComponent>()) {
		auto &at = entity.get_mut<AnimationTreeComponent>();
		m_componentRegistry.render<AnimationTreeComponent>(entity, at);
		componentCount++;
	}

	// Render AnimationTreeTemplate if present
	if (entity.has<AnimationTreeTemplate>()) {
		auto &templ = entity.get_mut<AnimationTreeTemplate>();
		m_componentRegistry.render<AnimationTreeTemplate>(entity,
								  templ);
		componentCount++;
	}

	// Render StartupMenu if present
	if (entity.has<StartupMenuComponent>()) {
		auto &sm = entity.get_mut<StartupMenuComponent>();
		m_componentRegistry.render<StartupMenuComponent>(entity, sm);
		componentCount++;
	}

	// Render PlayerController if present
	if (entity.has<PlayerControllerComponent>()) {
		auto &pc = entity.get_mut<PlayerControllerComponent>();
		m_componentRegistry.render<PlayerControllerComponent>(entity,
								      pc);
		componentCount++;
	}

	// Render CellGrid if present
	if (entity.has<CellGridComponent>()) {
		auto &grid = entity.get_mut<CellGridComponent>();
		m_componentRegistry.render<CellGridComponent>(entity, grid);
		componentCount++;
	}

	// Render Lot if present
	if (entity.has<LotComponent>()) {
		auto &lot = entity.get_mut<LotComponent>();
		m_componentRegistry.render<LotComponent>(entity, lot);
		componentCount++;
	}

	// Render District if present
	if (entity.has<DistrictComponent>()) {
		auto &district = entity.get_mut<DistrictComponent>();
		m_componentRegistry.render<DistrictComponent>(entity, district);
		componentCount++;
	}

	// Render Town if present
	if (entity.has<TownComponent>()) {
		auto &town = entity.get_mut<TownComponent>();
		m_componentRegistry.render<TownComponent>(entity, town);
		componentCount++;
	}

	// Render Roof if present
	if (entity.has<RoofComponent>()) {
		auto &roof = entity.get_mut<RoofComponent>();
		m_componentRegistry.render<RoofComponent>(entity, roof);
		componentCount++;
	}

	// Render Room if present
	if (entity.has<RoomComponent>()) {
		auto &room = entity.get_mut<RoomComponent>();
		if (m_componentRegistry.render<RoomComponent>(entity, room)) {
			room.markDirty();
		}
		componentCount++;
	}

	// Render ClearArea if present
	if (entity.has<ClearAreaComponent>()) {
		auto &clearArea = entity.get_mut<ClearAreaComponent>();
		if (m_componentRegistry.render<ClearAreaComponent>(entity,
								   clearArea)) {
			clearArea.markDirty();
		}
		componentCount++;
	}

	// Render FurnitureTemplate if present
	if (entity.has<FurnitureTemplateComponent>()) {
		auto &furniture = entity.get_mut<FurnitureTemplateComponent>();
		m_componentRegistry.render<FurnitureTemplateComponent>(
			entity, furniture);
		componentCount++;
	}

	// Render ActionDatabaseComponent if present
	if (entity.has<ActionDatabaseComponent>()) {
		auto &db = entity.get_mut<ActionDatabaseComponent>();
		m_componentRegistry.render<ActionDatabaseComponent>(entity, db);
		componentCount++;
	}

	// Render ActionDebug if present

	if (entity.has<ActionDebug>()) {
		auto &debug = entity.get_mut<ActionDebug>();
		m_componentRegistry.render<ActionDebug>(entity, debug);
		componentCount++;
	}

	// Render BehaviorTree if present
	if (entity.has<BehaviorTreeComponent>()) {
		auto &bt = entity.get_mut<BehaviorTreeComponent>();
		m_componentRegistry.render<BehaviorTreeComponent>(entity, bt);
		componentCount++;
	}

	// Render NavMesh if present
	if (entity.has<NavMeshComponent>()) {
		auto &nav = entity.get_mut<NavMeshComponent>();
		if (m_componentRegistry.render<NavMeshComponent>(entity, nav)) {
			if (nav.debugDraw && NavMeshSystem::getInstance())
				NavMeshSystem::getInstance()->setDebugDraw(
					entity, nav.debugDraw);
		}
		componentCount++;
	}

	// Render NavMeshGeometrySource if present
	if (entity.has<NavMeshGeometrySource>()) {
		auto &src = entity.get_mut<NavMeshGeometrySource>();
		m_componentRegistry.render<NavMeshGeometrySource>(entity, src);
		componentCount++;
	}

	// Render SmartObject if present
	if (entity.has<SmartObjectComponent>()) {
		auto &so = entity.get_mut<SmartObjectComponent>();
		m_componentRegistry.render<SmartObjectComponent>(entity, so);
		componentCount++;
	}

	// Render GoapPlanner if present
	if (entity.has<GoapPlannerComponent>()) {
		auto &planner = entity.get_mut<GoapPlannerComponent>();
		m_componentRegistry.render<GoapPlannerComponent>(entity,
								 planner);
		componentCount++;
	}

	// Render GoapRunner if present
	if (entity.has<GoapRunnerComponent>()) {
		auto &runner = entity.get_mut<GoapRunnerComponent>();
		m_componentRegistry.render<GoapRunnerComponent>(entity, runner);
		componentCount++;
	}

	// Render PathFollowing if present
	if (entity.has<PathFollowingComponent>()) {
		auto &pf = entity.get_mut<PathFollowingComponent>();
		m_componentRegistry.render<PathFollowingComponent>(entity, pf);
		componentCount++;
	}

	// Render Actuator if present
	if (entity.has<ActuatorComponent>()) {
		auto &actuator = entity.get_mut<ActuatorComponent>();
		m_componentRegistry.render<ActuatorComponent>(entity, actuator);
		componentCount++;
	}

	// Render EventHandler if present
	if (entity.has<EventHandlerComponent>()) {
		auto &handler = entity.get_mut<EventHandlerComponent>();
		m_componentRegistry.render<EventHandlerComponent>(entity,
								  handler);
		componentCount++;
	}

	// Render Item if present
	if (entity.has<ItemComponent>()) {
		auto &item = entity.get_mut<ItemComponent>();
		m_componentRegistry.render<ItemComponent>(entity, item);
		componentCount++;
	}

	// Render Inventory if present
	if (entity.has<InventoryComponent>()) {
		auto &inv = entity.get_mut<InventoryComponent>();
		m_componentRegistry.render<InventoryComponent>(entity, inv);
		componentCount++;
	}

	// Show message if no components

	if (componentCount == 0) {
		ImGui::TextDisabled("No components");
		ImGui::Text("Click 'Add Component' to add components");
	}

	ImGui::EndChild();
}

void EditorUISystem::renderAddComponentMenu(flecs::entity entity)
{
	if (ImGui::BeginPopup("AddComponentMenu")) {
		ImGui::Text("Add Component:");
		ImGui::Separator();

		// Group components by their group name
		auto groups = m_componentRegistry.getGroups();
		bool hasAny = false;

		for (const auto &group : groups) {
			// Count components in this group that the entity doesn't have
			int availableCount = 0;
			m_componentRegistry.forEachInGroup(
				group.c_str(),
				[&](const std::type_index &type,
				    const ComponentRegistry::ComponentInfo
					    &info) {
					if (!info.adder)
						return;
					if (!m_componentRegistry
						     .entityHasComponent(
							     entity, type)) {
						availableCount++;
					}
				});

			if (availableCount == 0)
				continue;
			hasAny = true;

			// Create a submenu for each group
			if (ImGui::BeginMenu(group.c_str())) {
				m_componentRegistry.forEachInGroup(
					group.c_str(),
					[&](const std::type_index &type,
					    const ComponentRegistry::ComponentInfo
						    &info) {
						if (!info.adder)
							return;
						if (!m_componentRegistry
							     .entityHasComponent(
								     entity,
								     type)) {
							if (ImGui::MenuItem(
								    info.name)) {
								m_componentRegistry
									.addComponentByType(
										entity,
										type);
							}
						}
					});
				ImGui::EndMenu();
			}
		}

		if (!hasAny) {
			ImGui::TextDisabled("All components added");
		}

		ImGui::EndPopup();
	}
}

void EditorUISystem::renderRemoveComponentMenu(flecs::entity entity)
{
	if (ImGui::BeginPopup("RemoveComponentMenu")) {
		ImGui::Text("Remove Component:");
		ImGui::Separator();

		// Dynamically list all registered components that the entity has
		bool hasAny = false;
		m_componentRegistry.forEach(
			[&](const std::type_index &type,
			    const ComponentRegistry::ComponentInfo &info) {
				if (m_componentRegistry.entityHasComponent(
					    entity, type)) {
					hasAny = true;
					if (ImGui::MenuItem(info.name)) {
						m_componentRegistry
							.removeComponentByType(
								entity, type);
					}
				}
			});

		if (!hasAny) {
			ImGui::TextDisabled("No components to remove");
		}

		ImGui::EndPopup();
	}
}

void EditorUISystem::createNewEntity()
{
	flecs::entity entity = m_world.entity();
	entity.set<EntityNameComponent>(EntityNameComponent("New Entity"));
	entity.add<EditorMarkerComponent>();

	// Add transform by default
	TransformComponent transform;
	transform.node = m_sceneMgr->getRootSceneNode()->createChildSceneNode();
	transform.position = Ogre::Vector3::ZERO;
	transform.rotation = Ogre::Quaternion::IDENTITY;
	transform.scale = Ogre::Vector3::UNIT_SCALE;
	entity.set<TransformComponent>(transform);

	setSelectedEntity(entity);
}

void EditorUISystem::createChildEntity(flecs::entity parent)
{
	if (!parent.is_alive() || !parent.has<TransformComponent>())
		return;

	// Create entity as child of parent using flecs::ChildOf
	flecs::entity entity = m_world.entity();
	entity.child_of(parent);
	entity.set<EntityNameComponent>(EntityNameComponent("Child Entity"));
	entity.add<EditorMarkerComponent>();

	// Create transform
	TransformComponent transform;
	auto &parentTransform = parent.get_mut<TransformComponent>();

	// SceneNode parenting depends on setting
	if (m_parentSceneNodes) {
		// Child SceneNode inherits parent's transform
		transform.node = parentTransform.node->createChildSceneNode();
		transform.position = Ogre::Vector3::ZERO;
	} else {
		// Child SceneNode at root level, position relative to parent
		transform.node =
			m_sceneMgr->getRootSceneNode()->createChildSceneNode();
		transform.position = parentTransform.position;
	}

	transform.rotation = Ogre::Quaternion::IDENTITY;
	transform.scale = Ogre::Vector3::UNIT_SCALE;
	entity.set<TransformComponent>(transform);

	setSelectedEntity(entity);
}

void EditorUISystem::deleteEntity(flecs::entity entity)
{
	if (!entity.is_alive())
		return;

	// First delete all children recursively
	auto children = getEntityChildren(entity);
	for (auto &child : children) {
		deleteEntity(child);
	}

	// Clean up physics body before removing component
	if (entity.has<RigidBodyComponent>()) {
		auto &rigidBody = entity.get_mut<RigidBodyComponent>();
		if (m_physicsSystem && rigidBody.bodyCreated) {
			m_physicsSystem->removeRigidBody(rigidBody);
		}
	}

	// Clean up transform node
	if (entity.has<TransformComponent>()) {
		auto &transform = entity.get_mut<TransformComponent>();
		if (transform.node) {
			m_sceneMgr->destroySceneNode(transform.node);
		}
	}

	// Clean up renderable
	if (entity.has<RenderableComponent>()) {
		auto &renderable = entity.get_mut<RenderableComponent>();
		if (renderable.entity) {
			m_sceneMgr->destroyEntity(renderable.entity);
		}
	}

	if (m_selectedEntity == entity) {
		setSelectedEntity(flecs::entity::null());
	}

	// Remove from cached list
	auto it = std::find(m_allEntities.begin(), m_allEntities.end(), entity);
	if (it != m_allEntities.end()) {
		m_allEntities.erase(it);
	}

	entity.destruct();
}

void EditorUISystem::duplicateEntity(flecs::entity entity)
{
	if (!entity.is_alive())
		return;

	flecs::entity newEntity = m_world.entity();

	// Copy name
	if (entity.has<EntityNameComponent>()) {
		auto &name = entity.get<EntityNameComponent>().name;
		newEntity.set<EntityNameComponent>(
			EntityNameComponent(name + " (Copy)"));
	}

	// Copy parent relationship using flecs::ChildOf
	flecs::entity parent = entity.parent();
	if (parent.is_valid() && parent != 0) {
		newEntity.child_of(parent);
	}

	// Copy transform
	if (entity.has<TransformComponent>()) {
		auto &oldTransform = entity.get<TransformComponent>();
		TransformComponent newTransform;

		// Find parent entity and node
		flecs::entity parent = entity.parent();
		Ogre::SceneNode *parentNode = m_sceneMgr->getRootSceneNode();

		if (parent.is_valid() && parent != 0 &&
		    parent.has<TransformComponent>()) {
			parentNode = parent.get<TransformComponent>().node;
		}

		// SceneNode parenting depends on setting
		if (m_parentSceneNodes && parent.is_valid() && parent != 0) {
			// Create as child of parent's SceneNode
			newTransform.node = parentNode->createChildSceneNode();
			newTransform.position =
				oldTransform.position + Ogre::Vector3(1, 0, 0);
		} else {
			// Create at root level
			newTransform.node = m_sceneMgr->getRootSceneNode()
						    ->createChildSceneNode();
			newTransform.position =
				oldTransform.position + Ogre::Vector3(1, 0, 0);
		}

		newTransform.rotation = oldTransform.rotation;
		newTransform.scale = oldTransform.scale;
		newTransform.applyToNode();
		newEntity.set<TransformComponent>(newTransform);
	}

	// Copy renderable (but not the mesh instance)
	if (entity.has<RenderableComponent>()) {
		auto &oldRenderable = entity.get<RenderableComponent>();
		RenderableComponent newRenderable;
		newRenderable.meshName = oldRenderable.meshName;
		newRenderable.visible = oldRenderable.visible;
		// Entity will be created when mesh is loaded
		newEntity.set<RenderableComponent>(newRenderable);
	}

	setSelectedEntity(newEntity);
}

flecs::entity EditorUISystem::findEntityParent(flecs::entity entity)
{
	if (!entity.is_alive())
		return flecs::entity::null();

	// Use flecs parent() function
	flecs::entity parent = entity.parent();
	if (parent.is_valid() && parent != 0) {
		return parent;
	}
	return flecs::entity::null();
}

std::vector<flecs::entity>
EditorUISystem::getEntityChildren(flecs::entity parent)
{
	std::vector<flecs::entity> children;

	if (!parent.is_alive())
		return children;

	// Use flecs::ChildOf relationship to get children
	parent.children(
		[&](flecs::entity child) { children.push_back(child); });

	return children;
}

bool EditorUISystem::isDescendantOf(flecs::entity potentialChild,
				    flecs::entity potentialParent)
{
	if (!potentialChild.is_alive() || !potentialParent.is_alive())
		return false;

	flecs::entity current = findEntityParent(potentialChild);
	while (current.is_alive()) {
		if (current == potentialParent)
			return true;
		current = findEntityParent(current);
	}
	return false;
}

void EditorUISystem::saveScene(const std::string &filepath)
{
	if (!m_serializer)
		return;

	if (m_serializer->saveToFile(filepath)) {
		Ogre::LogManager::getSingleton().logMessage("Scene saved to: " +
							    filepath);
	} else {
		Ogre::LogManager::getSingleton().logMessage(
			"Failed to save scene: " +
			m_serializer->getLastError());
	}
}

void EditorUISystem::loadScene(const std::string &filepath)
{
	if (!m_serializer)
		return;

	if (m_serializer->loadFromFile(filepath, this)) {
		Ogre::LogManager::getSingleton().logMessage(
			"Scene loaded from: " + filepath);
	} else {
		Ogre::LogManager::getSingleton().logMessage(
			"Failed to load scene: " +
			m_serializer->getLastError());
	}
}

// File Dialog Implementation

void EditorUISystem::showFileDialog(bool isSave)
{
	m_showFileDialog = true;
	m_fileDialogIsSave = isSave;
	m_refreshDirectory = true;

	// Initialize current path if empty
	if (m_currentPath.empty()) {
		m_currentPath = std::filesystem::current_path().string();
	}

	// Set default filename for save dialog
	if (isSave && strlen(m_filenameBuffer) == 0) {
		std::strncpy(m_filenameBuffer, "scene.json",
			     sizeof(m_filenameBuffer) - 1);
	}
}

void EditorUISystem::closeFileDialog()
{
	m_showFileDialog = false;
}

void EditorUISystem::renderFileDialog()
{
	const char *title = m_fileDialogIsSave ? "Save Scene" : "Load Scene";

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

	if (!ImGui::Begin(title, &m_showFileDialog)) {
		ImGui::End();
		return;
	}

	// Current path display
	ImGui::Text("Location: %s", m_currentPath.c_str());
	ImGui::Separator();

	// Refresh directory contents if needed
	if (m_refreshDirectory) {
		m_directoryContents.clear();
		try {
			for (const auto &entry :
			     std::filesystem::directory_iterator(
				     m_currentPath)) {
				m_directoryContents.push_back(
					entry.path().filename().string());
			}
			std::sort(m_directoryContents.begin(),
				  m_directoryContents.end());
		} catch (...) {
			// Ignore errors (e.g., permission denied)
		}
		m_refreshDirectory = false;
	}

	// Parent directory button
	if (ImGui::Button("..")) {
		std::filesystem::path p(m_currentPath);
		if (p.has_parent_path()) {
			m_currentPath = p.parent_path().string();
			m_refreshDirectory = true;
		}
	}
	ImGui::SameLine();
	ImGui::Text("(Parent Directory)");

	// File list
	ImGui::BeginChild("FileList", ImVec2(0, -60), true);

	for (const auto &name : m_directoryContents) {
		std::filesystem::path fullPath =
			std::filesystem::path(m_currentPath) / name;
		bool isDirectory = std::filesystem::is_directory(fullPath);

		// Skip non-json files in load mode (but show directories)
		if (!m_fileDialogIsSave && !isDirectory) {
			if (fullPath.extension() != ".json") {
				continue;
			}
		}

		std::string label = isDirectory ? "[D] " + name : name;

		if (ImGui::Selectable(label.c_str(), m_selectedFile == name)) {
			if (isDirectory) {
				m_currentPath = fullPath.string();
				m_refreshDirectory = true;
				m_selectedFile.clear();
			} else {
				m_selectedFile = name;
				std::strncpy(m_filenameBuffer, name.c_str(),
					     sizeof(m_filenameBuffer) - 1);
			}
		}

		// Double-click to enter directory or select file
		if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(0)) {
			if (isDirectory) {
				m_currentPath = fullPath.string();
				m_refreshDirectory = true;
				m_selectedFile.clear();
			}
		}
	}

	ImGui::EndChild();

	// Filename input
	ImGui::Separator();
	ImGui::Text("Filename:");
	ImGui::SameLine();
	ImGui::InputText("##filename", m_filenameBuffer,
			 sizeof(m_filenameBuffer));

	// Buttons
	if (ImGui::Button(m_fileDialogIsSave ? "Save" : "Load",
			  ImVec2(120, 0))) {
		std::string filename(m_filenameBuffer);
		if (!filename.empty()) {
			// Add .json extension if missing in save mode
			if (m_fileDialogIsSave &&
			    filename.find('.') == std::string::npos) {
				filename += ".json";
			}

			std::string fullPath =
				(std::filesystem::path(m_currentPath) /
				 filename)
					.string();

			if (m_fileDialogIsSave) {
				saveScene(fullPath);
			} else {
				loadScene(fullPath);
			}
			closeFileDialog();
		}
	}

	ImGui::SameLine();

	if (ImGui::Button("Cancel", ImVec2(120, 0))) {
		closeFileDialog();
	}

	ImGui::End();
}

void EditorUISystem::renderFPSOverlay(float deltaTime)
{
	// Toggle FPS overlay with F12 key
	if (ImGui::IsKeyPressed(ImGuiKey_F12)) {
		m_showFPSOverlay = !m_showFPSOverlay;
	}

	if (!m_showFPSOverlay) {
		return;
	}

	// Update FPS calculation
	m_fpsTimeAccumulator += deltaTime;
	m_fpsFrameCount++;

	// Note: Batch count is set by ImGuiRenderListener::postViewportUpdate
	// after each frame render (stats are updated at end of frame)

	// Update FPS every 0.5 seconds for smoother display
	if (m_fpsTimeAccumulator >= 0.5f) {
		m_currentFPS = m_fpsFrameCount / m_fpsTimeAccumulator;
		m_fpsTimeAccumulator = 0.0f;
		m_fpsFrameCount = 0;
	}

	// Set up transparent window style
	ImGuiWindowFlags windowFlags = ImGuiWindowFlags_NoDecoration |
				       ImGuiWindowFlags_AlwaysAutoResize |
				       ImGuiWindowFlags_NoSavedSettings |
				       ImGuiWindowFlags_NoFocusOnAppearing |
				       ImGuiWindowFlags_NoNav;

	// Position in top-right corner with padding
	ImVec2 windowPos = ImVec2(ImGui::GetIO().DisplaySize.x - 10.0f, 10.0f);
	ImVec2 windowPivot = ImVec2(1.0f, 0.0f); // Top-right pivot

	ImGui::SetNextWindowPos(windowPos, ImGuiCond_Always, windowPivot);
	ImGui::SetNextWindowBgAlpha(0.35f); // Semi-transparent background

	if (ImGui::Begin("FPS Overlay", nullptr, windowFlags)) {
		// FPS text color based on performance
		ImVec4 fpsColor;
		if (m_currentFPS >= 60.0f) {
			fpsColor = ImVec4(0.0f, 1.0f, 0.0f,
					  1.0f); // Green for 60+ FPS
		} else if (m_currentFPS >= 30.0f) {
			fpsColor = ImVec4(1.0f, 1.0f, 0.0f,
					  1.0f); // Yellow for 30-60 FPS
		} else {
			fpsColor = ImVec4(1.0f, 0.0f, 0.0f,
					  1.0f); // Red for <30 FPS
		}

		ImGui::TextColored(fpsColor, "%.1f FPS", m_currentFPS);
		ImGui::Text("Batches: %d", m_lastBatchCount);

		ImGui::Separator();

		ImVec4 hintColor = ImVec4(1.0f, 1.0f, 1.0f, 0.5f);
		ImGui::TextColored(hintColor, "F12 to toggle");
	}
	ImGui::End();
}

void EditorUISystem::showCreatePrefabDialog(flecs::entity entity)
{
	ImGui::OpenPopup("Create Prefab");
	if (ImGui::BeginPopupModal("Create Prefab", &m_showCreatePrefabDialog,
				   ImGuiWindowFlags_AlwaysAutoResize)) {
		ImGui::InputText("Prefab Name", m_prefabNameBuffer,
				 sizeof(m_prefabNameBuffer));

		if (ImGui::Button("Save", ImVec2(120, 0))) {
			if (entity.is_alive() &&
			    m_prefabNameBuffer[0] != '\0') {
				std::string prefabPath =
					PrefabSystem::getPrefabsDirectory() +
					"/" + m_prefabNameBuffer + ".json";
				PrefabSystem prefabSys(m_world, m_sceneMgr);
				if (prefabSys.savePrefab(entity, prefabPath)) {
					// Convert source entity to prefab instance
					entity.set<PrefabInstanceComponent>(
						PrefabInstanceComponent{
							prefabPath, true });
					// Re-instantiate so children come
					// from prefab
					prefabSys.resolveInstances();
					m_refreshPrefabList = true;
				}
			}
			m_showCreatePrefabDialog = false;
			m_prefabSourceEntity = flecs::entity::null();
		}
		ImGui::SameLine();
		if (ImGui::Button("Cancel", ImVec2(120, 0))) {
			m_showCreatePrefabDialog = false;
			m_prefabSourceEntity = flecs::entity::null();
		}
		ImGui::EndPopup();
	}
}

void EditorUISystem::renderPrefabBrowser()
{
	if (!m_showPrefabBrowser)
		return;

	ImGui::SetNextWindowPos(ImVec2(LEFT_PANEL_WIDTH, 300),
				ImGuiCond_FirstUseEver);
	ImGui::SetNextWindowSize(ImVec2(250, 400), ImGuiCond_FirstUseEver);

	ImGuiWindowFlags flags = ImGuiWindowFlags_NoCollapse;
	if (ImGui::Begin("Prefab Browser", &m_showPrefabBrowser, flags)) {
		// Refresh prefab list
		if (m_refreshPrefabList) {
			m_prefabFiles.clear();
			std::string prefabDir =
				PrefabSystem::getPrefabsDirectory();
			if (std::filesystem::exists(prefabDir)) {
				for (const auto &entry :
				     std::filesystem::directory_iterator(
					     prefabDir)) {
					if (entry.is_regular_file() &&
					    entry.path().extension() ==
						    ".json") {
						m_prefabFiles.push_back(
							entry.path()
								.filename()
								.string());
					}
				}
			}
			m_refreshPrefabList = false;
		}

		// Refresh button
		if (ImGui::Button("Refresh")) {
			m_refreshPrefabList = true;
		}
		ImGui::SameLine();
		if (ImGui::Button("Create Instance")) {
			// Will show file picker or use selected prefab
		}
		ImGui::SameLine();
		ImGui::Checkbox("Root", &m_prefabInstAtRoot);
		if (ImGui::IsItemHovered())
			ImGui::SetTooltip(
				"Instantiate at root level (no parent)");

		ImGui::Separator();

		// Prefab list
		for (const auto &file : m_prefabFiles) {
			std::string path = PrefabSystem::getPrefabsDirectory() +
					   "/" + file;
			ImGui::Text("%s", file.c_str());
			ImGui::SameLine();

			std::string editId = "Edit##" + file;
			if (ImGui::Button(editId.c_str())) {
				SceneSerializer serializer(m_world, m_sceneMgr);
				flecs::entity prefabRoot =
					serializer.loadPrefabForEdit(path,
								     this);
				if (prefabRoot.is_alive()) {
					setSelectedEntity(prefabRoot);
				}
			}
			ImGui::SameLine();

			std::string instId = "Inst##" + file;
			if (ImGui::Button(instId.c_str())) {
				PrefabSystem prefabSys(m_world, m_sceneMgr);
				flecs::entity parent = flecs::entity::null();
				Ogre::Vector3 pos(0, 0, 0);

				if (m_prefabUseCursor && m_cursor3D &&
				    m_cursor3D->isVisible()) {
					// Use cursor position as base
					pos = m_cursor3D->getPosition();

					// Optional downward raycast with margin
					if (m_prefabRaycastMargin > 0.0f &&
					    m_physicsSystem &&
					    m_physicsSystem->isInitialized()) {
						JoltPhysicsWrapper *physics =
							m_physicsSystem
								->getPhysicsWrapper();
						if (physics) {
							Ogre::Vector3 start =
								pos +
								Ogre::Vector3(
									0,
									m_prefabRaycastMargin,
									0);
							Ogre::Vector3 end =
								pos +
								Ogre::Vector3(
									0,
									-1000.0f,
									0);
							Ogre::Vector3 hitPos;
							JPH::BodyID hitBody;
							if (physics->raycastQuery(
								    start, end,
								    hitPos,
								    hitBody)) {
								pos = hitPos +
								      Ogre::Vector3(
									      0,
									      m_prefabRaycastMargin,
									      0);
							}
						}
					}

					// If not at root, parent under selected entity
					if (!m_prefabInstAtRoot &&
					    m_selectedEntity.is_alive() &&
					    m_selectedEntity
						    .has<TransformComponent>()) {
						parent = m_selectedEntity;
						// Convert world pos to local
						auto &pt = m_selectedEntity.get<
							TransformComponent>();
						if (pt.node) {
							pos = pt.node->convertWorldToLocalPosition(
								pos);
						}
					}
				} else if (!m_prefabInstAtRoot &&
					   m_selectedEntity.is_alive() &&
					   m_selectedEntity
						   .has<TransformComponent>()) {
					parent = m_selectedEntity;
					// Local offset from parent
					pos = Ogre::Vector3(2, 0, 0);
				}

				auto instance = prefabSys.createInstance(
					path, parent, pos,
					file.substr(0, file.find_last_of('.'))
						.c_str(),
					this);
				if (instance.is_alive()) {
					setSelectedEntity(instance);
				}
			}
			ImGui::SameLine();

			// Delete prefab button
			std::string delId = "Del##" + file;
			if (ImGui::Button(delId.c_str())) {
				m_prefabToDelete = path;
				m_showDeletePrefabConfirm = true;
			}
		}

		// Delete prefab confirmation dialog
		if (m_showDeletePrefabConfirm) {
			ImGui::OpenPopup("Delete Prefab");
		}
		if (ImGui::BeginPopupModal("Delete Prefab",
					   &m_showDeletePrefabConfirm,
					   ImGuiWindowFlags_AlwaysAutoResize)) {
			ImGui::Text(
				"Are you sure you want to delete this prefab?");
			ImGui::Text("  %s", m_prefabToDelete.c_str());
			ImGui::Separator();
			ImGui::TextColored(ImVec4(1.0f, 0.3f, 0.3f, 1.0f),
					   "This action cannot be undone!");

			if (ImGui::Button("Delete", ImVec2(120, 0))) {
				PrefabSystem prefabSys(m_world, m_sceneMgr);
				if (prefabSys.deletePrefab(m_prefabToDelete)) {
					m_refreshPrefabList = true;
				}
				m_showDeletePrefabConfirm = false;
				m_prefabToDelete.clear();
			}
			ImGui::SameLine();
			if (ImGui::Button("Cancel", ImVec2(120, 0))) {
				m_showDeletePrefabConfirm = false;
				m_prefabToDelete.clear();
			}
			ImGui::EndPopup();
		}
	}
	ImGui::End();
}

void EditorUISystem::renderCursorPanel()
{
	if (!m_showCursorPanel)
		return;

	if (!m_cursor3D)
		return;

	ImGui::SetNextWindowPos(ImVec2(LEFT_PANEL_WIDTH, 100),
				ImGuiCond_FirstUseEver);
	ImGui::SetNextWindowSize(ImVec2(280, 350), ImGuiCond_FirstUseEver);

	ImGuiWindowFlags flags = ImGuiWindowFlags_NoCollapse;
	if (ImGui::Begin("3D Cursor", &m_showCursorPanel, flags)) {
		// Visibility toggle
		bool visible = m_cursor3D->isVisible();
		if (ImGui::Checkbox("Visible", &visible)) {
			m_cursor3D->setVisible(visible);
		}

		ImGui::Separator();

		// Interaction mode radio buttons
		ImGui::Text("Interaction Mode:");
		int mode = static_cast<int>(m_cursorMode);
		if (ImGui::RadioButton("None", &mode, 0)) {
			m_cursorMode = CursorInteractionMode::None;
		}
		ImGui::SameLine();
		if (ImGui::RadioButton("Place", &mode, 1)) {
			m_cursorMode = CursorInteractionMode::Place;
			if (!m_cursor3D->isVisible())
				m_cursor3D->setVisible(true);
		}
		if (ImGui::IsItemHovered()) {
			ImGui::SetTooltip(
				"Click in viewport to raycast-place cursor on surface");
		}
		ImGui::SameLine();
		if (ImGui::RadioButton("Move", &mode, 2)) {
			m_cursorMode = CursorInteractionMode::Translate;
			if (!m_cursor3D->isVisible())
				m_cursor3D->setVisible(true);
		}
		if (ImGui::IsItemHovered()) {
			ImGui::SetTooltip(
				"Click and drag an axis to translate along it");
		}
		ImGui::SameLine();
		if (ImGui::RadioButton("Rotate", &mode, 3)) {
			m_cursorMode = CursorInteractionMode::Rotate;
			if (!m_cursor3D->isVisible())
				m_cursor3D->setVisible(true);
		}
		if (ImGui::IsItemHovered()) {
			ImGui::SetTooltip(
				"Click and drag an axis to rotate around it");
		}

		if (m_cursor3D->isDragging()) {
			ImGui::SameLine();
			ImGui::TextColored(ImVec4(0, 1, 0, 1), "[Dragging]");
		}

		ImGui::Separator();

		// Position editor
		Ogre::Vector3 pos = m_cursor3D->getPosition();
		float posArr[3] = { pos.x, pos.y, pos.z };
		if (ImGui::DragFloat3("Position", posArr, 0.01f)) {
			m_cursor3D->setPosition(
				Ogre::Vector3(posArr[0], posArr[1], posArr[2]));
		}

		// Rotation editor (Euler angles)
		Ogre::Quaternion rot = m_cursor3D->getOrientation();
		float yaw = Ogre::Radian(rot.getYaw()).valueDegrees();
		float pitch = Ogre::Radian(rot.getPitch()).valueDegrees();
		float roll = Ogre::Radian(rot.getRoll()).valueDegrees();
		float rotArr[3] = { yaw, pitch, roll };
		if (ImGui::DragFloat3("Rotation (Y/P/R)", rotArr, 0.5f)) {
			Ogre::Quaternion q1(Ogre::Degree(rotArr[0]),
					    Ogre::Vector3::UNIT_Y);
			Ogre::Quaternion q2(Ogre::Degree(rotArr[1]),
					    Ogre::Vector3::UNIT_X);
			Ogre::Quaternion q3(Ogre::Degree(rotArr[2]),
					    Ogre::Vector3::UNIT_Z);
			m_cursor3D->setOrientation(q1 * q2 * q3);
		}

		// Size
		float size = m_cursor3D->getSize();
		if (ImGui::DragFloat("Size", &size, 0.01f, 0.1f, 10.0f)) {
			m_cursor3D->setSize(size);
		}

		ImGui::Separator();

		// Snap to selected entity
		if (ImGui::Button("Snap to Selected", ImVec2(120, 0))) {
			if (m_selectedEntity.is_alive() &&
			    m_selectedEntity.has<TransformComponent>()) {
				m_cursor3D->snapToTransform(
					m_selectedEntity
						.get<TransformComponent>());
			}
		}
		if (ImGui::IsItemHovered()) {
			ImGui::SetTooltip(
				"Copy selected entity's world position/rotation to cursor");
		}

		ImGui::SameLine();

		// Apply to selected entity
		if (ImGui::Button("Apply to Selected", ImVec2(120, 0))) {
			if (m_selectedEntity.is_alive() &&
			    m_selectedEntity.has<TransformComponent>()) {
				auto &transform =
					m_selectedEntity
						.get_mut<TransformComponent>();
				m_cursor3D->applyToTransform(transform);
				if (m_selectedEntity.has<
					    StaticGeometryMemberComponent>()) {
					m_selectedEntity
						.get_mut<
							StaticGeometryMemberComponent>()
						.markDirty();
				}
			}
		}
		if (ImGui::IsItemHovered()) {
			ImGui::SetTooltip(
				"Copy cursor position/rotation to selected entity");
		}

		ImGui::Separator();

		// Prefab placement settings
		ImGui::Text("Prefab Placement");
		ImGui::Checkbox("Use Cursor Position", &m_prefabUseCursor);
		if (ImGui::IsItemHovered()) {
			ImGui::SetTooltip(
				"Place prefabs at cursor position instead of selected entity");
		}
		ImGui::DragFloat("Raycast Margin", &m_prefabRaycastMargin,
				 0.01f, 0.0f, 10.0f);
		if (ImGui::IsItemHovered()) {
			ImGui::SetTooltip(
				"Vertical offset: raycast from cursor+margin downward, "
				"place prefab at hit point + margin");
		}
	}
	ImGui::End();
}

void EditorUISystem::renderDialogueSettingsWindow()
{
	ImGui::SetNextWindowPos(ImVec2(LEFT_PANEL_WIDTH, 100),
				ImGuiCond_FirstUseEver);
	ImGui::SetNextWindowSize(ImVec2(400, 500), ImGuiCond_FirstUseEver);

	ImGuiWindowFlags flags = ImGuiWindowFlags_NoCollapse;
	if (!ImGui::Begin("Dialogue Settings", &m_showDialogueSettings,
			  flags)) {
		ImGui::End();
		return;
	}

	DialogueSystem &ds = DialogueSystem::getInstance();
	DialogueSystem::Settings s = ds.getSettings();

	// --- Visual settings ---
	ImGui::Text("Visual Settings");
	ImGui::Separator();

	char fontNameBuf[256];
	std::strncpy(fontNameBuf, s.fontName.c_str(), sizeof(fontNameBuf) - 1);
	fontNameBuf[sizeof(fontNameBuf) - 1] = '\0';
	if (ImGui::InputText("Font Name", fontNameBuf, sizeof(fontNameBuf))) {
		s.fontName = fontNameBuf;
	}

	if (ImGui::DragFloat("Font Size", &s.fontSize, 0.5f, 8.0f, 72.0f)) {
	}
	if (ImGui::DragFloat("Speaker Font Size", &s.speakerFontSize, 0.5f,
			     8.0f, 72.0f)) {
	}
	if (ImGui::SliderFloat("Background Opacity", &s.backgroundOpacity, 0.0f,
			       1.0f)) {
	}
	if (ImGui::SliderFloat("Box Height Fraction", &s.boxHeightFraction,
			       0.05f, 0.5f)) {
	}
	if (ImGui::SliderFloat("Box Position Fraction", &s.boxPositionFraction,
			       0.0f, 1.0f)) {
	}

	if (ImGui::Button("Apply Settings")) {
		ds.setSettings(s);
	}
	ImGui::SameLine();
	if (ImGui::Button("Save to dialogue.json")) {
		if (ds.saveSettings("dialogue.json")) {
			Ogre::LogManager::getSingleton().logMessage(
				"Dialogue settings saved.");
		}
	}
	ImGui::SameLine();
	if (ImGui::Button("Load from dialogue.json")) {
		if (ds.loadSettings("dialogue.json")) {
			Ogre::LogManager::getSingleton().logMessage(
				"Dialogue settings loaded.");
		}
	}

	ImGui::Spacing();
	ImGui::Text("Preview");
	ImGui::Separator();

	static char sampleText[512] =
		"This is sample dialogue text for preview.";
	static char sampleSpeaker[128] = "Speaker";
	static char sampleChoices[512] = "Choice 1\nChoice 2\nChoice 3";
	static bool showPreview = false;

	ImGui::InputTextMultiline("Sample Text", sampleText, sizeof(sampleText),
				  ImVec2(0, 60));
	ImGui::InputText("Sample Speaker", sampleSpeaker,
			 sizeof(sampleSpeaker));
	ImGui::InputTextMultiline("Sample Choices (one per line)",
				  sampleChoices, sizeof(sampleChoices),
				  ImVec2(0, 60));

	if (ImGui::Checkbox("Show Preview", &showPreview)) {
		if (showPreview) {
			std::vector<Ogre::String> choices;
			std::istringstream iss(sampleChoices);
			std::string line;
			while (std::getline(iss, line)) {
				if (!line.empty())
					choices.push_back(line);
			}
			ds.show(sampleText, choices, sampleSpeaker);
			ds.setEditorPreviewEnabled(true);
		} else {
			ds.hide();
			ds.setEditorPreviewEnabled(false);
		}
	}

	if (showPreview && ds.isActive()) {
		if (ImGui::Button("Update Preview")) {
			std::vector<Ogre::String> choices;
			std::istringstream iss(sampleChoices);
			std::string line;
			while (std::getline(iss, line)) {
				if (!line.empty())
					choices.push_back(line);
			}
			ds.show(sampleText, choices, sampleSpeaker);
		}
		ImGui::SameLine();
		if (ImGui::Button("Hide Preview")) {
			showPreview = false;
			ds.hide();
			ds.setEditorPreviewEnabled(false);
		}
	}

	ImGui::End();
}
