/**
 * @file Id.h
 * @brief 使用“索引 + 代数”打包方案的 32 位标识符工具。
 * @details
 * 位布局：
 * - 低位：索引
 * - 高位：代数
 *
 * 当索引被复用时，通过递增代数降低悬挂句柄误用风险。
 */
#pragma once
#include "CommonHeader.h"


namespace XEngine::id
{
/**
 * @brief 标识符相关类型与常量。
 */
using id_type = u32;

namespace detail {
/**
 * @brief 高位代数字段的位宽。
 */
constexpr u32 generation_bits{ 8 };
/**
 * @brief 低位索引字段的位宽。
 */
constexpr u32 index_bit{ sizeof(id_type) * 8 - generation_bits };
/**
 * @brief 用于提取索引字段的掩码。
 */
constexpr id_type index_mask{ (id_type{1} << index_bit) - 1 };
/**
 * @brief 右移后用于提取代数字段的掩码。
 */
constexpr id_type generation_mask{ (id_type{1} << generation_bits) - 1 };
}
/**
 * @brief 表示无效标识符的哨兵值。
 */
constexpr id_type invalid_id{ (id_type)-1 };
/**
 * @brief 延迟回收删除项时的触发阈值。
 */
constexpr u32 min_deleted_elements{ 1024 };

/**
 * @brief 可容纳代数字段的最小无符号整型。
 */
using generation_type = std::conditional_t<detail::generation_bits <= 16, std::conditional_t<detail::generation_bits <= 8, u8, u16>, u32>;
static_assert(sizeof(generation_type) * 8 >= detail::generation_bits);
static_assert((sizeof(id_type) - sizeof(generation_type)) > 0);



/**
 * @brief 判断标识符是否有效。
 * @param id 打包后的标识符。
 * @return 当 @p id 不是无效哨兵值时返回 true。
 */
constexpr bool
is_valid(id_type id)
{
	return id != invalid_id;
}

/**
 * @brief 从打包标识符中提取索引字段。
 * @param id 打包后的标识符。
 * @return 低位索引字段。
 * @pre 提取后的索引不能等于保留的全 1 索引值。
 */
constexpr id_type
index(id_type id)
{
	id_type index{ id & detail::index_mask };
	assert(index != detail::index_mask);
	return index;
}

/**
 * @brief 从打包标识符中提取代数字段。
 * @param id 打包后的标识符。
 * @return 高位代数字段。
 */
constexpr id_type
generation(id_type id)
{
	return (id >> detail::index_bit) & detail::generation_mask;
}

/**
 * @brief 为同一索引生成下一代标识符。
 * @param id 当前打包标识符。
 * @return 索引不变且代数递增后的标识符。
 * @pre 代数递增后不能溢出到保留范围。
 */
constexpr id_type
new_generation(id_type id)
{
	const id_type generation{ id::generation(id) + 1 };
	assert(generation < (((u64)1 << detail::generation_bits) - 1));
	return index(id) | (generation << detail::index_bit);
}




#if _DEBUG
namespace detail {
struct id_base
{
	constexpr explicit id_base(id_type id) : _id(id) {}
	constexpr operator id_type() const { return _id; }
private:
	id_type _id;
};
}

/**
 * @brief 在调试构建下声明强类型标识符。
 * @details
 * 调试构建使用派生自 id_base 的包装类型。
 * 发布构建退化为 id_type 别名以保持零开销抽象。
 */
#define DEFINE_TYPED_ID(name)									\
		struct name final : id::detail::id_base					\
		{														\
			constexpr explicit name(id::id_type id)				\
				: id_base{id}{}									\
			constexpr name() : id_base{ 0 }{}					\
		};														
#else
/**
 * @brief 发布模式下的零运行时开销类型别名。
 */
#define DEFINE_TYPED_ID(name) using name = id::id_type;
#endif


}
