#ifndef RENDER_TEXTURE_H
#define RENDER_TEXTURE_H
#include <render_type_def.h>
#include <render/task.h>
#include <d3d11.h>
#include <string>
#include <wrl/client.h>

struct TexSampler { //=
    static ID3D11SamplerState *S_DefaultColorSamper();

private:
    friend class WndRender; // 在WM_CREATE阶段被WndRender调用初始化
    static bool S_InitOnWmCreate(HWND hwnd, ID3D11Device *device);
}; //class TexSampler

class Texture2D { //=
public:
    //[add]
    struct RawCreateDesc {
        std::string name;
        UINT width = 0;
        UINT height = 0;
        DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN;
        const void *data = nullptr;
        UINT rowPitch = 0;
        UINT slicePitch = 0;
    };

    // [新增] 供 IBL 烘焙器创建可作为 RTV 写入、随后作为 SRV 采样的二维纹理。
    struct RenderTargetCreateDesc {
        std::string name;
        UINT width = 0;
        UINT height = 0;
        DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN;
    };

public:
    static int S_AddTexture(const Z::Task::AddTextureResource *data, ID3D11Device *device);
    static Texture2D *S_GetTexture2D(const char *texStemName);

    //[add] BRDF 集成 LUT 等资源使用的通用linear/HDR 路径
    // LUT:
    // 横坐标（U轴）：粗糙度（Roughness，0 ~ 1）
    // 纵坐标（V轴）：表面法线与视线夹角的余弦值（(cosθ) 或 N ⋅ V，0 ~ 1）
    // 输出颜色：RG 两个通道，分别代表菲涅耳项的线性近似系数（Scale 和 Bias）
    [[nodiscard]] static std::unique_ptr<Texture2D> S_CreateImmutable(ID3D11Device *device,
                                                                      const RawCreateDesc &desc);
    // [新增] 创建同时具有 D3D11_BIND_RENDER_TARGET 和
    // D3D11_BIND_SHADER_RESOURCE 的二维纹理。
    [[nodiscard]] static std::unique_ptr<Texture2D> CreateRenderTarget(
        ID3D11Device *device, const RenderTargetCreateDesc &desc);

    [[nodiscard]] static ID3D11ShaderResourceView *S_WhiteSRGB() noexcept;
    [[nodiscard]] static ID3D11ShaderResourceView *S_FlatNormalLinear() noexcept;
    [[nodiscard]] static ID3D11ShaderResourceView *S_DefaultOrmLinear() noexcept;
    [[nodiscard]] static ID3D11ShaderResourceView *S_BlackSRGB() noexcept;

private:
    friend class WndRender; // 在WM_CREATE阶段被WndRender调用初始化
    static bool S_InitOnWmCreate(HWND hwnd, ID3D11Device *device);

public:
    Texture2D(int index, const Z::Task::AddTextureResource *tex, ID3D11Device *device);
    //[add]
    [[nodiscard]] ID3D11Texture2D *Resource() const noexcept { return cp_tex2D.Get(); }
    //[add]
    [[nodiscard]] ID3D11ShaderResourceView *SRV() const noexcept { return cp_srv.Get(); }


    Z::TextureType type;
    bool bpp16;
    bool srgb;
    unsigned int index;
    const std::string name;
    const unsigned int rowPitch;
    const unsigned int size;
    Microsoft::WRL::ComPtr<ID3D11Texture2D> cp_tex2D;
    Microsoft::WRL::ComPtr<ID3D11ShaderResourceView> cp_srv;

private:
    //[add]
    Texture2D(std::string textureName, unsigned int textureRowPitch,
              unsigned int textureSize);
}; // class Texture2D

class TextureCube final { //=[add]
public: // definitions
    using FacePaths = std::array<std::filesystem::path, 6>;

    // D3D11的 cube face 顺序是固定的,而且必须与源数据相符
    enum class Face : UINT {
        PositiveX = 0, NegativeX = 1, PositiveY = 2,
        NegativeY = 3, PositiveZ = 4, NegativeZ = 5
    };

