#ifndef MODEL_H
#define MODEL_H

#include "material.h"
#include "scriptstringlist.h"

struct XSurfaceVertexInfo
{
    qint16 vertCount[4];
    qint32 vertsBlendPtr;
    quint16 vertsBlend;
};

union GfxColor
{
    unsigned int packed;
    quint8 array[4];
};

union PackedTexCoords
{
    unsigned int packed;
};

union PackedUnitVec
{
    unsigned int packed;
};

struct GfxPackedVertex
{
    float xyz[3];
    float binormalSign;
    GfxColor color;
    PackedTexCoords texCoord;
    PackedUnitVec normal;
    PackedUnitVec tangent;
};

struct $E41E24A1CD47CDFA361AA9F99910948B
{
    unsigned __int32 Type : 2;
    unsigned __int32 BaseAddress : 30;
    unsigned __int32 Endian : 2;
    unsigned __int32 Size : 24;
    unsigned __int32 AddressClamp : 1;
    unsigned __int32 : 1;
    unsigned __int32 RequestSize : 2;
    unsigned __int32 ClampDisable : 2;
};

union GPUVERTEX_FETCH_CONSTANT
{
    $E41E24A1CD47CDFA361AA9F99910948B __s0;
    unsigned int dword[2];
};

struct D3DVertexBuffer : D3DResource
{
    GPUVERTEX_FETCH_CONSTANT Format;
};

struct XSurfaceCollisionAabb
{
    quint16 mins[3];
    quint16 maxs[3];
};

struct XSurfaceCollisionNode
{
    XSurfaceCollisionAabb aabb;
    quint16 childBeginIndex;
    quint16 childCount;
};

struct XSurfaceCollisionLeaf
{
    quint16 triangleBeginIndex;
};

struct XSurfaceCollisionTree
{
    float trans[3];
    float scale[3];
    unsigned int nodeCount;
    QVector<XSurfaceCollisionNode> nodes;
    unsigned int leafCount;
    QVector<XSurfaceCollisionLeaf> leafs;
};

struct XRigidVertList
{
    quint16 boneOffset;
    quint16 vertCount;
    quint16 triOffset;
    quint16 triCount;
    XSurfaceCollisionTree *collisionTree;
};

struct D3DIndexBuffer : D3DResource
{
    unsigned int Address;
    unsigned int Size;
};

struct XSurface
{
    quint8 tileMode;
    bool deformed;
    quint16 vertCount;
    quint16 triCount;
    quint16 *triIndices;
    XSurfaceVertexInfo vertInfo;
    GfxPackedVertex *verts0;
    D3DVertexBuffer vb0;
    unsigned int vertListCount;
    XRigidVertList *vertList;
    D3DIndexBuffer indexBuffer;
    int partBits[4];
};

struct DObjAnimMat
{
    float quat[4];
    float trans[3];
    float transWeight;
};

struct XModelLodInfo
{
    float dist;
    quint16 numsurfs;
    quint16 surfIndex;
    int partBits[4];
};

struct XModelCollSurf
{
    float mins[3];
    float maxs[3];
    int boneIdx;
    int contents;
    int surfFlags;
};

struct XBoneInfo
{
    float bounds[2][3];
    float offset[3];
    float radiusSquared;
};

struct XModelHighMipBounds
{
    float mins[3];
    float maxs[3];
};

struct XModelStreamInfo
{
    XModelHighMipBounds *highMipBounds;
};

struct PhysPreset
{
    qint32 namePtr;
    QString name;

    int type;

    float mass;
    float bounce;
    float friction;
    float bulletForceScale;
    float explosiveForceScale;

    qint32 sndAliasPrefixPtr;
    QString sndAliasPrefix;

    float piecesSpreadFraction;
    float piecesUpwardVelocity;

    bool tempDefaultToCylinder;
};

struct CPlane
{
    float normal[3];
    float dist;
    quint8 type;
    quint8 signbits;
    quint8 pad[2];
};

struct CBrushSide
{
    qint32 planePtr;
    CPlane plane;
    uint materialNum;
    qint16 firstAdjacentSideOffset;
    quint8 edgeCount;
};

struct BrushWrapper
{
    float mins[3];
    int contents;
    float maxs[3];
    unsigned int numsides;
    CBrushSide *sides;
    __int16 axialMaterialNum[2][3];
    quint8 *baseAdjacentSide;
    __int16 firstAdjacentSideOffsets[2][3];
    quint8 edgeCount[2][3];
    int totalEdgeCount;
    CPlane *planes;
};

struct PhysGeomInfo
{
    BrushWrapper *brush;
    int type;
    float orientation[3][3];
    float offset[3];
    float halfLengths[3];
};

struct PhysMass
{
    float centerOfMass[3];
    float momentsOfInertia[3];
    float productsOfInertia[3];
};

struct PhysGeomList
{
    unsigned int count;
    PhysGeomInfo *geoms;
    PhysMass mass;
};

struct Model
{
    QString name;
    qint32 namePtr;
    quint8 numBones;
    quint8 numRootBones;
    quint8 numsurfs;
    quint8 lodRampType;

    quint32 boneNamesPtr;
    ScriptStringList boneNames;

    quint32 parentListPtr;
    quint8 *parentList;

    qint32 quatsPtr;
    qint16 *quats;

    qint32 transPtr;
    float *trans;

    qint32 partClassPtr;
    quint8 *partClassification;

    qint32 baseMatPtr;
    DObjAnimMat *baseMat;

    qint32 surfsPtr;
    XSurface *surfs;

    qint32 matHandlesPtr;
    Material **materialHandles;

    XModelLodInfo lodInfo[4];

    qint32 collSurfsPtr;
    XModelCollSurf *collSurfs;

    int numCollSurfs;
    int contents;

    qint32 boneInfoPtr;
    XBoneInfo *boneInfo;

    float radius;
    float mins[3];
    float maxs[3];

    qint16 numLods;
    qint16 collLod;

    XModelStreamInfo streamInfo;
    int memUsage;
    quint8 flags;
    std::shared_ptr<PhysPreset> physPreset;

    qint32 physGeomsPtr;
    PhysGeomList *physGeoms;
};

#endif // MODEL_H
