#pragma once

#include <Eigen/Eigen>
#include <memory>
#include <string>
#include <sstream>
#include <iomanip>
#include <unordered_map>

#include "texture/atlas/texture2d_atlas.h"

/**
 * @enum glyph_atlas_reason_t
 * @brief 图集操作结果原因枚举
 *
 * 用于标识字形图集操作的结果状态，便于调用者了解操作失败的具体原因。
 */
enum class glyph_atlas_reason_t {
    success,         ///< 操作成功完成
    glyph_not_found, ///< 未找到请求的字形
    atlas_full,      ///< 图集空间已满，无法分配更多区域
    unknown          ///< 未知原因导致的失败
};

/**
 * @struct glyph_atlas_result_t
 * @brief 图集操作结果结构体
 *
 * 封装了字形图集操作的完整结果信息，包括操作状态和分配的区域。
 */
struct glyph_atlas_result_t {
    glyph_atlas_reason_t reason = glyph_atlas_reason_t::unknown; ///< 操作结果原因
    atlas_region_t region;      ///< 分配的区域信息（仅当操作成功时有效）
};

/**
 * @class atlas_base
 * @brief 字形图集管理基类
 *
 * 提供字形图集管理的通用功能，包括图集初始化、区域分配和缓存管理。
 * 派生类需要实现具体的字形渲染和图集更新逻辑。
 */
class atlas_base {
protected:
    std::shared_ptr<texture2d_atlas> atlas_; ///< 底层纹理图集对象
    std::unordered_map<std::string, atlas_region_t> cached_regions_; ///< 已缓存的区域映射表

    /**
     * @brief 为字形创建唯一的缓存键
     *
     * @param in_glyph_index 字形的Unicode码点或字体特定索引
     * @param in_font_name 字体名称
     * @param in_font_size 字体大小
     * @return 唯一标识字形的缓存键字符串
     */
    static std::string create_cache_key(uint32_t in_glyph_index, const std::string& in_font_name, float in_font_size) {
        std::stringstream ss;
        ss << std::hex << in_glyph_index << "_" << in_font_name << "_" << std::fixed
           << std::setprecision(1) << in_font_size;
        return ss.str();
    }

    /**
     * @brief 初始化底层纹理图集
     *
     * @param in_atlas_size 图集的像素尺寸
     * @param in_pixel_format 图集的像素格式
     * @return 初始化是否成功
     */
    bool initialize_atlas(const Eigen::Vector2i& in_atlas_size, sg_pixel_format in_pixel_format) {
        atlas_ = std::make_shared<texture2d_atlas>(
            in_atlas_size,
            in_pixel_format,
            allocation_strategy_t::bin_packing  // 使用二叉树装箱算法策略
        );

        return atlas_ != nullptr;
    }

    /**
     * @brief 从缓存中查找字形区域
     *
     * @param in_cache_key 缓存键
     * @return 查找结果，包含成功/失败状态和区域信息
     */
    glyph_atlas_result_t find_in_cache(const std::string& in_cache_key) {
        glyph_atlas_result_t result{};

        auto it = cached_regions_.find(in_cache_key);
        if (it != cached_regions_.end()) {
            result.reason = glyph_atlas_reason_t::success;
            result.region = it->second;
        }

        return result;
    }

    /**
     * @brief 将区域信息添加到缓存
     *
     * @param in_cache_key 缓存键
     * @param in_region 要缓存的区域
     */
    void add_to_cache(const std::string& in_cache_key, const atlas_region_t& in_region) {
        cached_regions_[in_cache_key] = in_region;
    }

public:
    /**
     * @brief 虚析构函数
     *
     * 确保正确释放派生类资源
     */
    virtual ~atlas_base() = default;

    /**
     * @brief 初始化图集
     *
     * @param in_atlas_size 图集的像素尺寸
     * @return 初始化是否成功
     */
    virtual bool initialize(const Eigen::Vector2i& in_atlas_size) = 0;

    /**
     * @brief 获取图集底层纹理
     *
     * @return 图集纹理对象
     */
    [[nodiscard]] auto get_texture() const {
        return atlas_->get_texture();
    }

    /**
     * @brief 获取已缓存区域的数量
     *
     * @return 缓存的区域数量
     */
    [[nodiscard]] size_t get_cached_regions_count() const {
        return cached_regions_.size();
    }

    /**
     * @brief 清除所有缓存的区域
     */
    void clear_cache() {
        cached_regions_.clear();
    }
};
