#include "xgfxworld.h"
#include "xstring.h"

XGfxWorld::XGfxWorld()
    : XAsset()
    , mName()
    , mBaseName()
    , mPlaneCount(0)
    , mNodeCount(0)
    , mIndexCount(0)
    , mIndices(0)
    , mIndexBuffer()
    , mSurfaceCount(0)
    , mStreamInfo()
    , mSkySurfCount(0)
    , mSkyStartSurfs()
    , mSkyImage()
    , mSkySamplerState(0)
    , mVertexCount(0)
    , mVertexData()
    , mVertexLayerDataSize(0)
    , mVertexLayerData()
    , mSunParse()
    , mSunLight()
    , mSunColorFromBsp()
    , mSunPrimaryLightIndex(0)
    , mPrimaryLightCount(0)
    , mCullGroupCount(0)
    , mReflectionProbeCount(0)
    , mReflectionProbes()
    , mReflectionProbeTextures()
    , mDpvsPlanes()
    , mCellBitsCount(0)
    , mCells()
    , mLightmapCount(0)
    , mLightmaps()
    , mLightGrid()
    , mLightmapPrimaryTextures()
    , mLightmapSecondaryTextures()
    , mModelCount(0)
    , mModels()
    , mMins()
    , mMaxs()
    , mChecksum(0)
    , mMaterialMemoryCount(0)
    , mMaterialMemory()
    , mSun()
    , mOutdoorLookupMatrix()
    , mOutdoorImage()
    , mCellCasterBits()
    , mSceneDynModel()
    , mSceneDynBrush()
    , mPrimaryLightEntityShadowVis()
    , mPrimaryLightDynEntShadowVis()
    , mNonSunPrimaryLightForModelDynEnt()
    , mShadowGeom()
    , mLightRegion()
    , mDpvs()
    , mDpvsDyn()
{
    SetType(ASSET_TYPE_GFXWORLD);
    SetName("GFXWorld");
}

XGfxWorld::~XGfxWorld()
{

}

