#include "EditorUISystem.hpp"
#include "../ui/ComponentEditorRegistry.hpp"
#include "../ui/TransformEditor.hpp"
#include "../ui/RenderableEditor.hpp"
#include <imgui.h>
#include <algorithm>

EditorUISystem::EditorUISystem(flecs::world &world,
                   Ogre::SceneManager *sceneMgr,
                   Ogre::Vector3 &cursorPos)
    : m_world(world)
    , m_sceneMgr(sceneMgr)
    , m_cursorPosition(cursorPos)
    , m_nameQuery(world.query<EntityNameComponent>())
    , m_editorRegistry()
{
    registerEditors();
    refreshEntityList();
}

EditorUISystem::~EditorUISystem()
{
}

void EditorUISystem::registerEditors()
{
    // Register transform editor - using the template version
    auto transformEditor =
        std::make_unique<TransformEditor>(m_cursorPosition, [this]() {
            if (m_onCursorMoved) {
                m_onCursorMoved(m_cursorPosition);
            }
        });
    m_editorRegistry.registerEditor<TransformComponent>(
        std::move(transformEditor));

    // Register renderable editor - using the template version
    auto renderableEditor = std::make_unique<RenderableEditor>(m_sceneMgr);
    m_editorRegistry.registerEditor<RenderableComponent>(
        std::move(renderableEditor));
}

void EditorUISystem::setOnCursorMoved(
    std::function<void(const Ogre::Vector3 &)> callback)
{
    m_onCursorMoved = callback;
}

void EditorUISystem::update()
{
    renderHierarchyWindow();
    renderPropertyWindow();
}

void EditorUISystem::renderHierarchyWindow()
{
    ImGui::Begin("Scene Hierarchy", nullptr, ImGuiWindowFlags_NoCollapse);

    if (ImGui::Button("Create Entity")) {
        flecs::entity entity = m_world.entity();
        entity.set<EntityNameComponent>({ "New Entity" });

        // Create transform component with scene node
        TransformComponent transform;
        transform.node =
            m_sceneMgr->getRootSceneNode()->createChildSceneNode();
        transform.position = Ogre::Vector3::ZERO;
        entity.set<TransformComponent>(transform);

        refreshEntityList();
    }

    ImGui::Separator();

    static float lastRefresh = 0;
    if (ImGui::GetTime() - lastRefresh > 1.0f) {
        refreshEntityList();
        lastRefresh = ImGui::GetTime();
    }

    // Display entities using query
    m_nameQuery.each([this](flecs::entity e, EntityNameComponent &name) {
        if (!e.is_alive())
            return;

        std::string displayName =
            name.name.empty() ?
                ("Entity " + std::to_string(e.id())) :
                name.name;

        ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_Leaf |
                       ImGuiTreeNodeFlags_NoTreePushOnOpen;
        if (m_selectedEntity == e) {
            flags |= ImGuiTreeNodeFlags_Selected;
        }

        ImGui::TreeNodeEx(displayName.c_str(), flags);

        if (ImGui::IsItemClicked()) {
            setSelectedEntity(e);
        }

        if (ImGui::BeginPopupContextItem()) {
            renderEntityContextMenu(e);
            ImGui::EndPopup();
        }

        // Component indicators
        if (e.has<TransformComponent>()) {
            ImGui::SameLine();
            ImGui::TextDisabled("[Transform]");
        }
        if (e.has<RenderableComponent>()) {
            ImGui::SameLine();
            ImGui::TextDisabled("[Mesh]");
        }
    });

    ImGui::End();
}

void EditorUISystem::renderEntityContextMenu(flecs::entity entity)
{
    if (ImGui::MenuItem("Delete")) {
        // Clean up scene node
        if (entity.has<TransformComponent>()) {
            auto &transform = entity.get_mut<TransformComponent>();
            if (transform.node) {
                m_sceneMgr->destroySceneNode(transform.node);
                transform.node = nullptr;
            }
        }

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

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

    ImGui::Separator();

    if (ImGui::MenuItem("Add Transform Component")) {
        if (!entity.has<TransformComponent>()) {
            TransformComponent transform;
            transform.node = m_sceneMgr->getRootSceneNode()
                         ->createChildSceneNode();
            transform.position = Ogre::Vector3::ZERO;
            entity.set<TransformComponent>(transform);
        }
    }

    if (ImGui::MenuItem("Add Mesh Component")) {
        if (!entity.has<RenderableComponent>()) {
            entity.set<RenderableComponent>({});
        }
    }
}

void EditorUISystem::renderPropertyWindow()
{
    ImGui::Begin("Properties", nullptr, ImGuiWindowFlags_NoCollapse);

    if (m_selectedEntity && m_selectedEntity.is_alive()) {
        // Entity name editing
        if (m_selectedEntity.has<EntityNameComponent>()) {
            auto &name =
                m_selectedEntity.get_mut<EntityNameComponent>();
            static char nameBuffer[256];
            strcpy(nameBuffer, name.name.c_str());
            if (ImGui::InputText("Entity Name", nameBuffer,
                         sizeof(nameBuffer))) {
                name.name = nameBuffer;
            }
        }

        ImGui::Separator();

        render3DCursorControls();

        ImGui::Separator();

        renderComponentEditors(m_selectedEntity);
    } else {
        ImGui::Text("No entity selected");
        render3DCursorControls();
    }

    ImGui::End();
}

void EditorUISystem::render3DCursorControls()
{
    if (ImGui::CollapsingHeader("3D Cursor",
                    ImGuiTreeNodeFlags_DefaultOpen)) {
        ImGui::Indent();

        float cursorPos[3] = { m_cursorPosition.x, m_cursorPosition.y,
                       m_cursorPosition.z };
        if (ImGui::DragFloat3("Cursor Position", cursorPos, 0.1f)) {
            m_cursorPosition = Ogre::Vector3(
                cursorPos[0], cursorPos[1], cursorPos[2]);
            if (m_onCursorMoved) {
                m_onCursorMoved(m_cursorPosition);
            }
        }

        ImGui::Text("Tip: Ctrl+Click in scene view to move cursor");

        if (ImGui::Button("Reset Cursor")) {
            m_cursorPosition = Ogre::Vector3::ZERO;
            if (m_onCursorMoved) {
                m_onCursorMoved(m_cursorPosition);
            }
        }

        ImGui::Unindent();
    }
}

void EditorUISystem::renderComponentEditors(flecs::entity entity)
{
    // Render Transform component if present
    if (entity.has<TransformComponent>()) {
        auto &transform = entity.get_mut<TransformComponent>();
        m_editorRegistry.renderComponent<TransformComponent>(entity,
                                     transform);
    }

    // Render Renderable component if present
    if (entity.has<RenderableComponent>()) {
        auto &renderable = entity.get_mut<RenderableComponent>();
        m_editorRegistry.renderComponent<RenderableComponent>(
            entity, renderable);
    }
}

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

void EditorUISystem::refreshEntityList()
{
    m_entityList.clear();

    m_nameQuery.each([this](flecs::entity e, EntityNameComponent &name) {
        m_entityList.push_back(e);
    });
}
