#ifndef RENDER_RENDER_TYPE_DEF_H
#define RENDER_RENDER_TYPE_DEF_H

#include <string>
#include <DirectXMath.h>
#include <filesystem>
#include <vector>
#include <unordered_map>
#include <array>
#include <intsafe.h>


class Material;

namespace Z {
// C++ / HLSL 必须共同遵守的绑定约定
// global 约定。材质拥有t0-t7；
// 阴影拥有 t8/s2/b3。

namespace RenderBindings {
/* CBuffer */
constexpr UINT SceneCB = 0;            // b0
constexpr UINT MaterialCB = 1;         // b1
constexpr UINT PerObjectCB = 2;        // b2
constexpr UINT ShadowCB = 3;           // b3
constexpr UINT IBL_CB = 4;             // b4 (IBL-Constants)


/* Texture Buffer */
constexpr UINT MaterialTextureFirst = 0;
constexpr UINT MaterialTextureLast = 7;

constexpr UINT BaseColorTexture = 0; // t0, sRGB
constexpr UINT NormalTexture = 1;    // t1, Linear
constexpr UINT OrmTexture = 2;       // t2, Linear: R=AO, G=Roughness, B=Metallic
constexpr UINT EmissiveTexture = 3;  // t3, sRGB

constexpr UINT ShadowTexture = 8;        // t8
constexpr UINT IrradianceTexture = 9;    // t9
constexpr UINT PrefilteredTexture = 10;  // t10
constexpr UINT BrdfLutTexture = 11;      // t11


/* Sampler */
constexpr UINT MaterialSampler = 0;  // s0
constexpr UINT ShadowSampler = 2;    // s2
constexpr UINT IBLSamplerSlot = 3;   // s3

}

enum struct TextureType : uint8_t {
    NONE = 0, DIFFUSE = 1, SPECULAR = 2, AMBIENT = 3, EMISSIVE = 4,
    HEIGHT = 5, NORMALS = 6, SHININESS = 7, OPACITY = 8, DISPLACEMENT = 9,
    LIGHTMAP = 10, REFLECTION = 11, BASE_COLOR = 12, NORMAL_CAMERA = 13, EMISSION_COLOR = 14,
    METALNESS = 15, DIFFUSE_ROUGHNESS = 16, AMBIENT_OCCLUSION = 17, UNKNOWN = 18, SHEEN = 19,
    CLEARCOAT = 20, TRANSMISSION = 21, MAYA_BASE = 22, MAYA_SPECULAR = 23, SPECULAR_COLOR = 24,
    MAYA_SPECULAR_ROUGHNESS = 25, ANISOTROPY = 26, GLTF_METALLIC_ROUGHNESS = 27,
};


//region Model - Mesh
// Animation
struct PositionKey {
    double time;
    DirectX::XMFLOAT3 value;
};
struct RotationKey {
    double time;
    DirectX::XMFLOAT4 value;
};
struct ScaleKey {
    double time;
    DirectX::XMFLOAT3 value;
};
struct NodeAnimation {
    std::string name;
    std::vector<PositionKey> ar_posKeys;
    std::vector<RotationKey> ar_rotationKeys;
    std::vector<ScaleKey> ar_scaleKeys;
};
struct AnimationClip {
    std::string name;
    double durationTicks{0};
    double tickPerSec{25};
    std::unordered_map<std::string, NodeAnimation> map_channels;
};

// SkeletonData
struct Node {
    std::string name;
    DirectX::XMFLOAT4X4 localTsf;
    std::vector<Node> ar_child;
};
struct BoneInfo {
    std::string name;
    DirectX::XMFLOAT4X4 offsetMatrix;
};
struct SkeletonData {
    DirectX::XMFLOAT4X4 gInvTsf;
    std::vector<BoneInfo> ar_boneInfo;
    Node rootNode;
    std::unordered_map<std::string, unsigned int> map_boneName_idx;
};

// MeshData
constexpr int MAX_BONES_PER_VERT = 4;

struct VertexData { // 同时作为GPU数据传给VertexBuffer
    DirectX::XMFLOAT3 pos{};
    DirectX::XMFLOAT3 normal{};
    DirectX::XMFLOAT3 tangent{};
    DirectX::XMFLOAT2 uv0{};
    DirectX::XMFLOAT2 uv1{};
    DirectX::XMFLOAT4 color{};
    std::array<int, MAX_BONES_PER_VERT> ar_boneIndex; //将来初始化为-1
    std::array<float, MAX_BONES_PER_VERT> ar_boneWeights{};
};

struct TextureData {
    TextureType type;
    std::filesystem::path path;
    std::string name;
    std::vector<std::byte> data;
    unsigned int bytesPerPixel;
    unsigned int rowPitch;
    unsigned int size;
};

struct Mesh {
    int index; //在 Z::Model.ar_meshDatas 数组内的下标
    std::string name;
    DirectX::XMFLOAT4X4 localTsf;
    std::vector<VertexData> ar_vertices; // .data()作为buffer的data传给GPU去init
    std::vector<unsigned int> ar_indices; // .data()作为buffer的data传给GPU去init
    bool hasSkin{};
};

// Model ROOT
struct Model {
    std::string name;
    std::filesystem::path path;
    std::vector<Mesh> ar_meshDatas;
    SkeletonData skeletonData;
    std::vector<AnimationClip> ar_animationClips;
};
//endregion Model - Mesh


//MARK: 通信ShaderInfo
namespace ShaderInfo {
enum struct PropType {
    None = 0, Matrix3x3 = 1, Matrix4x4 = 2,
    Float = 10, Float2 = 11, Float3 = 12, Float4 = 13,
    Int = 20, Int2 = 21, Int3 = 22, Int4 = 23,
};

union Value {
    int Int;
    int Int2[2];
    int Int3[3];
    int Int4[4];
    float Float;
    float Float2[2];
    float Float3[3];
    float Float4[4];
    float Float3x3[3][3];
    float Float4x4[4][4];
};

struct PropInfo {
    const char *name;
    int index; // prop在cubufferinfo的array里的下标
    PropType type;
    Value value;
};

struct TexInfo {
    const char *name;
    int index;  // tex在shaderinfo的array里的下标
};

struct CbufferInfo {
    ~CbufferInfo() { delete []ar_prop; }
    const char *name;
    int index;
    PropInfo *ar_prop;
    int c_prop;
};

struct ShaderInfo {
    ~ShaderInfo() {
        delete[] ar_cbuffer;
        delete[] ar_tex;
    }
    const char *name;
    CbufferInfo *ar_cbuffer;
    int c_cbuffer;
    TexInfo *ar_tex;
    int c_tex;
};
}

















}
#endif //RENDER_RENDER_TYPE_DEF_H
