#pragma once
/**
 * @file texture_sampler.h
 * @brief 跨平台纹理采样器抽象
 */

#include "sokol_gfx.h"
#include <limits>
#include <cstdint>
#include <memory>
#include <unordered_map>

class texture_sampler;

enum class sampler_type {
	default_,
	pixel_art,
	bilinear,
	trilinear,
	tileable,
	linear_clamp,
	shadow_map,
	anisotropic,
};

/**
 * @class texture_sampler_builder
 * @brief 跨平台纹理采样器工具
 *
 * 提供简化的创建和管理纹理采样器的接口，
 * 支持流式配置风格。
 */
class texture_sampler_builder {
public:
    /**
     * @brief 创建默认采样器
     * @return 具有默认配置的采样器(最近点采样，重复包裹)
     */
    static texture_sampler_builder create_default();

    /**
     * @brief 创建用于像素艺术的采样器(最近点采样)
     * @return 为像素艺术渲染配置的采样器
     */
    static texture_sampler_builder create_pixel_art();

    /**
     * @brief 创建双线性过滤采样器
     * @return 具有双线性过滤的采样器(线性过滤，无MIP映射)
     */
    static texture_sampler_builder create_bilinear();

    /**
     * @brief 创建三线性过滤采样器
     * @return 具有三线性过滤的采样器(带MIP映射的线性过滤)
     */
    static texture_sampler_builder create_trilinear();

    /**
     * @brief 创建可平铺纹理的采样器
     * @return 为可平铺纹理配置的采样器，使用线性过滤
     */
    static texture_sampler_builder create_tileable();

    /**
     * @brief 创建带边缘限制的线性过滤采样器
     * @return 配置为平滑渲染并带边缘限制的采样器
     */
    static texture_sampler_builder create_linear_clamp();

    /**
     * @brief 创建阴影贴图采样器
     * @param compare_func 阴影采样的比较函数
     * @return 为阴影贴图采样配置的采样器
     */
    static texture_sampler_builder create_shadow_map(sg_compare_func compare_func = SG_COMPAREFUNC_LESS);

    /**
     * @brief 创建各向异性过滤采样器
     * @param anisotropy 各向异性程度(1-16)
     * @return 具有各向异性过滤的采样器
     */
    static texture_sampler_builder create_anisotropic(uint32_t anisotropy = 16);

    /**
     * @brief 设置缩小过滤器
     * @param filter 用于缩小的过滤器
     * @return 采样器引用，用于方法链式调用
     */
    texture_sampler_builder& with_min_filter(sg_filter filter);

    /**
     * @brief 设置放大过滤器
     * @param filter 用于放大的过滤器
     * @return 采样器引用，用于方法链式调用
     */
    texture_sampler_builder& with_mag_filter(sg_filter filter);

    /**
     * @brief 设置MIP映射过滤器
     * @param filter 用于MIP映射选择的过滤器
     * @return 采样器引用，用于方法链式调用
     */
    texture_sampler_builder& with_mipmap_filter(sg_filter filter);

    /**
     * @brief 同时设置所有过滤器
     * @param min_filter 缩小过滤器
     * @param mag_filter 放大过滤器
     * @param mip_filter MIP映射过滤器
     * @return 采样器引用，用于方法链式调用
     */
    texture_sampler_builder& with_filters(sg_filter min_filter, sg_filter mag_filter, sg_filter mip_filter);

    /**
     * @brief 将所有过滤器设置为相同值
     * @param filter 用于所有过滤操作的过滤器
     * @return 采样器引用，用于方法链式调用
     */
    texture_sampler_builder& with_all_filters(sg_filter filter);

    /**
     * @brief 设置水平包裹模式
     * @param wrap U坐标的包裹模式
     * @return 采样器引用，用于方法链式调用
     */
    texture_sampler_builder& with_wrap_u(sg_wrap wrap);

    /**
     * @brief 设置垂直包裹模式
     * @param wrap V坐标的包裹模式
     * @return 采样器引用，用于方法链式调用
     */
    texture_sampler_builder& with_wrap_v(sg_wrap wrap);

    /**
     * @brief 设置深度包裹模式(仅3D纹理)
     * @param wrap W坐标的包裹模式
     * @return 采样器引用，用于方法链式调用
     */
    texture_sampler_builder& with_wrap_w(sg_wrap wrap);

    /**
     * @brief 同时设置所有包裹模式
     * @param wrap 所有坐标的包裹模式
     * @return 采样器引用，用于方法链式调用
     */
    texture_sampler_builder& with_wrap(sg_wrap wrap);

    /**
     * @brief 单独设置所有包裹模式
     * @param wrap_u U坐标的包裹模式
     * @param wrap_v V坐标的包裹模式
     * @param wrap_w W坐标的包裹模式
     * @return 采样器引用，用于方法链式调用
     */
    texture_sampler_builder& with_wrap(sg_wrap wrap_u, sg_wrap wrap_v, sg_wrap wrap_w);

    /**
     * @brief 设置LOD范围
     * @param min_lod 最小细节级别
     * @param max_lod 最大细节级别
     * @return 采样器引用，用于方法链式调用
     */
    texture_sampler_builder& with_lod_range(float min_lod, float max_lod);

    /**
     * @brief 设置最小LOD级别
     * @param min_lod 最小细节级别
     * @return 采样器引用，用于方法链式调用
     */
    texture_sampler_builder& with_min_lod(float min_lod);

    /**
     * @brief 设置最大LOD级别
     * @param max_lod 最大细节级别
     * @return 采样器引用，用于方法链式调用
     */
    texture_sampler_builder& with_max_lod(float max_lod);

    /**
     * @brief 设置边界颜色
     * @param color 使用的边界颜色
     * @return 采样器引用，用于方法链式调用
     */
    texture_sampler_builder& with_border_color(sg_border_color color);

    /**
     * @brief 设置阴影采样器的比较函数
     * @param compare 使用的比较函数
     * @return 采样器引用，用于方法链式调用
     */
    texture_sampler_builder& with_compare(sg_compare_func compare);

    /**
     * @brief 设置最大各向异性级别
     * @param anisotropy 最大各向异性(1-16)
     * @return 采样器引用，用于方法链式调用
     */
    texture_sampler_builder& with_max_anisotropy(uint32_t anisotropy);

    /**
     * @brief 设置调试标签
     * @param label 采样器的调试标签
     * @return 采样器引用，用于方法链式调用
     */
    texture_sampler_builder& with_label(const char* label);

    /**
     * @brief 构建最终的采样器描述符
     * @return 完整的采样器描述符，可用于sg_make_sampler
     */
    [[nodiscard]] sg_sampler_desc build() const;

	/**
	 * @brief 创建纹理采样器
	 * @return 纹理采样器指针
	 */
	[[nodiscard]] std::shared_ptr<texture_sampler> create() const;

	static std::shared_ptr<texture_sampler> get_sampler(sampler_type in_type);
	static void clear();
private:
	inline static std::unordered_map<sampler_type, std::shared_ptr<texture_sampler>> sampler_map_;

    // 默认构造函数创建标准采样器配置
    texture_sampler_builder();

    // 正在构建的采样器描述符
    sg_sampler_desc desc_;
};

class texture_sampler {
public:
	texture_sampler(const sg_sampler_desc& desc);
	~texture_sampler();

	/**
	 * @brief 获取sokol-gfx采样器句柄
	 * @return sokol-gfx采样器句柄
	 */
	operator const auto&() const {
		return sampler_;
	}
	const auto& get_sampler() const { return sampler_; }
private:
	sg_sampler sampler_{};
};
