#include "RenderLayerPanel.h"
#include "../core/commands/RenderLayerCommands.h"
#include "../core/commands/RenderLayerMembershipCommand.h"
#include <pxr/usd/usd/prim.h>
#include <imgui.h>
#include <cstring>

namespace UsdLayerManager {

RenderLayerPanel::RenderLayerPanel() {}
RenderLayerPanel::~RenderLayerPanel() {}

void RenderLayerPanel::SetStage(pxr::UsdStageRefPtr stage) {
    m_stage = stage;
    m_defaultSelected = true;
    m_selectedLayerId.clear();
}

// ---------------------------------------------------------------------------
void RenderLayerPanel::Render() {
    if (!m_renderLayerManager) {
        ImGui::TextDisabled("No stage loaded");
        return;
    }

    ImGui::Text("Render Layers");
    ImGui::Separator();

    ImGui::SetNextItemWidth(180.0f);
    ImGui::InputText("##newLayerName", m_newLayerNameBuf, sizeof(m_newLayerNameBuf));
    ImGui::SameLine();
    if (ImGui::Button("Create Layer")) {
        std::string name = m_newLayerNameBuf[0] ? m_newLayerNameBuf : "RenderLayer";
        std::string newId;
        if (m_commandHistory) {
            auto cmd = std::make_unique<RenderLayerCreateCommand>(m_renderLayerManager, name);
            RenderLayerCreateCommand* raw = cmd.get();
            m_commandHistory->Push(std::move(cmd));
            newId = raw->GetCreatedLayerId();
        } else {
            newId = m_renderLayerManager->CreateRenderLayer(name);
        }
        if (!newId.empty()) {
            m_defaultSelected  = false;
            m_selectedLayerId  = newId;
        }
    }

    ImGui::Checkbox("Auto-save active layer", &m_autoSave);
    if (ImGui::IsItemHovered())
        ImGui::SetTooltip(
            "Writes the active render layer's .usda file shortly after each edit.\n"
            "The stage itself (root layer and other sublayers) still needs Ctrl+S.");

    ImGui::Spacing();
    RenderLayerList();

    ImGui::Spacing();
    ImGui::Separator();
    ImGui::TextDisabled("Membership");
    ImGui::Separator();
    RenderMembershipPanel();

    RenderRenameModal();
}

// ---------------------------------------------------------------------------
void RenderLayerPanel::RenderLayerList() {
    auto layers = m_renderLayerManager->GetRenderLayers();

    if (!ImGui::BeginTable("RenderLayerTable", 3,
            ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersInnerV |
            ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_ScrollY,
            ImVec2(0, 150)))
        return;

    ImGui::TableSetupColumn("##active", ImGuiTableColumnFlags_WidthFixed, 24.0f);
    ImGui::TableSetupColumn("Name",     ImGuiTableColumnFlags_WidthStretch);
    ImGui::TableSetupColumn("##dirty",  ImGuiTableColumnFlags_WidthFixed, 14.0f);

    for (int i = 0; i < static_cast<int>(layers.size()); ++i) {
        const auto& li = layers[i];
        ImGui::TableNextRow();
        ImGui::PushID(i);

        // Col 0: activate radio button.
        ImGui::TableSetColumnIndex(0);
        {
            bool isActive = li.isActive;
            if (ImGui::RadioButton("##act", isActive) && !isActive) {
                std::string target = li.isDefault ? std::string() : li.layerIdentifier;
                if (m_commandHistory)
                    m_commandHistory->Push(
                        std::make_unique<RenderLayerActivateCommand>(m_renderLayerManager, target));
                else if (li.isDefault)
                    m_renderLayerManager->ActivateDefaultLayer();
                else
                    m_renderLayerManager->ActivateRenderLayer(target);
            }
            if (ImGui::IsItemHovered())
                ImGui::SetTooltip(isActive ? "Active" : "Click to activate");
        }

        // Col 1: name — selecting a row picks which layer's membership shows below.
        ImGui::TableSetColumnIndex(1);
        {
            bool selected = li.isDefault
                ? m_defaultSelected
                : (!m_defaultSelected && m_selectedLayerId == li.layerIdentifier);
            ImVec4 nameColor = li.isActive ? ImVec4(0.5f, 1.0f, 0.5f, 1.0f)
                                            : ImVec4(1.0f, 1.0f, 1.0f, 1.0f);
            ImGui::PushStyleColor(ImGuiCol_Text, nameColor);
            if (ImGui::Selectable(li.name.c_str(), selected,
                    ImGuiSelectableFlags_SpanAllColumns)) {
                m_defaultSelected = li.isDefault;
                m_selectedLayerId = li.isDefault ? std::string() : li.layerIdentifier;
            }
            ImGui::PopStyleColor();

            if (!li.isDefault && ImGui::BeginPopupContextItem()) {
                if (ImGui::MenuItem("Rename")) {
                    m_openRenameModal = true;
                    m_renameTargetId  = li.layerIdentifier;
                    std::strncpy(m_renameBuf, li.name.c_str(), sizeof(m_renameBuf) - 1);
                    m_renameBuf[sizeof(m_renameBuf) - 1] = '\0';
                }
                if (ImGui::MenuItem("Delete")) {
                    if (m_commandHistory)
                        m_commandHistory->Push(
                            std::make_unique<RenderLayerDeleteCommand>(m_renderLayerManager, li.layerIdentifier));
                    else
                        m_renderLayerManager->DeleteRenderLayer(li.layerIdentifier);
                    if (!m_defaultSelected && m_selectedLayerId == li.layerIdentifier) {
                        m_defaultSelected = true;
                        m_selectedLayerId.clear();
                    }
                }
                ImGui::EndPopup();
            }
        }

        // Col 2: dirty indicator.
        ImGui::TableSetColumnIndex(2);
        if (!li.isDefault && li.layer && li.layer->IsDirty())
            ImGui::TextColored(ImVec4(1.0f, 0.6f, 0.2f, 1.0f), "*");
        else
            ImGui::TextDisabled(" ");

        ImGui::PopID();
    }

    ImGui::EndTable();
}

// ---------------------------------------------------------------------------
void RenderLayerPanel::RenderMembershipPanel() {
    if (m_defaultSelected) {
        ImGui::TextDisabled("Default has no membership of its own - it always shows the full, unmodified stage.");
        return;
    }
    if (m_selectedLayerId.empty()) {
        ImGui::TextDisabled("Select a render layer above to edit its membership.");
        return;
    }

    std::string displayName = m_selectedLayerId;
    for (const auto& li : m_renderLayerManager->GetRenderLayers())
        if (!li.isDefault && li.layerIdentifier == m_selectedLayerId) { displayName = li.name; break; }
    ImGui::Text("Members of \"%s\"", displayName.c_str());

    auto members = m_renderLayerManager->GetMembers(m_selectedLayerId);

    auto isValid = [&](const pxr::SdfPath& p) {
        return m_stage && m_stage->GetPrimAtPath(p).IsValid();
    };

    bool anyMissing = false;
    for (const auto& p : members)
        if (!isValid(p)) { anyMissing = true; break; }

    if (m_sceneHierarchyPanel && ImGui::Button("Add Selected")) {
        auto paths = m_sceneHierarchyPanel->GetSelectedPaths();
        if (!paths.empty()) {
            std::vector<pxr::SdfPath> sdfPaths;
            sdfPaths.reserve(paths.size());
            for (const auto& p : paths) sdfPaths.emplace_back(p);
            if (m_commandHistory)
                m_commandHistory->Push(std::make_unique<RenderLayerAddMembersCommand>(
                    m_renderLayerManager, m_selectedLayerId, sdfPaths));
            else
                for (const auto& sp : sdfPaths) m_renderLayerManager->AddMember(m_selectedLayerId, sp);
        }
    }
    if (anyMissing) {
        ImGui::SameLine();
        if (ImGui::Button("Remove Missing")) {
            std::vector<pxr::SdfPath> toRemove;
            for (const auto& p : members)
                if (!isValid(p)) toRemove.push_back(p);
            if (m_commandHistory)
                m_commandHistory->Push(std::make_unique<RenderLayerRemoveMembersCommand>(
                    m_renderLayerManager, m_selectedLayerId, toRemove));
            else
                for (const auto& p : toRemove) m_renderLayerManager->RemoveMember(m_selectedLayerId, p);
        }
    }

    if (members.empty()) {
        ImGui::TextDisabled("No members. Select lights/objects in Scene Hierarchy and click \"Add Selected\".");
        return;
    }

    if (ImGui::BeginChild("RenderLayerMembersList", ImVec2(0, 0), true)) {
        for (const auto& path : members) {
            ImGui::PushID(path.GetString().c_str());
            bool missing = !isValid(path);

            if (missing) ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.45f, 0.45f, 1.0f));
            ImGui::TextUnformatted(path.GetText());
            if (missing) {
                ImGui::PopStyleColor();
                ImGui::SameLine();
                ImGui::TextDisabled("(missing)");
            }

            ImGui::SameLine();
            ImGui::SetCursorPosX(ImGui::GetWindowContentRegionMax().x - 24.0f);
            if (ImGui::SmallButton("x")) {
                if (m_commandHistory)
                    m_commandHistory->Push(std::make_unique<RenderLayerRemoveMembersCommand>(
                        m_renderLayerManager, m_selectedLayerId, std::vector<pxr::SdfPath>{path}));
                else
                    m_renderLayerManager->RemoveMember(m_selectedLayerId, path);
            }
            ImGui::PopID();
        }
    }
    ImGui::EndChild();
}

// ---------------------------------------------------------------------------
void RenderLayerPanel::RenderRenameModal() {
    if (m_openRenameModal) {
        ImGui::OpenPopup("Rename Render Layer");
        m_openRenameModal = false;
    }
    if (ImGui::BeginPopupModal("Rename Render Layer", nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
        ImGui::SetNextItemWidth(240.0f);
        bool enterPressed = ImGui::InputText("Name", m_renameBuf, sizeof(m_renameBuf),
                                             ImGuiInputTextFlags_EnterReturnsTrue);
        bool okClicked = ImGui::Button("OK");
        ImGui::SameLine();
        bool cancelClicked = ImGui::Button("Cancel");

        if ((enterPressed || okClicked) && m_renameBuf[0]) {
            if (m_commandHistory)
                m_commandHistory->Push(std::make_unique<RenderLayerRenameCommand>(
                    m_renderLayerManager, m_renameTargetId, std::string(m_renameBuf)));
            else
                m_renderLayerManager->RenameRenderLayer(m_renameTargetId, m_renameBuf);
            ImGui::CloseCurrentPopup();
        } else if (cancelClicked) {
            ImGui::CloseCurrentPopup();
        }
        ImGui::EndPopup();
    }
}

} // namespace UsdLayerManager
