// src/Window.cpp

#include "Window.h"
#include "glad.h"
#include <iostream>

// Static storage for user callbacks
static std::function<void(int, int)> g_resizeCallback;
static std::function<void(int, int, int, int)> g_keyCallback;

Window::Window(int width, int height, const std::string& title)
    : width_(width), height_(height), title_(title) {
    Initialize();
}

Window::~Window() {
    Cleanup();
}

// Move constructor
Window::Window(Window&& other) noexcept
    : window_(other.window_), width_(other.width_), height_(other.height_), title_(std::move(other.title_)) {
    other.window_ = nullptr;
}

// Move assignment
Window& Window::operator=(Window&& other) noexcept {
    if (this != &other) {
        Cleanup();
        window_ = other.window_;
        width_  = other.width_;
        height_ = other.height_;
        title_  = std::move(other.title_);
        other.window_ = nullptr;
    }
    return *this;
}

void Window::Initialize() {
    if (!glfwInit()) {
        std::cerr << "Failed to initialize GLFW\n";
        return;
    }

    // Create window with OpenGL context
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    window_ = glfwCreateWindow(width_, height_, title_.c_str(), nullptr, nullptr);
    if (!window_) {
        std::cerr << "Failed to create GLFW window\n";
        glfwTerminate();
        return;
    }

    glfwMakeContextCurrent(window_);
    glfwSetFramebufferSizeCallback(window_, FramebufferSizeCallback);
    glfwSetKeyCallback(window_, KeyCallback);
}

// Cleans up GLFW window and terminates GLFW if needed
void Window::Cleanup() {
    if (window_) {
        glfwDestroyWindow(window_);
        window_ = nullptr;
    }
    glfwTerminate();
}

void Window::PollEvents() const {
    glfwPollEvents();
}

bool Window::ShouldClose() const {
    return glfwWindowShouldClose(window_);
}

void Window::SwapBuffers() const {
    glfwSwapBuffers(window_);
}

void Window::SetVSync(bool enable) const {
    glfwSwapInterval(enable ? 1 : 0);
}

void Window::SetResizeCallback(std::function<void(int, int)> callback) {
    g_resizeCallback = std::move(callback);
}

void Window::SetKeyCallback(std::function<void(int, int, int, int)> callback) {
    g_keyCallback = std::move(callback);
}

// Static GLFW callbacks
void Window::FramebufferSizeCallback(GLFWwindow* window, int width, int height) {
    if (g_resizeCallback) {
        g_resizeCallback(width, height);
    }
}

void Window::KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods) {
    if (g_keyCallback) {
        g_keyCallback(key, scancode, action, mods);
    }
}
