#pragma once

#include "sokol/sokol_header.h"
#include "misc/color.h"
#include "misc/mirage_type.h"

enum class draw_effect {
};

// 用于标识批次的键
struct batch_key {
	sg_pipeline pipeline{};
	sg_image image{};
	// 可选：添加其他影响状态的元素，如着色器、混合模式等

	bool operator==(const batch_key& other) const {
		return pipeline.id == other.pipeline.id &&
			   image.id == other.image.id;
	}

	bool operator<(const batch_key& other) const {
		if (pipeline.id != other.pipeline.id)
			return pipeline.id < other.pipeline.id;
		return image.id < other.image.id;
	}
};

// 表示一个绘制批次
struct draw_batch {
	batch_key key;
	uint32_t vertex_start = 0;    // 批次在顶点缓冲区中的起始索引
	uint32_t vertex_count = 0;    // 批次包含的顶点数量
	uint32_t index_start = 0;     // 批次在索引缓冲区中的起始索引
	uint32_t index_count = 0;     // 批次包含的索引数量
};

// 特化类型
using rect_color = rect_quad<linear_color>;
using rect_uv    = rect_quad<Eigen::Vector2f>;
using rect_round = rect_quad<float>;

// 为rect_uv提供默认构造函数特化
template<>
inline rect_quad<Eigen::Vector2f>::rect_quad() : std::array<Eigen::Vector2f, 4>{
	Eigen::Vector2f{ 0, 0 },
	Eigen::Vector2f{ 1, 0 },
	Eigen::Vector2f{ 0, 1 },
	Eigen::Vector2f{ 1, 1 }
} {
}

class render_elements {
public:
    render_elements() = default;
    ~render_elements();

	void create_resources();
	void load_mirage_pipelines();

    // 开始新一帧的渲染
    void begin_frame();

    // 结束当前帧并提交所有批次
    void end_frame();

    // 设置当前渲染状态
    void set_pipeline(sg_pipeline pipeline);
    void set_texture(sg_image image);
	void set_projection_matrix(const Eigen::Matrix4f& in_matrix) { projection_matrix = in_matrix; }

    // 添加矩形（自动加入当前批次）
    void make_rect(const Eigen::Vector2f& in_pos,
                  const Eigen::Vector2f& in_size,
                  const rect_color& in_color,
                  const mirage_vertex_param_t& in_param_a = {},
                  const mirage_vertex_param_t& in_param_b = {},
                  const mirage_vertex_param_t& in_param_c = {},
                  const rect_uv& in_uv = {},
                  float in_rotation_radians = 0.0f,
                  const Eigen::Vector2f& in_pivot = Eigen::Vector2f(1.0f, 1.0f),
                  const Eigen::Vector2f& in_scale = Eigen::Vector2f(0.5f, 0.5f));

    // 添加圆角矩形
    void make_rounded_rect(const Eigen::Vector2f& in_pos,
                          const Eigen::Vector2f& in_size,
                          const rect_color& in_color,
                          const rect_uv& in_uv = {},
                          const rect_round& in_round = {},
                          float in_rotation_radians = 0.0f,
                          const Eigen::Vector2f& in_pivot = Eigen::Vector2f(1.0f, 1.0f),
                          const Eigen::Vector2f& in_scale = Eigen::Vector2f(0.5f, 0.5f));

private:
    // 根据顶点和索引数据创建一个矩形
    void add_rect_to_batch(const Eigen::Vector2f& in_pos,
                          const Eigen::Vector2f& in_size,
                          const rect_color& in_color,
                          const mirage_vertex_param_t& in_param_a,
						  const mirage_vertex_param_t& in_param_b,
						  const mirage_vertex_param_t& in_param_c,
						  const rect_uv& in_uv,
                          float in_rotation_radians,
                          const Eigen::Vector2f& in_pivot,
                          const Eigen::Vector2f& in_scale);

    // 确保当前批次与给定的渲染状态兼容
    void ensure_batch_compatibility(const batch_key& key);

    // 将当前批次数据上传到GPU
    void flush_batches();

    // 创建或调整缓冲区大小
    void ensure_buffer_capacity(uint32_t vertex_count, uint32_t index_count);

    // 当前渲染状态
    batch_key current_key{};

    // 当前批次索引
    int32_t current_batch_index = -1;

    // 所有待渲染的批次
    std::vector<draw_batch> batches;

    // 顶点和索引数据
    std::vector<mirage_vertex_t> vertices;
    std::vector<uint32_t> indices;

    // GPU缓冲区
    sg_buffer vertex_buffer{};
    sg_buffer index_buffer{};

    // 缓冲区容量追踪
    uint32_t vertex_buffer_capacity = 0;
    uint32_t index_buffer_capacity = 0;

    // 统计信息
    uint32_t draw_call_count = 0;
    uint32_t total_triangles = 0;

	Eigen::Matrix4f projection_matrix;

    sg_pipeline rounded_rect_pipeline{};
};
