//
// Created by sebastian on 23.12.25.
//

#include "GLFWWindow.h"

#include <iostream>

static bool s_GLFWINITIALIZED = false;

Window* Window::Create(const WindowProps& props)
{
    return new GLFWWindow(props);
}


GLFWWindow::GLFWWindow(const WindowProps& props)
{
    Init(props);
}

GLFWWindow::~GLFWWindow()
{
    Shutdown();
}

void GLFWWindow::Init(const WindowProps& props)
{
    m_Data.Title = props.Title;
    m_Data.Width = props.Width;
    m_Data.Height = props.Height;
    m_Data.VSync = props.VSync;

    if (!s_GLFWINITIALIZED)
    {
        if (!glfwInit())
        {
            std::cerr << "Failed to initialize GLFW" << std::endl;
            return;
        }
    }

    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    m_Window = glfwCreateWindow(
        static_cast<int>(m_Data.Width), static_cast<int>(m_Data.Height), m_Data.Title.c_str(), nullptr, nullptr);

    glfwMakeContextCurrent(m_Window);

    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
        std::cerr << "Failed to initialize GLAD!\n";
        return;
    }

    glfwSetWindowUserPointer(m_Window, &m_Data);

    glfwSetFramebufferSizeCallback(m_Window,
       [](GLFWwindow* window, int width, int height)
       {
           auto& data = *(WindowData*)glfwGetWindowUserPointer(window);
           data.Width = width;
           data.Height = height;

           glViewport(0, 0, width, height);

           // Später:
           // EventSystem::Dispatch(WindowResizeEvent(width, height));
       }
   );
    std::cout << "OpenGL Info:\n";
    std::cout << "  Vendor:   " << glGetString(GL_VENDOR) << "\n";
    std::cout << "  Renderer: " << glGetString(GL_RENDERER) << "\n";
    std::cout << "  Version:  " << glGetString(GL_VERSION) << "\n";

}

void GLFWWindow::SetVSync(bool enabled)
{
    glfwSwapInterval(enabled ? 1 : 0);
    m_Data.VSync = enabled;
}

bool GLFWWindow::shouldClose() const
{
    return glfwWindowShouldClose(m_Window);
}

void GLFWWindow::OnUpdate()
{
    glfwPollEvents();
    glfwSwapBuffers(m_Window);
}

void GLFWWindow::Shutdown() const
{
    glfwDestroyWindow(m_Window);
}
