#pragma once

#include <extra2d/graphics/resources/buffer.h>
#include <glad/glad.h>
#include <cstddef>
#include <cstdint>

namespace extra2d {

// ============================================================================
// OpenGL 缓冲区实现
// ============================================================================
class GLBuffer : public Buffer {
public:
    /**
     * @brief 构造函数
     */
    GLBuffer();

    /**
     * @brief 析构函数
     */
    ~GLBuffer() override;

    /**
     * @brief 初始化缓冲区
     * @param desc 缓冲区描述
     * @return 成功返回 true
     */
    bool init(const BufferDesc& desc);

    /**
     * @brief 关闭缓冲区，释放资源
     */
    void shutdown();

    // Buffer 接口实现
    void bind() override;
    void unbind() override;
    void setData(const void* data, size_t size) override;
    void updateData(const void* data, size_t offset, size_t size) override;
    void* map() override;
    void unmap() override;
    size_t getSize() const override { return size_; }
    BufferType getType() const override { return type_; }
    BufferUsage getUsage() const override { return usage_; }
    bool isValid() const override { return bufferID_ != 0; }
    uintptr_t getNativeHandle() const override { return static_cast<uintptr_t>(bufferID_); }

    /**
     * @brief 获取 OpenGL 缓冲区 ID
     * @return 缓冲区 ID
     */
    GLuint getBufferID() const { return bufferID_; }

    /**
     * @brief 获取 OpenGL 缓冲区目标类型
     * @return 缓冲区目标类型
     */
    GLenum getTarget() const { return target_; }

private:
    GLuint bufferID_ = 0;
    GLenum target_ = GL_ARRAY_BUFFER;
    size_t size_ = 0;
    BufferType type_ = BufferType::Vertex;
    BufferUsage usage_ = BufferUsage::Static;
    GLenum glUsage_ = GL_STATIC_DRAW;
    bool mapped_ = false;
    void* mappedPtr_ = nullptr;

    /**
     * @brief 转换使用模式到 OpenGL 枚举
     */
    static GLenum convertUsage(BufferUsage usage);

    /**
     * @brief 转换缓冲区类型到 OpenGL 目标
     */
    static GLenum convertType(BufferType type);
};

} // namespace extra2d
