/**
 * @file ContentToEngine.cpp
 * @brief 内容二进制数据到渲染/资源句柄的转换实现。
 * @details
 * 本文件完成导入数据的运行时落地，包含：
 * - 网格层级(LOD)结构重排与子网格 GPU 资源创建；
 * - 着色器分组缓存与 key 索引查询；
 * - 材质/纹理/几何资源的统一创建与释放入口。
 */
#include "ContentToEngine.h"
#include "Graphics\Renderer.h"
#include "Utilities\IOStream.h"

namespace XEngine::content {
namespace {

/**
 * @brief 几何层级缓冲区的视图封装。
 * @details
 * 对连续内存中的几何层级布局进行字段映射，提供阈值、LOD 偏移与 GPU ID 访问。
 */
class geometry_hierarchy_stream
{
public:
	DISABLE_COPY_AND_MOVE(geometry_hierarchy_stream);

	geometry_hierarchy_stream(u8 *const buffer, u32 lods = u32_invalid_id)
		:_buffer{ buffer }
	{
		assert(buffer && lods);
		if (lods != u32_invalid_id)
		{
			*((u32*)buffer) = lods;
		}

		_lod_count = *((u32*)buffer);
		_thresholds = (f32*)(&buffer[sizeof(u32)]);
		_lod_offsets = (lod_offset*)(&_thresholds[_lod_count]);
		_gpu_ids = (id::id_type*)(&_lod_offsets[_lod_count]);
	}

	void gpu_ids(u32 lod, id::id_type*& ids, u32& id_count)
	{
		assert(lod < _lod_count);
		ids = &_gpu_ids[_lod_offsets[lod].offset];
		id_count = _lod_offsets[lod].count;
	}

	u32 lod_from_threshold(f32 threshold)
	{
		assert(threshold > 0);
		if (_lod_count == 1) return 0;

		for (u32 i{ _lod_count - 1 }; i > 0; --i)
		{
			if (_thresholds[i] <= threshold) return i;
		}

		assert(false);
		return 0;
	}

