#pragma once

#include <Logger.h>
#include <glm/vec2.hpp>
#include <glm/vec3.hpp>
#include <glm/vec4.hpp>
#include <glm/mat3x3.hpp>
#include <glfw/glfw3.h>
#include <glm/glm.hpp>

#include "model/Mesh2D.h"
#include "systems/sources/ShaderProgram.h"
#include "systems/Camera.h"
#include "TextRenderer.h"
#include "systems/sources/CompleteShader.h"
#include "systems/sources/ShaderManagement.h"
#include "model/util/LightSource.h"
#include "model/Model2D.h"
#include "model/util/PhysicsSystem.h"
#include "systems/buffer/Tesselator.h"
#include "systems/buffer/BufferBuilder.h"

class IllegalStateException : public std::exception {
private:
    std::string message;
public:
    IllegalStateException(const std::string& msg) {
        this->message = msg;
    }
    char const* what() const noexcept override {
        return message.c_str();
    }
    const std::string& getMessage() const {
        return message;
    }
    operator std::string() const {
        return message;
    }
};

// 单例模式
class VIVID_2D_MYDLL_API ModelRender {
private:
    explicit ModelRender() = default; // 默认构造函数
    ModelRender(const ModelRender& other) = delete; // 复制构造函数
    ModelRender(const ModelRender&& other) = delete; // 移动构造函数
    ~ModelRender() = default; // 默认析构函数

public:
    // 获取全局唯一实例
    static ModelRender* instance() {
        if (s_instance == nullptr) {
            s_instance = new ModelRender();
        }
        return s_instance;
    }

    static void destroyInstance() {
        if (s_instance) {
            ModelRender* tmp = s_instance;
            s_instance = nullptr;
            delete tmp;
        }
    }

    // 类型定义
    typedef glm::vec2 Vector2f;
    typedef glm::vec3 Vector3f;
    typedef glm::vec4 Vector4f;
    typedef glm::mat3 Matrix3f;
    typedef Vivid2D::Mesh2D Mesh2D;
    typedef Vivid2D::Model2D Model2D;
    typedef Vivid2D::util::LightSource LightSource;
    typedef Vivid2D::util::PhysicsSystem PhysicsSystem;
    typedef Vivid2D::util::PhysicsParticle PhysicsParticle;
    typedef Vivid2D::util::CircleCollider CircleCollider;
    typedef Vivid2D::util::RectangleCollider RectangleCollider;

    typedef Vivid2D::ModelPart ModelPart;
    typedef Vivid2D::Render::Buffer::Tesselator Tesselator;
    typedef Vivid2D::Render::Buffer::BufferBuilder BufferBuilder;

    using ByteBuffer = std::vector<unsigned char>;

    /**
     * 缩略图边界计算结果
     */
    struct ThumbnailBounds {
        GLfloat minX, maxX, minY, maxY;
        GLfloat scale;
        GLfloat offsetX, offsetY;
    };

    struct MeshGLResources {
        GLuint vao = 0;
        GLuint vbo = 0;
        GLuint ebo = 0;

        void dispose() {
            if (ebo != 0) {
                glDeleteBuffers(1, &ebo);
                ebo = 0;
            }
            if (vbo != 0) {
                glDeleteBuffers(1, &vbo);
                vbo = 0;
            }
            if (vao != 0) {
                glDeleteVertexArrays(1, &vao);
                vao = 0;
            }
        }
    };
public:
    // 常量
    static constexpr double c_pi = 3.14159265358979323846;

private:
    Logger logger{ "ModelRender" };
    // 全局唯一实例
    static ModelRender* s_instance;
    bool m_isInitialized = false;
    struct Size {
        int width;
        int height;
    };
    /**
     * 视口大小（宽高)（像素），定义渲染区域的大小
     * 默认值：(800, 600) (像素)
     *
     * @see #setViewport(int, int)
     * @see #setViewport(Size)
     */
    Size m_viewportSize{ 800, 600 };
    /**
     * 清除颜色（RGBA），用于在每帧开始时清空颜色缓冲区
     * 默认值：黑色不透明 (0.0f, 0.0f, 0.0f, 1.0f)
     *
     * @see RenderSystem#clearColor(GLfloat, GLfloat, GLfloat, GLfloat)
     */
    Vector4f m_clearColor{ 0.0f, 0.0f, 0.0f, 1.0f };

    /**
     * 深度测试启用标志，控制是否进行深度缓冲测试
     * 在2D渲染中通常禁用以提高性能
     * 默认值：false（禁用）
     *
     * @see RenderSystem#enableDepthTest()
     * @see RenderSystem#disableDepthTest()
     */
    bool m_enableDepthTest = false;

    /**
     * 混合功能启用标志，控制透明度和颜色混合
     * 默认值：true（启用）
     *
     * @see RenderSystem#enableBlend()
     * @see RenderSystem#disableBlend()
     */
    bool m_enableBlending = true;

    /**
     * 最大光源数量，用于限制同时启用的光源数量
     * 默认值：80
     */
    int m_maxLightCount = 80;

