// D:\Dev\Mosis\MosisService\designer\src\desktop_platform.cpp
// Include glad BEFORE GLFW
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include "desktop_platform.h"
#include <iostream>

namespace mosis {

// DesktopPlatform implementation

DesktopPlatform::DesktopPlatform(GLFWwindow* window, uint32_t width, uint32_t height)
    : m_window(window)
    , m_width(width)
    , m_height(height)
{
}

std::unique_ptr<IGraphicsContext> DesktopPlatform::CreateGraphicsContext() {
    // On desktop, GLFW manages the context, so we don't need a separate wrapper
    // Return nullptr to indicate context is already managed
    return nullptr;
}

std::unique_ptr<IRenderTarget> DesktopPlatform::CreateRenderTarget(uint32_t width, uint32_t height) {
    auto target = std::make_unique<DesktopRenderTarget>();
    if (target->Create(width, height)) {
        return target;
    }
    return nullptr;
}

Rml::FileInterface& DesktopPlatform::GetFileInterface() {
    return m_file_interface;
}

void DesktopPlatform::Log(const std::string& message) {
    std::cout << message << std::endl;
}

bool DesktopPlatform::PollEvents() {
    glfwPollEvents();
    return !glfwWindowShouldClose(m_window);
}

void DesktopPlatform::SwapBuffers() {
    glfwSwapBuffers(m_window);
}

void DesktopPlatform::SetResolution(uint32_t width, uint32_t height) {
    m_width = width;
    m_height = height;
    glfwSetWindowSize(m_window, width, height);
}

void DesktopPlatform::SetAssetsPath(const std::string& path) {
    m_file_interface.SetAssetsPath(path);
}

// DesktopRenderTarget implementation

DesktopRenderTarget::~DesktopRenderTarget() {
    Destroy();
}

bool DesktopRenderTarget::Create(uint32_t width, uint32_t height) {
    m_width = width;
    m_height = height;

    // Create framebuffer
    glGenFramebuffers(1, &m_framebuffer);
    glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);

    // Create color texture
    glGenTextures(1, &m_texture);
    glBindTexture(GL_TEXTURE_2D, m_texture);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture, 0);

    // Create depth/stencil renderbuffer
    glGenRenderbuffers(1, &m_depth_buffer);
    glBindRenderbuffer(GL_RENDERBUFFER, m_depth_buffer);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_depth_buffer);

    // Check completeness
    if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
        Destroy();
        return false;
    }

    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    return true;
}

void DesktopRenderTarget::Bind() {
    glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
    glViewport(0, 0, m_width, m_height);
}

void DesktopRenderTarget::Unbind() {
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
}

void DesktopRenderTarget::Destroy() {
    if (m_depth_buffer) {
        glDeleteRenderbuffers(1, &m_depth_buffer);
        m_depth_buffer = 0;
    }
    if (m_texture) {
        glDeleteTextures(1, &m_texture);
        m_texture = 0;
    }
    if (m_framebuffer) {
        glDeleteFramebuffers(1, &m_framebuffer);
        m_framebuffer = 0;
    }
}

} // namespace mosis
