#ifndef MATERIAL_H
#define MATERIAL_H

#include "materialtechset.h"

struct GfxDrawSurfFields
{
    quint64 objectId : 16;
    quint64 reflectionProbeIndex : 8;
    quint64 customIndex : 5;
    quint64 materialSortedIndex : 11;
    quint64 prepass : 2;
    quint64 primaryLightIndex : 8;
    quint64 surfType : 4;
    quint64 primarySortKey : 6;
    quint64 unused : 4;
};

struct MaterialInfo
{
    qint32 namePtr;
    QString name;

    quint8 gameFlags;
    quint8 sortKey;
    quint8 textureAtlasRowCount;
    quint8 textureAtlasColumnCount;
    GfxDrawSurfFields drawSurf;
    unsigned int surfaceTypeBits;
};

enum MapType : qint32
{
    MAPTYPE_NONE = 0x0,
    MAPTYPE_INVALID1 = 0x1,
    MAPTYPE_INVALID2 = 0x2,
    MAPTYPE_2D = 0x3,
    MAPTYPE_3D = 0x4,
    MAPTYPE_CUBE = 0x5,
    MAPTYPE_COUNT = 0x6,
};

struct GPUTEXTURESIZE_1D
{
    quint32 Width : 24;
};

struct GPUTEXTURESIZE_2D
{
    quint32 Width : 13;
    quint32 Height : 13;
};

struct GPUTEXTURESIZE_3D
{
    quint32 Width : 11;
    quint32 Height : 11;
    quint32 Depth : 10;
};

struct GPUTEXTURESIZE_STACK
{
    quint32 Width : 13;
    quint32 Height : 13;
    quint32 Depth : 6;
};

struct GPUTEXTURE_FETCH_CONSTANT
{
    quint32 Type : 2;
    quint32 SignX : 2;
    quint32 SignY : 2;
    quint32 SignZ : 2;
    quint32 SignW : 2;
    quint32 ClampX : 3;
    quint32 ClampY : 3;
    quint32 ClampZ : 3;
    quint32 : 3;
    quint32 Pitch : 9;
    quint32 Tiled : 1;

    quint32 DataFormat : 6;
    quint32 Endian : 2;
    quint32 RequestSize : 2;
    quint32 Stacked : 1;
    quint32 ClampPolicy : 1;
    quint32 BaseAddress : 20;
    union
    {
        GPUTEXTURESIZE_1D OneD;
        GPUTEXTURESIZE_2D TwoD;
        GPUTEXTURESIZE_3D ThreeD;
        GPUTEXTURESIZE_STACK Stack;
    } Size;

    quint32 NumFormat : 1;
    quint32 SwizzleX : 3;
    quint32 SwizzleY : 3;
    quint32 SwizzleZ : 3;
    quint32 SwizzleW : 3;
    qint32 ExpAdjust : 6;
    quint32 MagFilter : 2;
    quint32 MinFilter : 2;
    quint32 MipFilter : 2;
    quint32 AnisoFilter : 3;
    quint32 : 3;
    quint32 BorderSize : 1;

    quint32 VolMagFilter : 1;
    quint32 VolMinFilter : 1;
    quint32 MinMipLevel : 4;
    quint32 MaxMipLevel : 4;
    quint32 MagAnisoWalk : 1;
    quint32 MinAnisoWalk : 1;
    qint32 LODBias : 10;
    qint32 GradExpAdjustH : 5;
    qint32 GradExpAdjustV : 5;

    quint32 BorderColor : 2;
    quint32 ForceBCWToMax : 1;
    quint32 TriClamp : 2;
    qint32 AnisoBias : 4;
    quint32 Dimension : 2;
    quint32 PackedMips : 1;
    quint32 MipAddress : 20;
};

// QDataStream &operator>>(QDataStream &in, GPUTEXTURE_FETCH_CONSTANT &s)
// {
//     quint32 raw1, raw2, raw3, raw4, raw5;
//     in >> raw1 >> raw2 >> raw3 >> raw4 >> raw5;