    // ================== 着色器与资源管理 ==================

    /**
        * 默认着色器程序，用于大多数模型的渲染
        * 包含基础的光照、纹理和变换功能
        *
        * @see #compileDefaultShader()
        */
    ShaderProgram* m_defaultProgram = nullptr;

    /**
     * 网格GPU资源缓存，管理已上传到GPU的网格数据
     * 键：Mesh2D对象
     * 值：对应的OpenGL资源（VAO、VBO、EBO）
     *
     * @see MeshGLResources
     */
    std::unordered_map<Mesh2D, MeshGLResources> m_meshResources;

    /**
     * 纹理单元分配器，用于管理多个纹理的绑定
     * 确保不同的纹理绑定到正确的纹理单元
     * 默认从0开始递增分配
     */
    [[deprecated]]int m_textureUnitAllocator;

    /**
     * 默认白色纹理ID，当模型没有指定纹理时使用
     * 这是一个1x1的纯白色纹理，确保模型有基本的颜色显示
     *
     * @see #createDefaultTexture()
     */
    int m_defaultTextureId = 0;

    // ================== 碰撞箱渲染配置 ==================

    /**
     * 碰撞箱渲染开关，控制是否在场景中显示物理碰撞体的轮廓
     * 调试时非常有用，可以直观看到碰撞边界
     * 默认值：true（启用）
     */
    bool m_renderColliders = true;

    /**
     * 碰撞箱线框宽度，控制碰撞体轮廓线的粗细
     * 单位：像素
     * 默认值：1.0f
     */
    GLfloat m_colliderLineWidth = 1.0f;

    /**
     * 碰撞箱颜色（RGBA），定义碰撞体轮廓的显示颜色
     * 默认值：白色不透明 (1.0f, 1.0f, 1.0f, 1.0f)
     */
    Vector4f m_colliderColor{ 1.0f, 1.0f, 1.0f, 1.0f };

    /**
     * 圆形碰撞体细分数量，控制圆形碰撞体的平滑度
     * 值越高圆形越平滑，但渲染开销也越大
     * 默认值：32（在性能和视觉效果间取得平衡）
     */
    int m_circleSegments = 32;

    /**
     * 光源位置渲染开关，控制是否在场景中显示光源的位置
     * 用点状标记显示每个启用的光源位置
     * 默认值：true（启用）
     */
    bool m_renderLightPositions = true;

    // ================== 摄像机状态 ==================

    /**
     * 默认摄像机，用于控制场景的视图和缩放
     * 默认位置：(0, 0)
     */
    Camera m_camera{0, 0};

    // ================== 字体管理 ==================
    std::unique_ptr<TextRenderer> m_defaultTextRenderer;
    Size m_fontBitmapSize{ 512, 512 };
    int m_fontFirstChar = 32;
    int m_fontCharCount = 96;

public:
    // ================== 摄像机API方法 ==================

    /**
     * 获取摄像机对象副本
     */
    Camera getCamera() const {
        return m_camera;
    }
    /**
     * 获取当前实例摄像机引用
     */
    Camera& getCameraReference() {
        return m_camera;
    }

    /**
     * 设置摄像机位置
     */
    void setCameraPosition(GLfloat x, GLfloat y) {
        m_camera.setPosition(x, y);
    }

    /**
     * 设置摄像机缩放
     */
    void setCameraZoom(GLfloat zoom) {
        m_camera.setZoom(zoom);
    }

    /**
     * 设置摄像机Z轴位置
     */
    void setCameraZPosition(GLfloat z) {
        m_camera.setZPosition(z);
    }

    /**
     * 移动摄像机
     */
    void moveCamera(GLfloat dx, GLfloat dy) {
        m_camera.move(dx, dy);
    }

    /**
     * 缩放摄像机
     */
    void zoomCamera(GLfloat factor) {
        m_camera.zoom(factor);
    }

    /**
     * 重置摄像机
     */
    void resetCamera() {
        m_camera.reset();
    }

    /**
     * 启用/禁用摄像机
     */
    void setCameraEnabled(bool enabled) {
        m_camera.setEnabled(enabled);
    }

    /**
     * 构建考虑摄像机变换的投影矩阵
     */
    Matrix3f buildCameraProjection(int width, int height);


    // ================== 初始化 / 清理 ==================
    void initialize() noexcept(false);

    /**
     * 初始化所有非默认着色器的基础信息（顶点坐标等）
     */
    void initNonDefaultShaders();

    /**
     * 初始化着色器的基础uniforms（顶点坐标相关）
     */
    void initShaderBasicUniforms(ShaderProgram* program, CompleteShader* shader);


    auto& getTextRenderer() const {
        return m_defaultTextRenderer;
    }

    // ================== 工具 ==================
    static Matrix3f buildOrthoProjection(int width, int height);

    /**
        * 渲染文字
        *
        * @param text  文字内容
        * @param x     世界坐标 X
        * @param y     世界坐标 Y ,反转的
        * @param color RGBA 颜色
        */
    void renderText(std::string text, GLfloat x, GLfloat y, Vector4f color);