    struct SubresourceData {
        const void *data = nullptr;
        UINT rowPitch = 0;
        UINT slicePitch = 0;
    };

    // subresources 使用 D3D11 顺序: face * mipLevels + mip.
    struct CreateDesc {
        std::string name;
        UINT size = 0;
        UINT mipLevels = 1;
        DXGI_FORMAT format = DXGI_FORMAT_R16G16B16A16_FLOAT;
        std::vector<SubresourceData> subresources;
    };

public: // static
    // 创建一个不可变的立方体。这是预烘焙辐照度和预过滤环境贴图（包括自定义 mip 链）的首选路径。
    [[nodiscard]] static std::unique_ptr<TextureCube> S_Create(ID3D11Device *device,
                                                               const CreateDesc &desc);

    // 从六个基本面创建一个立方体，并要求 D3D11 生成一个常规 mip 链。这适用于天空盒，不适用于 GGX 预过滤。
    [[nodiscard]] static std::unique_ptr<TextureCube> S_CreateWithGeneratedMips(
        ID3D11Device *device,
        ID3D11DeviceContext *context,
        std::string name,
        UINT size,
        DXGI_FORMAT format,
        const std::array<SubresourceData, 6> &faces);

    // 六个已创建的Texture2D 资源的便捷路径。仅复制 mip 0；可选的 mip 生成使用硬件盒过滤器。
    [[nodiscard]] static std::unique_ptr<TextureCube> S_CreateFromTexture2Ds(
        ID3D11Device *device,
        ID3D11DeviceContext *context,
        std::string name,
        const std::array<const Texture2D *, 6> &faces,
        bool generateMips);

    // [新增] 使用 Windows Imaging Component 从六个文件导入 TextureCube。
    // 支持系统 WIC 已安装解码器能够读取的 PNG/JPG/BMP/TIFF 等格式。
    // 六张图必须尺寸一致且为正方形。
    [[nodiscard]] static std::unique_ptr<TextureCube> LoadFromFiles(
        ID3D11Device *device,
        ID3D11DeviceContext *context,
        std::string name,
        const FacePaths &facePaths,
        bool useSrgbView = true,
        bool generateMips = true);

    // [新增] 创建供 IBL 烘焙器逐面、逐 mip 写入的浮点 TextureCube。
    [[nodiscard]] static std::unique_ptr<TextureCube> CreateRenderTarget(
        ID3D11Device *device,
        std::string name,
        UINT size,
        UINT mipLevels,
        DXGI_FORMAT format = DXGI_FORMAT_R16G16B16A16_FLOAT);

public: // instance
    [[nodiscard]] ID3D11Texture2D *Resource() const noexcept { return m_texture.Get(); }
    [[nodiscard]] ID3D11ShaderResourceView *SRV() const noexcept { return m_srv.Get(); }
    [[nodiscard]] UINT Size() const noexcept { return m_size; }
    [[nodiscard]] UINT MipLevels() const noexcept { return m_mipLevels; }
    [[nodiscard]] DXGI_FORMAT Format() const noexcept { return m_format; }
    [[nodiscard]] const std::string &Name() const noexcept { return m_name; }

private: //static
    static bool S_SupportsGeneratedMips(ID3D11Device *device, DXGI_FORMAT format);
    static bool S_CreateCubeSRV(ID3D11Device *device, TextureCube &cube);

private: //instance
    TextureCube(std::string name, UINT size, UINT mipLevels, DXGI_FORMAT format);

private:
    std::string m_name;
    UINT m_size = 0;
    UINT m_mipLevels = 0;
    DXGI_FORMAT m_format = DXGI_FORMAT_UNKNOWN;
    Microsoft::WRL::ComPtr<ID3D11Texture2D> m_texture;
    Microsoft::WRL::ComPtr<ID3D11ShaderResourceView> m_srv;
}; // class TextureCube















#endif //RENDER_TEXTURE_H