	[[nodiscard]] constexpr u32 lod_count() const { return _lod_count; }
	[[nodiscard]] constexpr f32* thresholds() const { return _thresholds; }
	[[nodiscard]] constexpr lod_offset* lod_offsets() const { return _lod_offsets; }
	[[nodiscard]] constexpr id::id_type* gpu_ids() const { return _gpu_ids; }
private:
	u8 *const		_buffer;
	f32*			_thresholds;
	lod_offset*		_lod_offsets;
	id::id_type*	_gpu_ids;
	u32				_lod_count;
};


/**
 * @brief 支持 noexcept 移动的着色器组缓存容器。
 */
struct noexcept_map {
	std::unordered_map<u32, std::unique_ptr<u8[]>> map;
	noexcept_map() = default;
	noexcept_map(const noexcept_map&) = default;
	noexcept_map(noexcept_map&&) noexcept = default;
	noexcept_map& operator=(const noexcept_map&) = default;
	noexcept_map& operator=(noexcept_map&&) noexcept = default;

};

/**
 * @brief 单子网格资源的指针标记位。
 */
constexpr uintptr_t														single_mesh_marker{ (uintptr_t)0x01 };
/**
 * @brief 几何层级资源池。
 */
utl::free_list<u8*>														geometry_hierarchies;
/**
 * @brief 几何资源互斥锁。
 */
std::mutex																geometry_mutex;

/**
 * @brief 着色器组资源池。
 */
utl::free_list<noexcept_map>											shader_groups;
/**
 * @brief 着色器资源互斥锁。
 */
std::mutex																shader_mutex;


/**
 * @brief 预估并计算几何层级缓冲区所需字节数。
 * @param data 几何二进制输入数据。
 * @return 所需缓冲区大小（字节）。
 */
u32
get_geometry_hierarchy_buffer_size(const void *const data)
{
	assert(data);
	utl::blob_stream_reader blob{ (const u8*)data };
	const u32 lod_count{ blob.reader<u32>() };
	assert(lod_count);
	constexpr u32 su32{ sizeof(u32) };

	u32 size{ su32 + (sizeof(f32) + sizeof(lod_offset)) * lod_count };

	for (u32 lod_idx{ 0 }; lod_idx < lod_count; ++lod_idx)
	{
		// skip threshold
		blob.skip(sizeof(f32));
		// add size of gpu_ids
		size += sizeof(id::id_type) * blob.reader<u32>();
		// skip submesh data and goto next LOD
		blob.skip(blob.reader<u32>());
	}

	return size;
}

/**
 * @brief 创建多 LOD 网格层级资源。
 * @param data 几何二进制输入数据。
 * @return 几何内容资源 ID。
 */
//id::id_type
//create_mesh_hierarchy(const void *const data)
//{
//	assert(data);
//
//	const u32 size{ get_geometry_hierarchy_buffer_size(data) };
//	u8 *const hierarchy_buffer{ (u8 *const)malloc(size) };
//
//	utl::blob_stream_reader blob{ (const u8*)data };
//	const u32 lod_count{ blob.reader<u32>() };
//	assert(lod_count);
//	geometry_hierarchy_stream stream{ hierarchy_buffer, lod_count };
//	u32 submesh_index{ 0 };
//	id::id_type *const gpu_ids{ stream.gpu_ids() };
//
//	for (u32 lod_idx{ 0 }; lod_idx < lod_count; ++lod_idx)
//	{
//		stream.thresholds()[lod_idx] = blob.reader<f32>();
//		const u32 id_count{ blob.reader<u32>() };
//		assert(id_count < (1 << 16));
//		stream.lod_offsets()[lod_idx] = { (u16)submesh_index, (u16)id_count };
//		blob.skip(sizeof(u32)); // skip sizeof submeshes
//		for (u32 id_idx{ 0 }; id_idx < id_count; ++id_idx)
//		{
//			const u8* at{ blob.position() };
//			gpu_ids[submesh_index++] = graphics::add_submesh(at);
//			blob.skip((u32)(at - blob.position()));
//			assert(submesh_index < (1 << 16));
//		}
//	}
//
//	assert([&]()
//		{
//			f32 previous_theshold{ stream.thresholds()[0] };
//			for (u32 i{ 1 }; i < lod_count; ++i)
//			{
//				if (stream.thresholds()[i] <= previous_theshold) return false;
//				previous_theshold = stream.thresholds()[i];
//			}
//			return true;
//		}());
//
//	static_assert(alignof(void*) > 2, "We need the least significant bit for th single mesh marker.");
//	std::lock_guard lock{ geometry_mutex };
//	return geometry_hierarchies.add(hierarchy_buffer);
//}

/**
 * @brief 判断几何数据是否为单 LOD 单子网格。
 * @param data 几何二进制输入数据。
 * @return 单子网格返回 true。
 */
bool
is_single_mesh(const void *const data)
{
	assert(data);
	utl::blob_stream_reader blob{ (const u8*)data };
	const u32 lod_count{ blob.reader<u32>() };
	assert(lod_count);
	if (lod_count > 1) return false;


	blob.skip(sizeof(f32)); // skip threhold
	const u32 submesh_count{ blob.reader<u32>() };
	assert(submesh_count);
	return submesh_count == 1;
}

/**
 * @brief 创建单子网格资源并编码为伪指针句柄。
 * @param data 几何二进制输入数据。
 * @return 几何内容资源 ID。
 */
//id::id_type
//create_single_submesh(const void *const data)
//{
//	assert(data);
//	utl::blob_stream_reader blob{ (const u8*)data };
//	// skip lod_count, lod_threshold, submesh_count, and sizeof_submeshes
//	blob.skip(sizeof(u32) + sizeof(f32) + sizeof(u32) + sizeof(u32));
//	const u8* at{ blob.position() };
//	const id::id_type gpu_id{ graphics::add_submesh(at) };
//
//	// create a fake pointer and put it in the geometry_hierarchies.
//	static_assert(sizeof(uintptr_t) > sizeof(id::id_type));
//	constexpr u8 shift_bits{ (sizeof(uintptr_t) - sizeof(id::id_type)) << 3 };
//	u8 *const fake_pointer{ (u8 *const)((((uintptr_t)gpu_id) << shift_bits) | single_mesh_marker) };
//	std::lock_guard lock{ geometry_mutex };
//	return geometry_hierarchies.add(fake_pointer);
//}

/**
 * @brief 从单子网格伪指针解码 GPU 资源 ID。
 * @param pointer 编码后的伪指针。
 * @return GPU 子网格 ID。
 */
constexpr id::id_type
gpu_id_from_fake_pointer(u8 *const pointer)
{
	assert((uintptr_t)pointer & single_mesh_marker);
	static_assert(sizeof(uintptr_t) > sizeof(id::id_type));
	constexpr u8 shift_bits{ (sizeof(uintptr_t) - sizeof(id::id_type)) << 3 };
	return (((uintptr_t)pointer) >> shift_bits) & (uintptr_t)id::invalid_id;
}
// 
// data contain:
//struct{
//	u32 lod_count,
//	struct{
//		f32 lod_threshold,
//		u32 submesh_count,
//		u32 sizeof_submeshes,
//		struct{
//			u32 element_size, u32 vertex_count,
//			u32 index_count, u32 elements_type, u32 primitive_topology
//			u8 positions[sizeof(f32) * 3 * vertex_count],
//			u8 elements[sizeof(element_size) * vertex_count],
//			u8 indices[index_size * index_count],
//		} submeshes[submesh_count]
//	  }mesh_lods[lod_count]
// } geometry;
// 
// Output format
//
// struct{
//	u32 lod_count,
//	f32 thresholds[lod_count]
//	struct{
//		u16 offset,
//		u16 count
//		}lod_offsets[lod_count],
//	id::idtype gpu_ids[total_number_of_submeshes]
//}geometry_hierarchy
//
//
//
//

/**
 * @brief 按输入几何形态创建对应资源。
 * @param data 几何二进制输入数据。
 * @return 几何内容资源 ID。
 */
//id::id_type
//create_geometry_resource(const void *const data)
//{
//	assert(data);
//	return is_single_mesh(data) ? create_single_submesh(data) : create_mesh_hierarchy(data);
//}

/**
 * @brief 销毁几何资源并释放关联子网格。
 * @param id 几何内容资源 ID。
 */
//void
//destory_geometry_resource(id::id_type id)
//{
//	std::lock_guard lock{ geometry_mutex };
//	u8 *const pointer{ geometry_hierarchies[id] };
//	if ((uintptr_t)pointer & single_mesh_marker)
//	{
//		graphics::remove_submesh(gpu_id_from_fake_pointer(pointer));
//	}
//	else
//	{
//		geometry_hierarchy_stream stream{ pointer };
//		const u32 lod_count{ stream.lod_count() };
//		u32 id_index{ 0 };
//		for (u32 lod{ 0 }; lod < lod_count; ++lod)
//		{
//			for (u32 i{ 0 }; i < stream.lod_offsets()[lod].count; ++i)
//			{
//				graphics::remove_submesh(stream.gpu_ids()[id_index++]);
//			}
//		}
//
//		free(pointer);
//	}
//
//	geometry_hierarchies.remove(id);
//}

/**
 * @brief 创建材质资源。
 * @param data 材质初始化数据。
 * @return 材质资源 ID。
 */
//id::id_type
//create_material_resource(const void *const data)
//{
//	assert(data);
//	return graphics::add_material(*(const graphics::material_init_info *const)data);
//}
} // namespace

/**
 * @brief 销毁材质资源。
 * @param id 材质资源 ID。
 */
//void
//destory_material_resource(id::id_type id)
//{
//	graphics::remove_material(id);
//}

/**
 * @brief 统一资源创建入口。
 * @param data 资源二进制数据。
 * @param type 资源类型。
 * @return 资源 ID。
 */
//id::id_type
//create_resource(const void *const data, asset_type::type type)
//{
//	assert(data);
//	id::id_type id{ id::invalid_id };
//
//	switch (type)
//	{
//	case XEngine::content::asset_type::unknown:									break;
//	case XEngine::content::asset_type::animation:								break;
//	case XEngine::content::asset_type::audio:									break;
//	case XEngine::content::asset_type::material: id = create_material_resource(data);								break;
//	case XEngine::content::asset_type::mesh: id = create_geometry_resource(data);	break;
//	case XEngine::content::asset_type::skeleton:								break;
//	case XEngine::content::asset_type::texture:									break;
//	}
//
//	assert(id::is_valid(id));
//	return id;
//
//}


/**
 * @brief 统一资源销毁入口。
 * @param id 资源 ID。
 * @param type 资源类型。
 */
//void
//destroy_resource(id::id_type id, asset_type::type type)
//{
//	assert(id::is_valid(id));
//	switch (type)
//	{
//	case XEngine::content::asset_type::unknown:									break;
//	case XEngine::content::asset_type::animation:								break;
//	case XEngine::content::asset_type::audio:									break;
//	case XEngine::content::asset_type::material: destory_material_resource(id);								break;
//	case XEngine::content::asset_type::mesh: destory_geometry_resource(id);		break;
//	case XEngine::content::asset_type::skeleton:								break;
//	case XEngine::content::asset_type::texture:									break;
//	default:
//		assert(false);
//		break;
//	}
//}
/**
 * @brief 注册着色器组并复制其二进制数据。
 * @param shaders 着色器数组。
 * @param num_shaders 着色器数量。
 * @param keys 查询键数组。
 * @return 着色器组 ID。
 */
id::id_type
add_shader_group(const u8 *const * shaders, u32 num_shaders, const u32 *const keys)
{
	assert(shaders && num_shaders && keys);
	noexcept_map group;
	for (u32 i{ 0 }; i < num_shaders; ++i)
	{
		assert(shaders[i]);
		const compiled_shader_ptr shader_ptr{ (const compiled_shader_ptr)shaders[i] };
		const u64 size{ shader_ptr->buffer_size()};
		std::unique_ptr<u8[]> shader{ std::make_unique<u8[]>(size) };
		memcpy(shader.get(), shaders[i], size);
		group.map[keys[i]] = std::move(shader);
	}
	std::lock_guard lock{ shader_mutex };
	return shader_groups.add(std::move(group));
}
/**
 * @brief 删除着色器组。
 * @param id 着色器组 ID。
 */
void
remove_shader_group(id::id_type id)
{
	std::lock_guard lock{ shader_mutex };
	assert(id::is_valid(id));

	shader_groups[id].map.clear();
	shader_groups.remove(id);
}
/**
 * @brief 在着色器组内按键查找着色器。
 * @param id 着色器组 ID。
 * @param shader_key 查询键。
 * @return 命中时返回着色器指针。
 */
compiled_shader_ptr
get_shader(id::id_type id, u32 shader_key)
{
	std::lock_guard lock{ shader_mutex };
	assert(id::is_valid(id));
	for (const auto& [key, value] : shader_groups[id].map)
	{
		if (key == shader_key)
		{
			return (const compiled_shader_ptr)value.get();
		}
	}
	assert(false);

	return nullptr;
}


/**
 * @brief 获取几何资源包含的全部子网格 GPU ID。
 * @param geometry_content_id 几何内容资源 ID。
 * @param id_count 输出数组长度。
 * @param gpu_ids 输出数组。
 */
void
get_submesh_gpu_id(id::id_type geometry_content_id, u32 id_count, id::id_type *const gpu_ids)
{
	std::lock_guard lock{ geometry_mutex };
	u8 *const pointer{ geometry_hierarchies[geometry_content_id] };
	if ((uintptr_t)pointer & single_mesh_marker)
	{
		assert(id_count == 1);
		*gpu_ids = gpu_id_from_fake_pointer(pointer);
	}
	else
	{
		geometry_hierarchy_stream stream{ pointer };

		assert([&]() {
			const u32 lod_count{ stream.lod_count() };
			const lod_offset lod_offset{ stream.lod_offsets()[lod_count - 1] };
			const u32 gpu_id_count{ (u32)lod_offset.offset + (u32)lod_offset.count };
			return gpu_id_count == id_count;
			}());


		memcpy(gpu_ids, stream.gpu_ids(), sizeof(id::id_type) * id_count);

	}
}

/**
 * @brief 按阈值查询各几何实例使用的 LOD 偏移。
 * @param geometry_ids 几何资源 ID 数组。
 * @param thresholds 每个实例的阈值数组。
 * @param id_count 查询数量。
 * @param offsets 输出 LOD 偏移数组。
 */
void
get_lod_offset(const id::id_type *const geometry_ids, const f32 *const thresholds, u32 id_count, utl::vector<lod_offset>& offsets)
{
	assert(geometry_ids && thresholds && id_count);
	assert(offsets.empty());

	std::lock_guard lock{ geometry_mutex };

	for (u32 i{ 0 }; i < id_count; ++i)
	{
		u8 *const pointer{ geometry_hierarchies[geometry_ids[i]] };
		if ((uintptr_t)pointer & single_mesh_marker)
		{
			assert(id_count == 1);
			offsets.emplace_back(lod_offset{ 0,1 });
		}
		else
		{
			geometry_hierarchy_stream stream{ pointer };
			const u32 lod{ stream.lod_from_threshold(thresholds[i]) };
			offsets.emplace_back(stream.lod_offsets()[lod]);
		}
	}
}
}
