//
// Created by spenc on 5/18/2025.
//

#include "Editor.h"
#include <functional>




#include "types/all.h"


#include "Windows/LoggerWindow.h"
#include "Windows/Viewport.h"
#include "Windows/FileBrowser.h"
#include "Windows/InspectorWindow.h"
#include "Windows/SceneExplorer.h"

namespace OX
{
    void Editor::Init(Core &core)
    {
        Logger::LogInfo("%s Init", m_name.c_str());


        m_name = OX_EDITOR_VERSION;


        IMGUI_CHECKVERSION();
        ImGui::CreateContext();
        ImGuiIO &io = ImGui::GetIO();

        io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
        io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;

        ImGui::StyleColorsDark();

        ImGuiStyle &style = ImGui::GetStyle();
        if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) {
            style.WindowRounding = 5.0f;
            style.Colors[ImGuiCol_WindowBg].w = 1.0f;
        }

        ImGui_ImplGlfw_InitForOpenGL(core.GetWindow().GetHandle(), true);
        ImGui_ImplOpenGL3_Init("#version 330 core");

        fileBrowser = std::make_shared<FileBrowser>();
        primaryViewport = std::make_shared<Viewport>();
        inspectorWindow = std::make_shared<InspectorWindow>();
        sceneExplorer = std::make_shared<SceneExplorer>();

        LoggerWindow::Init();


        core.GetScene().createRootObject("Welcome!");
    }

    void Editor::Update(Core &core)
    {
        OX_PROFILE_FUNCTION();
    }

    void Editor::Draw(Core &core)
    {
        OX_PROFILE_FUNCTION();


        ImGui_ImplOpenGL3_NewFrame();
        ImGui_ImplGlfw_NewFrame();
        ImGui::NewFrame();


        // === Main Docking Space ===
        ImGuiWindowFlags windowFlags = ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking |
                                       ImGuiWindowFlags_NoBackground;

        const ImGuiViewport *viewport = ImGui::GetMainViewport();
        ImGui::SetNextWindowPos(viewport->WorkPos);
        ImGui::SetNextWindowSize(viewport->WorkSize);
        ImGui::SetNextWindowViewport(viewport->ID);
        ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
        ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
        ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
        windowFlags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize |
                ImGuiWindowFlags_NoMove;
        windowFlags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus;

        ImGui::Begin("DockSpace Root", nullptr, windowFlags);
        ImGui::PopStyleVar(3);

        ImGuiID dockspaceID = ImGui::GetID("MyDockSpace");
        ImGui::DockSpace(dockspaceID, ImVec2(0.0f, 0.0f), ImGuiDockNodeFlags_PassthruCentralNode);

        LoggerWindow::Draw();
        fileBrowser->Draw();
        primaryViewport->Draw(core);
        inspectorWindow->Draw(core, *this);
        sceneExplorer->Draw(core, *this);


        ImGui::Begin("Profiler");

        const auto &tree = Profiler::GetSavedTree();
        if (tree.empty()) {
            ImGui::Text("No samples yet.");
        } else {
            if (ImGui::BeginTable("ProfilerTable", 3,
                                  ImGuiTableFlags_Resizable | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersInnerV)) {
                ImGui::TableSetupColumn("Section");
                ImGui::TableSetupColumn("Calls", ImGuiTableColumnFlags_WidthFixed, 60.0f);
                ImGui::TableSetupColumn("Total Time (ms)", ImGuiTableColumnFlags_WidthFixed, 120.0f);
                ImGui::TableHeadersRow();

                std::function<void(const Profiler::SavedSample &)> DrawNode;
                DrawNode = [&](const Profiler::SavedSample &node)
                {
                    ImGui::TableNextRow();

                    // === Section name with Tree UI ===
                    ImGui::TableNextColumn();

                    // Color based on total time
                    ImVec4 color;
                    if (node.totalTime > 10.0f) color = ImVec4(1.0f, 0.2f, 0.2f, 1.0f); // red
                    else if (node.totalTime > 5.0f) color = ImVec4(1.0f, 0.5f, 0.0f, 1.0f); // orange
                    else if (node.totalTime > 1.0f) color = ImVec4(1.0f, 1.0f, 0.0f, 1.0f); // yellow
                    else color = ImVec4(0.4f, 1.0f, 0.4f, 1.0f); // green

                    ImGui::PushStyleColor(ImGuiCol_Text, color);
                    bool open = ImGui::TreeNodeEx(node.name.c_str(),
                                                  ImGuiTreeNodeFlags_SpanAllColumns | ImGuiTreeNodeFlags_DefaultOpen);
                    ImGui::PopStyleColor();

                    // === Call count ===
                    ImGui::TableNextColumn();
                    ImGui::Text("%d", node.callCount);

                    // === Total time ===
                    ImGui::TableNextColumn();
                    ImGui::Text("%.2f", node.totalTime);

                    // === Recurse if open ===
                    if (open) {
                        for (const auto &child: node.children) {
                            DrawNode(child);
                        }
                        ImGui::TreePop();
                    }
                };

                for (const auto &root: tree) {
                    DrawNode(root);
                }

                ImGui::EndTable();
            }
        }

        ImGui::End();


        ImGui::End(); // DockSpace Root

        // --- Render ImGui onto FBO 0 ---
        {
            ImGui::EndFrame();
            ImGui::Render();
            ImGui::UpdatePlatformWindows();
            ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
        }
    }

    void Editor::Shutdown(Core &core)
    {
        ImGui_ImplOpenGL3_Shutdown();
        ImGui_ImplGlfw_Shutdown();
        ImGui::DestroyContext();
    }
} // OX
