#pragma once
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#include <string>
#include <memory>
#include <functional>

class Window {
public:
    Window(int width, int height, const std::string& title);
    ~Window();

    // Delete copy constructor and assignment operator (RAII principle)
    Window(const Window&) = delete;
    Window& operator=(const Window&) = delete;

    // Move semantics (C++11 and later)
    Window(Window&& other) noexcept;
    Window& operator=(Window&& other) noexcept;

    void PollEvents() const;
    bool ShouldClose() const;
    void SwapBuffers() const;
    void SetVSync(bool enable) const;
    
    GLFWwindow* Handle() const { return window_; }
    
    // Modern C++ getters using [[nodiscard]] (C++17)
    [[nodiscard]] int GetWidth() const { return width_; }
    [[nodiscard]] int GetHeight() const { return height_; }
    [[nodiscard]] float GetAspectRatio() const { return static_cast<float>(width_) / static_cast<float>(height_); }

    // Callback setters using std::function (more flexible than raw function pointers)
    void SetResizeCallback(std::function<void(int, int)> callback);
    void SetKeyCallback(std::function<void(int, int, int, int)> callback);

private:
    GLFWwindow* window_;
    int width_, height_;
    std::string title_;

    // Static callbacks for GLFW
    static void FramebufferSizeCallback(GLFWwindow* window, int width, int height);
    static void KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods);

    void Initialize();
    void Cleanup();
};