// IAEngine: 2D Game Engine by IA
// Copyright (C) 2025 IASoft (PVT) LTD (oss@iasoft.dev)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.

#include <IAEngine/Engine.hpp>
#include <Renderer/Renderer.hpp>
#include <Renderer/DebugDraw.hpp>

#include <Physics.hpp>
#include <WorldManager.hpp>

#include <IAEngine/imgui/backends/imgui_impl_sdl3.h>
#include <IAEngine/imgui/backends/imgui_impl_sdlgpu3.h>

#include <IAEngine/EngineLibraryInterface.hpp>

namespace ia::iae
{
    EXTERN SDL_Window *g_windowHandle;

    ImGuiIO g_imGUIIO{};

    VOID DebugDraw::Initialize()
    {
        const auto mainScale = SDL_GetDisplayContentScale(SDL_GetPrimaryDisplay());

        IMGUI_CHECKVERSION();
        ImGui::CreateContext();
        g_imGUIIO = ImGui::GetIO();
        g_imGUIIO.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
        g_imGUIIO.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;

        ImGui::StyleColorsClassic();

        ImGuiStyle &style = ImGui::GetStyle();
        style.ScaleAllSizes(mainScale);
        style.FontScaleDpi = mainScale;

        ImGui_ImplSDLGPU3_InitInfo initInfo{.Device = Renderer::GetDevice(),
                                            .ColorTargetFormat =
                                                Renderer::GetRenderTargetFormat(),
                                            .PresentMode = SDL_GPU_PRESENTMODE_VSYNC};
        ImGui_ImplSDL3_InitForSDLGPU(g_windowHandle);
        ImGui_ImplSDLGPU3_Init(&initInfo);
    }

    VOID DebugDraw::Terminate()
    {
        ImGui_ImplSDL3_Shutdown();
        ImGui_ImplSDLGPU3_Shutdown();
        ImGui::DestroyContext();
    }

    VOID DebugDraw::Render()
    {
        ImGui_ImplSDLGPU3_NewFrame();
        ImGui_ImplSDL3_NewFrame();
        ImGui::NewFrame();

        Physics::DebugDraw();
        WorldManager::DebugDraw();
        Game_OnDebugDraw();

        ImGui::Render();
    }
} // namespace ia::iae

namespace ia::iae
{
    struct State
    {
        ImU32 ActiveColor{0xFFFFFFFF};
        FLOAT32 ActiveStrokeWidth{1.0f};
    } g_debugDrawState{};

    VOID Engine::DebugDraw_SetColor(IN Color color)
    {
        g_debugDrawState.ActiveColor = IM_COL32(color.R, color.G, color.B, color.A);
    }

    VOID Engine::DebugDraw_SetStrokeWidth(IN FLOAT32 width)
    {
        g_debugDrawState.ActiveStrokeWidth = width;
    }

    VOID Engine::DebugDraw_Line(IN Vec2 from, IN Vec2 to)
    {
        const auto drawList = ImGui::GetForegroundDrawList();
        drawList->AddLine(ImVec2(from.x, from.y), ImVec2(to.x, to.y), g_debugDrawState.ActiveColor, g_debugDrawState.ActiveStrokeWidth);
    }

    VOID Engine::DebugDraw_FillRect(IN Vec2 position, IN Vec2 size)
    {
        const auto drawList = ImGui::GetForegroundDrawList();
        drawList->AddRectFilled(ImVec2(position.x, position.y), ImVec2(position.x + size.x, position.y + size.y), g_debugDrawState.ActiveColor);
    }

    VOID Engine::DebugDraw_StrokeRect(IN Vec2 position, IN Vec2 size)
    {
        const auto drawList = ImGui::GetForegroundDrawList();
        drawList->AddRect(ImVec2(position.x, position.y), ImVec2(position.x + size.x, position.y + size.y), g_debugDrawState.ActiveColor, g_debugDrawState.ActiveStrokeWidth);
    }
} // namespace ia::iae