#pragma once

#include <memory>

#include "BufferBuilder.h" 
#include "../../systems/RenderSystem.h" 

/**
 * @file BufferSystem.h
 * @brief Vivid2D 渲染系统的即时模式（Immediate Mode）缓冲区管理系统。
 *
 * 核心目标：提供一个简单、高效的接口，用于在运行时动态构建几何体数据（顶点流），
 * 并使用一次 Draw Call 提交给 GPU 渲染，然后立即释放 GPU 资源。
 *
 * ==========================================================
 * 核心组件介绍
 * ==========================================================
 *
 * 1. Tesselator (单例管理器)
 * ----------------------------
 * - 作用：系统的入口点，管理一个 BufferBuilder 单例实例。
 * - 接口：Tesselator::getInstance() 获取单例；Tesselator::getBuilder() 获取构建器。
 * - 核心方法：Tesselator::end()。调用此方法会触发整个绘制流程 (Builder -> Uploader)。
 *
 * 2. BufferBuilder (数据构建器)
 * ----------------------------
 * - 作用：负责在 CPU 内存中收集顶点数据（x, y, u, v）和当前的渲染状态 (RenderState)。
 * - 接口：begin() 启动构建；vertex() 添加顶点；setTexture/setColor 等设置状态。
 * - 输出：end() 返回一个 BuiltBuffer 实例。
 *
 * 3. BuiltBuffer (缓冲区结果)
 * --------------------------
 * - 作用：一个数据结构，封装了所有必要的 GPU 资源句柄 (VAO/VBO)、顶点数量、GL 模式，以及构建时捕获的 RenderState 副本。
 * - 特点：所有权通过 std::unique_ptr 转移，确保资源只被 Uploader 绘制和清理一次。
 *
 * 4. BufferUploader (绘制和清理器)
 * --------------------------------
 * - 作用：接收 BuiltBuffer，将其中记录的 RenderState 应用到 GL 上下文，绑定 VAO，执行 glDrawArrays 绘制，最后清理 GPU 资源。
 * - 核心方法：BufferUploader::drawWithShader(std::unique_ptr<BuiltBuffer> buffer)。
 *
 * ==========================================================
 * 典型工作流程 (绘制一个带纹理的四边形)
 * ==========================================================
 *
 * 1. 初始化和获取：
 * Tesselator& t = Tesselator::getInstance();
 * BufferBuilder& builder = t.getBuilder();
 *
 * 2. 开始构建：
 * builder.begin(GL_QUADS, 4); // 预计绘制一个包含 4 个顶点的四边形
 *
 * 3. 设置状态：
 * builder.setShader(myProgramId);
 * builder.setTexture(myTextureId, 0);
 * builder.setColor(glm::vec4(1.0f, 1.0f, 1.0f, 0.5f)); // 半透明白色
 *
 * 4. 添加顶点（x, y, u, v）：
 * builder.vertex(10.0f, 10.0f, 0.0f, 0.0f);
 * builder.vertex(110.0f, 10.0f, 1.0f, 0.0f);
 * builder.vertex(110.0f, 110.0f, 1.0f, 1.0f);
 * builder.vertex(10.0f, 110.0f, 0.0f, 1.0f);
 *
 * 5. 提交绘制和清理：
 * t.end();
 * // 此时，数据已上传、绘制完成，GPU 上的 VAO/VBO 资源已被释放。
 *
 */
namespace Vivid2D::Render::Buffer {

    class BufferBuilder;

    /**
     * @brief Tesselator 类：作为 BufferBuilder 的单例管理器。
     * * 职责：
     * 1. 提供单例访问。
     * 2. 封装 BufferBuilder，提供一致的几何体构建接口。
     * 3. 在 end() 调用时，将构建结果交由 BufferUploader 立即绘制。
     */
    class VIVID_2D_MYDLL_API Tesselator {
    private:
        static constexpr int DEFAULT_BUFFER_SIZE = 2097152; // 2MB floats

        std::unique_ptr<BufferBuilder> builder; // BufferBuilder 实例

        /**
         * @brief 私有构造函数，确保单例。
         */
        explicit Tesselator(int bufferSize);

        /**
         * @brief 私有默认构造函数。
         */
        Tesselator();

    public:
        Tesselator(const Tesselator&) = delete;
        Tesselator& operator=(const Tesselator&) = delete;

        /**
         * @brief 获取 Tesselator 的单例实例（线程安全延迟初始化）。
         * * 必须在渲染线程上调用或在初始化阶段调用。
         * @return Tesselator& 单例实例的引用。
         */
        static Tesselator& getInstance();

        /**
         * @brief 结束构建，将数据上传到 GPU，并立即绘制。
         * * 必须在渲染线程上调用。
         */
        void end();

        /**
         * @brief 获取底层的 BufferBuilder 对象，用于添加顶点和设置状态。
         * @return BufferBuilder&
         */
        BufferBuilder& getBuilder();
    };

} // namespace Buffer