#include "xmodel.h"
#include "xstring.h"

XModel::XModel()
    : XAsset()
    , mName()
    , mNumBones(0)
    , mNumRootBones(0)
    , mNumSurfs(0)
    , mLodRampType(0)
    , mBoneNames()
    , mParentList()
    , mQuats()
    , mTrans(0)
    , mPartClassification()
    , mBaseMat()
    , mSurfs()
    , mMaterialHandles()
    , mLodInfo(4)
    , mCollSurfs()
    , mNumCollSurfs(0)
    , mContents(0)
    , mBoneInfo()
    , mRadius(0)
    , mMins()
    , mMaxs()
    , mNumLods(0)
    , mCollLod(0)
    , mStreamInfo()
    , mMemUsage(0)
    , mFlags(0)
    , mPhysPreset()
    , mPhysGeoms()
{
    SetType(ASSET_TYPE_XMODEL);
    SetName("Model");
}

XModel::~XModel()
{

}

void XModel::ParseData(XDataStream *aStream) {
    mName.ParsePtr(aStream, false);

    qint32 boneNamesPtr, parentListPtr, quatsPtr, transPtr, partClassPtr;

    mNumBones = aStream->ParseUInt8(QString("%1 num bones").arg(GetName()));
    mNumRootBones = aStream->ParseUInt8(QString("%1 num root bones").arg(GetName()));
    mNumSurfs = aStream->ParseUInt8(QString("%1 num surfs").arg(GetName()));
    mLodRampType = aStream->ParseUInt8(QString("%1 lod ramp type").arg(GetName()));

    boneNamesPtr = aStream->ParseInt32(QString("%1 bone names ptr").arg(GetName()));
    parentListPtr = aStream->ParseInt32(QString("%1 parent list ptr").arg(GetName()));
    quatsPtr = aStream->ParseInt32(QString("%1 quats ptr").arg(GetName()));
    transPtr = aStream->ParseInt32(QString("%1 trans ptr").arg(GetName()));
    partClassPtr = aStream->ParseInt32(QString("%1 part classification ptr").arg(GetName()));

    mBaseMat.ParsePtr(aStream, false);

    qint32 surfsPtr = aStream->ParseInt32(QString("%1 surfs ptr").arg(GetName()));
    qint32 matHandlesPtr = aStream->ParseInt32(QString("%1 material handles ptr").arg(GetName()));

    for (int i = 0; i < 4; i++) {
        XModelLodInfo newLodInfo;
        newLodInfo.ParseData(aStream);
        mLodInfo.append(newLodInfo);
    }

    qint32 collSurfsPtr;
    collSurfsPtr = aStream->ParseInt32(QString("%1 coll surfs ptr").arg(GetName()));
    mNumCollSurfs = aStream->ParseInt32(QString("%1 num coll surfs").arg(GetName()));
    mContents = aStream->ParseInt32(QString("%1 contents").arg(GetName()));

    mBoneInfo.ParsePtr(aStream, false);

    mRadius = aStream->ParseSingle(QString("%1 radius").arg(GetName()));

    mMins.setX(aStream->ParseSingle(QString("%1 mins x").arg(GetName())));
    mMins.setY(aStream->ParseSingle(QString("%1 mins y").arg(GetName())));
    mMins.setZ(aStream->ParseSingle(QString("%1 mins z").arg(GetName())));

    mMaxs.setX(aStream->ParseSingle(QString("%1 maxs x").arg(GetName())));
    mMaxs.setY(aStream->ParseSingle(QString("%1 maxs y").arg(GetName())));
    mMaxs.setZ(aStream->ParseSingle(QString("%1 maxs z").arg(GetName())));

    mNumLods = aStream->ParseInt16(QString("%1 num lods").arg(GetName()));
    mCollLod = aStream->ParseInt16(QString("%1 coll lod").arg(GetName()));

    mStreamInfo.ParsePtr(aStream, false);

    mMemUsage = aStream->ParseInt32(QString("%1 mem usage").arg(GetName()));
    mFlags = aStream->ParseUInt8(QString("%1 flags").arg(GetName()));

    aStream->skipRawData(3);

    mPhysPreset.ParsePtr(aStream, false);
    mPhysGeoms.ParsePtr(aStream, false);

    mName.ParseData(aStream);

    if (boneNamesPtr == -1) {
        for (int i = 0; i < mNumBones; i++) {
            quint16 bone = aStream->ParseUInt16(QString("%1 bone %2").arg(GetName()).arg(i));
            mBoneNames.append(bone);
        }
    }

    if (parentListPtr == -1) {
        for (int i = 0; i < (mNumBones - mNumRootBones); i++) {
            quint8 parent = aStream->ParseUInt8(QString("%1 parent %2").arg(GetName()).arg(i));
            mParentList.append(parent);
        }
    }

    if (quatsPtr == -1) {
        for (int i = 0; i < 8 * (mNumBones - mNumRootBones); i++) {
            quint8 quat = aStream->ParseUInt8(QString("%1 quat %2").arg(GetName()).arg(i));
            mQuats.append(quat);
        }
    }

    if (transPtr == -1) {
        for (int i = 0; i < 16 * (mNumBones - mNumRootBones); i++) {
            float trans = aStream->ParseSingle(QString("%1 trans %2").arg(GetName()).arg(i));
            mTrans.append(trans);
        }
    }

    if (partClassPtr == -1) {
        for (int i = 0; i < mNumBones; i++) {
            quint8 partClass = aStream->ParseUInt8(QString("%1 part class %2").arg(GetName()).arg(i));
            mPartClassification.append(partClass);
        }
    }

    mBaseMat.ParseData(aStream);

    if (surfsPtr == -1) {
        for (int i = 0; i < mNumSurfs; i++) {
            XSurface newSurf;
            newSurf.ParseData(aStream);
            mSurfs.append(newSurf);
        }
    }

    if (matHandlesPtr == -1) {
        for (int i = 0; i < mNumSurfs; i++) {
            XMaterial newMaterial;
            newMaterial.ParseData(aStream);
            mMaterialHandles.append(newMaterial);
        }
    }

    if (collSurfsPtr == -1) {
        for (int i = 0; i < mNumCollSurfs; i++) {
            XModelCollSurf newCollSurf;
            newCollSurf.ParseData(aStream);
            mCollSurfs.append(newCollSurf);
        }
    }

    mBoneInfo.ParseData(aStream);
    mStreamInfo.ParseData(aStream);
    mPhysPreset.ParseData(aStream);
    mPhysGeoms.ParseData(aStream);
}


void XModel::Clear()
{

}