void XGfxWorld::ParseData(QDataStream *aStream) {
    if (GetPtr() == -1) {
        mName.ParsePtr(aStream, false);
        mBaseName.ParsePtr(aStream, false);

        qint32 indicesPtr;
        *aStream
            >> mPlaneCount
            >> mNodeCount
            >> mIndexCount
            >> indicesPtr;

        mIndexBuffer.ParseData(aStream);

        *aStream >> mSurfaceCount;

        mStreamInfo.SetPtr(-1);
        mStreamInfo.ParseData(aStream);

        qint32 skyStartSurfPtr, skyImagePtr;
        *aStream
            >> mSkySurfCount
            >> skyStartSurfPtr
            >> skyImagePtr
            >> mSkySamplerState;

        aStream->skipRawData(3);

        *aStream >> mVertexCount;

        mVertexData.ParseData(aStream);

        *aStream >> mVertexLayerDataSize;

        mVertexLayerData.ParseData(aStream);
        mSunParse.ParseData(aStream);

        mSunLight.ParsePtr(aStream, false);

        float r, g, b;
        *aStream
            >> r
            >> g
            >> b;
        mSunColorFromBsp = QColor(r, g, b);

        qint32 reflectionProbesPtr, reflectionProbeTexturesPtr;
        *aStream
            >> mSunPrimaryLightIndex
            >> mPrimaryLightCount
            >> mCullGroupCount
            >> mReflectionProbeCount
            >> reflectionProbesPtr
            >> reflectionProbeTexturesPtr;

        mDpvsPlanes.ParseData(aStream);

        qint32 cellsPtr, lightmapsPtr;
        *aStream
            >> mCellBitsCount
            >> cellsPtr
            >> mLightmapCount
            >> lightmapsPtr;

        mLightGrid.ParseData(aStream);

        qint32 lightMapsPrimaryPtr, lightmapSecondaryPtr, modelsPtr, materialMemoryPtr;
        *aStream
            >> lightMapsPrimaryPtr
            >> lightmapSecondaryPtr
            >> mModelCount
            >> modelsPtr
            >> mMins[0]
            >> mMins[1]
            >> mMins[2]
            >> mMaxs[0]
            >> mMaxs[1]
            >> mMaxs[2]
            >> mChecksum
            >> mMaterialMemoryCount
            >> materialMemoryPtr;

        mSun.ParseData(aStream);

        for (int i = 0; i < 4; i++)
        {
            for (int j = 0; j < 4; j++)
            {
                mOutdoorLookupMatrix[i][j];
            }
        }

        qint32 outdoorImagePtr, cellCasterBitsPtr, sceneDynModelPtr, sceneDynBrushPtr,
            primaryLightEntPtr, primaryLightDynPtr, nonSunPrimaryPtr, shadowGeomPtr, lightRegionPtr;
        *aStream
            >> outdoorImagePtr
            >> cellCasterBitsPtr
            >> sceneDynModelPtr
            >> sceneDynBrushPtr
            >> primaryLightEntPtr
            >> primaryLightDynPtr
            >> nonSunPrimaryPtr
            >> shadowGeomPtr
            >> lightRegionPtr;

        mDpvs.ParseData(aStream);
        mDpvsDyn.ParseData(aStream);

        mName.ParseData(aStream);
        mBaseName.ParseData(aStream);

        if (indicesPtr)
        {
            aStream->readRawData(mIndices.data(), 2 * mIndexCount);
        }

        //mIndexBuffer.ParseData(aStream);

        if (skyStartSurfPtr)
        {
            for (int i = 0; i < mSkySurfCount; i++)
            {
                qint32 newSurface;
                *aStream >> newSurface;
                mSkyStartSurfs.append(newSurface);
            }
        }

        mSkyImage.ParseData(aStream);
        mSunLight.ParseData(aStream);

        if (reflectionProbesPtr)
        {
            for (int i = 0; i < mReflectionProbeCount; i++)
            {
                XGfxReflectionProbe newProbe;
                newProbe.ParseData(aStream);
                mReflectionProbes.append(newProbe);
            }
        }

        if (reflectionProbeTexturesPtr)
        {
            for (int i = 0; i < mReflectionProbeCount; i++)
            {
                XGfxTexture newProbeTexture;
                newProbeTexture.ParseData(aStream);
                mReflectionProbeTextures.append(newProbeTexture);
            }
        }

        mDpvsPlanes.ParseData(aStream);

        if (cellsPtr)
        {
            for (int i = 0; i < mDpvsPlanes.GetCellCount(); i++)
            {
                XGfxCell newCell;
                newCell.ParseData(aStream);
                mCells.append(newCell);
            }
        }

        if (lightmapsPtr)
        {
            for (int i = 0; i < mLightmapCount; i++)
            {
                XGfxLightmapArray lightMapArray;
                lightMapArray.ParseData(aStream);
                mLightmaps.append(lightMapArray);
            }
        }

        mLightGrid.ParseData(aStream);

        if (lightMapsPrimaryPtr)
        {
            for (int i = 0; i < mLightmapCount; i++)
            {
                XGfxTexture primaryTexture;
                primaryTexture.ParseData(aStream);
                mLightmapPrimaryTextures.append(primaryTexture);
            }
        }
        if (lightmapSecondaryPtr)
        {
            for (int i = 0; i < mLightmapCount; i++)
            {
                XGfxTexture secondaryTexture;
                secondaryTexture.ParseData(aStream);
                mLightmapSecondaryTextures.append(secondaryTexture);
            }
        }
        if (modelsPtr)
        {
            for (int i = 0; i < mModelCount; i++)
            {
                XGfxBrushModel newModel;
                newModel.ParseData(aStream);
                mModels.append(newModel);
            }
        }
        if (materialMemoryPtr)
        {
            for (int i = 0; i < mMaterialMemoryCount; i++)
            {
                XMaterialMemory newMaterialMemory;
                newMaterialMemory.ParseData(aStream);
                mMaterialMemory.append(newMaterialMemory);
            }
        }

        //mVertexData.ParseData(aStream);
        //mVertexLayerData.ParseData(aStream);

        mSun.ParseData(aStream);
        mOutdoorImage.ParseData(aStream);

        if (cellCasterBitsPtr)
        {
            for (int i = 0; i < ((mDpvsPlanes.GetCellCount() + 31) >> 5) * mDpvsPlanes.GetCellCount(); i++)
            {
                quint32 casterBit;
                *aStream >> casterBit;
                mCellCasterBits.append(casterBit);
            }
        }

        if (sceneDynModelPtr)
        {
            for (int i = 0; i < mDpvsDyn.GetClientCount(1); i++)
            {
                XGfxSceneDynModel dynModel;
                dynModel.ParseData(aStream);
                mSceneDynModel.append(dynModel);
            }
        }
        if (sceneDynBrushPtr)
        {
            for (int i = 0; i < mDpvsDyn.GetClientCount(1); i++)
            {
                XGfxSceneDynBrush dynBrush;
                dynBrush.ParseData(aStream);
                mSceneDynBrush.append(dynBrush);
            }
        }
    }
    // TODO: Finish this... Double ugh
}

void XGfxWorld::Clear()
{

}