//     s.Type          =  raw1             & 0b000000000000000000000011;
//     s.SignX         = (raw1 >> 2)       & 0b000000000000000000000011;
//     s.SignY         = (raw1 >> 4)       & 0b000000000000000000000011;
//     s.SignZ         = (raw1 >> 6)       & 0b000000000000000000000011;
//     s.SignW         = (raw1 >> 8)       & 0b000000000000000000000011;
//     s.ClampX        = (raw1 >> 10)      & 0b000000000000000000000111;
//     s.ClampY        = (raw1 >> 13)      & 0b000000000000000000000111;
//     s.ClampZ        = (raw1 >> 16)      & 0b000000000000000000000111;
//     s.Pitch         = (raw1 >> 22)      & 0b000000000000000111111111;
//     s.Tiled         = (raw1 >> 31)      & 0b000000000000000000000001;

//     s.DataFormat    = raw2              & 0b000000000000000000111111;
//     s.Endian        = (raw2 >> 6)       & 0b000000000000000000000011;
//     s.RequestSize   = (raw2 >> 8)       & 0b000000000000000000000011;
//     s.Stacked       = (raw2 >> 10)      & 0b000000000000000000000001;
//     s.ClampPolicy   = (raw2 >> 11)      & 0b000000000000000000000001;
//     s.BaseAddress   = (raw2 >> 12)      & 0b000011111111111111111111;
//     s.Size          = (raw2 >> 32)      & 0b000000000000000000001111;

//     s.NumFormat     = raw3              & 0b000000000000000000000001;
//     s.SwizzleX      = (raw3 >> 32)      & 0b000000000000000000000111;
//     s.SwizzleY      = (raw3 >> 32)      & 0b000000000000000000000111;
//     s.SwizzleZ      = (raw3 >> 32)      & 0b000000000000000000000111;
//     s.SwizzleW      = (raw3 >> 32)      & 0b000000000000000000000111;
//     s.ExpAdjust     = (raw3 >> 32)      & 0b000000000000000000111111;
//     s.MagFilter     = (raw3 >> 32)      & 0b000000000000000000001111;
//     s.MinFilter     = (raw3 >> 32)      & 0b000000000000000000001111;
//     s.MipFilter     = (raw3 >> 32)      & 0b000000000000000000001111;
//     s.AnisoFilter   = (raw3 >> 32)      & 0b000000000000000000001111;
//     s.: 3;
//     s.BorderSize =
//     s.VolMagFilter =
//     s.VolMinFilter =
//     s.MinMipLevel =
//     s.MaxMipLevel =
//     s.MagAnisoWalk =
//     s.MinAnisoWalk =
//     s.LODBias =
//     s.GradExpAdjustH =
//     s.GradExpAdjustV =
//     s.BorderColor =
//     s.ForceBCWToMax =
//     s.TriClamp =
//     s.AnisoBias =
//     s.Dimension =
//     s.PackedMips =
//     s.MipAddress =






//     return in;
// }

struct D3DBaseTexture : D3DResource
{
    unsigned int MipFlush;
    GPUTEXTURE_FETCH_CONSTANT Format;
};

struct D3DTexture : D3DBaseTexture
{
};

struct D3DVolumeTexture : D3DBaseTexture
{
};

struct D3DCubeTexture : D3DBaseTexture
{
};

struct WaterWritable
{
    float floatTime;
};

struct GfxImage;
struct water_t
{
    WaterWritable writable;
    float *H0X;
    float *H0Y;
    float *wTerm;
    int M;
    int N;
    float Lx;
    float Lz;
    float gravity;
    float windvel;
    float winddir[2];
    float amplitude;
    float codeConstant[4];
    GfxImage *image;
};

union MaterialTextureDefInfo
{
    GfxImage *image;
    water_t *water;
};

struct MaterialTextureDef
{
    unsigned int nameHash;
    char nameStart;
    char nameEnd;
    quint8 samplerState;
    quint8 semantic;
    MaterialTextureDefInfo u;
};

struct MaterialConstantDef
{
    unsigned int nameHash;
    char name[12];
    float literal[4];
};

struct GfxStateBits
{
    unsigned int loadBits[2];
};

struct Material
{
    MaterialInfo info;

    quint8 stateBitsEntry[26];
    quint8 textureCount;
    quint8 constantCount;
    quint8 stateBitsCount;
    quint8 stateFlags;
    quint8 cameraRegion;

    qint32 techSetPtr;
    MaterialTechSet *techniqueSet;

    qint32 textureTablePtr;
    MaterialTextureDef *textureTable;

    qint32 constantTablePtr;
    MaterialConstantDef *constantTable;

    qint32 stateBitsTablePtr;
    GfxStateBits *stateBitsTable;
};

#endif // MATERIAL_H