    /**
        * 获取默认摄像机与当前摄像机之间的偏移量
        *
        * @return Vector2f 偏移向量 (dx, dy)
        */
    Vector2f getCameraOffset();

    void setViewport(int width, int height);

    // ================== 辅助：外部获取状态 ==================
    bool isInitialized() const {
        return m_isInitialized;
    }

    int getLoadedMeshCount() const {
        return m_meshResources.size();
    }

    void cleanup();

    // ================== 渲染流程 (已修改) ==================
    void render(GLfloat deltaTime, Model2D& model);

    // ================== 缩略图渲染方法 ==================

    /**
     * 渲染模型缩略图（图层式渲染，不受摄像机控制）
     *
     * <p>该方法提供类似PS图层预览的缩略图渲染功能：</p>
     * <ul>
     *   <li>固定位置和大小，不受摄像机影响</li>
     *   <li>自动缩放确保模型完全可见</li>
     *   <li>禁用复杂效果以提高性能</li>
     *   <li>独立的渲染状态管理</li>
     * </ul>
     *
     * @param model 要渲染的模型
     * @param x 缩略图左上角X坐标（屏幕坐标）
     * @param y 缩略图左上角Y坐标（屏幕坐标）
     * @param width 缩略图宽度
     * @param height 缩略图高度
     */
    void renderThumbnail(Model2D& model, GLfloat x, GLfloat y, GLfloat width, GLfloat height);

private:

    void logGLInfo();

    void uploadLightsToShader(ShaderProgram* sp, Model2D& model);

    void setupGLState();

    void compileDefaultShader();

    void createDefaultTexture();


    /**
     * 计算模型的边界和合适的缩放比例
     */
    ThumbnailBounds calculateThumbnailBounds(Model2D& model, GLfloat thumbWidth, GLfloat thumbHeight);

    /**
     * 递归计算模型的边界
     */
    void calculateModelBounds(Model2D& model, ThumbnailBounds bounds, Matrix3f parentTransform);

    /**
     * 递归计算部件及其子部件的边界
     */
    void calculateModelBoundsForPart(ModelPart* part, ThumbnailBounds bounds, Matrix3f parentTransform);

    /**
     * 计算单个部件的边界
     */
    void calculatePartBounds(ModelPart* part, ThumbnailBounds bounds, Matrix3f worldTransform);

    /**
     * 构建缩略图专用的正交投影矩阵
     */
    Matrix3f buildThumbnailProjection(GLfloat width, GLfloat height);

    /**
     * 缩略图专用的部件渲染
     */
    void renderPartForThumbnail(ModelPart* part, Matrix3f parentTransform);

    /**
     * 缩略图专用的网格渲染
     */
    void renderMeshForThumbnail(Mesh2D* mesh, Matrix3f modelMatrix);

    /**
     * 设置缩略图专用的简化光照
     */
    void setupThumbnailLighting(ShaderProgram* sp, Model2D& model);


    /**
     * 设置所有非默认着色器的顶点坐标相关uniform
     */
    void setupNonDefaultShaders(Matrix3f projection, Matrix3f view);

    void renderLightPositions(Model2D& model);

    /**
     * 绘制简洁的灯泡形状
     *
     * @param position  灯泡位置
     * @param intensity 光源强度，用于控制灯泡大小
     */
    void drawLightBulb(Vector2f position, GLfloat intensity);

    /**
     * 绘制十字标记（用于环境光）
     */
    void drawCrossMark(Vector2f position, GLfloat size);

    /**
     * 关键修改点：在渲染前确保更新 part 的 worldTransform，
     * 然后直接使用 part.getWorldTransform() 作为 uModelMatrix 传入 shader。
     */
    void renderPartRecursive(ModelPart* part, Matrix3f parentMat);

    void renderMesh(Mesh2D* mesh, Matrix3f modelMatrix);


    // ================== 渲染碰撞箱相关实现 ==================

    void renderPhysicsColliders(PhysicsSystem* physics);


    /**
     * 绘制圆形碰撞框（线框）
     * 使用临时 VAO/VBO，每帧创建并删除（简单实现）
     */
    void drawCircleColliderWire(Vector2f center, GLfloat radius);

    /**
     * 绘制矩形碰撞框（线框）
     */
    void drawRectangleColliderWire(Vector2f center, GLfloat width, GLfloat height);

    // ================== uniform 设置辅助（内部使用，确保 program 已绑定） ==================

    void setUniformIntInternal(ShaderProgram* sp, std::string name, int value);

    void setUniformVec3Internal(ShaderProgram* sp, std::string name, Vector3f vec);
    
    void setUniformVec2Internal(ShaderProgram* sp, std::string name, Vector2f vec);
    
    void setUniformFloatInternal(ShaderProgram* sp, std::string name, GLfloat value);
    
    void setUniformVec4Internal(ShaderProgram* sp, std::string name, Vector4f vec);
    
    void setUniformMatrix3(ShaderProgram* sp, std::string name, Matrix3f m);

    // ================== 部件属性 ==================
    void setPartUniforms(ShaderProgram* sp, ModelPart* part);



};