#pragma once
#include "D3D12CommonHeader.h"

/**
 * @brief Direct3D 12 核心类
 * @details 定义了 Direct3D 12 核心功能的初始化与关闭函数
 */

namespace XEngine::graphics::d3d12 {
class descriptor_heap;
}

namespace XEngine::graphics::d3d12::core{
/**
 * @brief 初始化 Direct3D 12 核心功能
 * @details 调用 DXGI 接口，确定要使用的 GPU 并创建 Direct3D 12 设备
 * @return true 如果初始化成功，否则返回 false
 */
bool initialize();
/**
 * @brief 关闭 Direct3D 12 核心功能
 * @details 调用 Direct3D 12 设备的关闭函数，释放所有资源
 */
void shutdown();

/**
 * @brief 立即释放 DirectX COM 对象并将指针置空
 * @details 安全释放资源：若指针非空则调用其 Release() 方法，随后将原指针置为 nullptr。
 *          适用于所有继承自 IUnknown 的 COM 接口类型。
 * @tparam T COM 接口类型（如 ID3D12Resource、ID3D11Buffer 等）
 * @param resource 待释放的 COM 接口指针（引用传递，释放后自动置空）
 */
template<typename T>
constexpr void release(T*& resource)
{
    if(resource)
    {
        resource->Release();
        resource = nullptr;
    }
}

namespace detail {
/**
 * @brief 延迟释放 COM 对象（内部实现）
 * @details 将资源加入延迟释放队列，不立即调用 Release()，用于异步或帧末统一回收。
 * @param resource COM 对象指针（按值传递，仅用于记录，不修改外部指针）
 */
void deferred_release(IUnknown* resource);
} // namespace detail

/**
 * @brief 安全包装延迟释放，并将外部指针置空
 * @details 调用 detail::deferred_release 将资源加入延迟释放队列，同时将传入的指针置为 nullptr，
 *          防止调用者误用悬空指针。适用于需要延迟释放但希望立即清空原指针的场景。
 * @tparam T COM 接口类型
 * @param resource 待延迟释放的 COM 接口指针（引用传递，释放后自动置空）
 */
template<typename T>
constexpr void deferred_release(T*& resource)
{
    if(resource)
    {
        detail::deferred_release(resource);
        resource = nullptr;
    }
}

/**
 * @brief 获取 Direct3D 12 设备
 * @details 返回 Direct3D 12 设备的智能指针
 * @return ID3D12Device* Direct3D 12 设备的智能指针
 */
ID3D12Device *const device();

/**
 * @brief 获取当前帧索引
 * @details 返回当前渲染的帧索引
 * @return u32 当前帧索引
 */
u32 current_frame_index();

descriptor_heap& rtv_heap();
descriptor_heap& dsv_heap();
descriptor_heap& srv_heap();
descriptor_heap& uav_heap();

/**
 * @brief 获取默认渲染目标格式
 * @details 返回 Direct3D 12 设备的默认渲染目标格式
 * @return DXGI_FORMAT 默认渲染目标格式
 */
DXGI_FORMAT default_render_target_format();

/**
 * @brief 设置延迟释放标志
 * @details 用于在渲染循环中设置延迟释放标志，通知资源管理器在当前帧渲染完成后释放资源
 */
void set_deferred_release_flag();

surface create_surface(platform::window window);
void remove_surface(surface_id id);
void resize_surface(surface_id id, u32 width, u32 height);
u32 surface_width(surface_id id);
u32 surface_height(surface_id id);
void render_surface(surface_id id);


}// namespace XEngine::graphics::d3d12::core