//
// Generated by dtk
// Translation Unit: J3DClusterLoader.cpp
//

#include "JSystem/JSystem.h" // IWYU pragma: keep

#include "JSystem/J3DGraphLoader/J3DClusterLoader.h"
#include "JSystem/J3DGraphAnimator/J3DSkinDeform.h"
#include "m_Do/m_Do_printf.h"
#include "JSystem/JSupport/JSupport.h"
#include "JSystem/JUtility/JUTNameTab.h"

/* 802FB04C-802FB0E8       .text load__24J3DClusterLoaderDataBaseFPCv */
void* J3DClusterLoaderDataBase::load(const void* i_data) {
    const JUTDataFileHeader* fileHeader = (JUTDataFileHeader*)i_data;
    if (fileHeader->mMagic == 'J3D1' && fileHeader->mType == 'bls1') {
        J3DClusterLoader_v15 loader;
        return loader.load(i_data);
    } else if (fileHeader->mMagic == 'J3D2' && fileHeader->mType == 'bls2') {
        return NULL;
    }
    return NULL;
}

/* 802FB0E8-802FB104       .text __ct__20J3DClusterLoader_v15Fv */
J3DClusterLoader_v15::J3DClusterLoader_v15() {}

/* 802FB104-802FB160       .text __dt__20J3DClusterLoader_v15Fv */
J3DClusterLoader_v15::~J3DClusterLoader_v15() {}

/* 802FB160-802FB21C       .text load__20J3DClusterLoader_v15FPCv */
void* J3DClusterLoader_v15::load(const void* i_data) {
    mpDeformData = new J3DDeformData();
    mpDeformData->clear();

    const JUTDataFileHeader* fileHeader = (JUTDataFileHeader*)i_data;
    const JUTDataBlockHeader* block = &fileHeader->mFirstBlock;
    for (int i = 0; i < fileHeader->mBlockNum; i++) {
        switch (block->mType) {
        case 'CLS1':
            readCluster((J3DClusterBlock*)block);
            break;
        default:
            OSReport("Unknown data block\n");
            break;
        }
        block = (JUTDataBlockHeader*)((u8*)block + block->mSize);
    }

    return mpDeformData;
}

/* 802FB21C-802FB698       .text readCluster__20J3DClusterLoader_v15FPC15J3DClusterBlock */
void J3DClusterLoader_v15::readCluster(const J3DClusterBlock* block) {
    mpDeformData->mClusterNum = block->mClusterNum;
    mpDeformData->mClusterKeyNum = block->mClusterKeyNum;
    mpDeformData->mVtxPosNum = block->mVtxPosNum;
    mpDeformData->mVtxNrmNum = block->mVtxNrmNum;
    mpDeformData->mClusterVertexNum = block->mClusterVertexNum;

    if (block->mClusterName != NULL) {
        mpDeformData->mClusterName = new JUTNameTab(JSUConvertOffsetToPtr<ResNTAB>(block, block->mClusterName));
    } else {
        mpDeformData->mClusterName = NULL;
    }
    if (block->mClusterKeyName != NULL) {
        mpDeformData->mClusterKeyName = new JUTNameTab(JSUConvertOffsetToPtr<ResNTAB>(block, block->mClusterKeyName));
    } else {
        mpDeformData->mClusterKeyName = NULL;
    }

    mpDeformData->mVtxPos = JSUConvertOffsetToPtr<f32>(block, block->mVtxPos);
    mpDeformData->mVtxNrm = JSUConvertOffsetToPtr<f32>(block, block->mVtxNrm);

    mpDeformData->mClusterPointer = new J3DCluster[mpDeformData->getClusterNum()];
    J3DCluster* blockCluster = JSUConvertOffsetToPtr<J3DCluster>(block, block->mClusterPointer);
    for (int i = 0; i < mpDeformData->getClusterNum(); i++) {
        mpDeformData->mClusterPointer[i] = blockCluster[i];
    }

    mpDeformData->mClusterKeyPointer = new J3DClusterKey[mpDeformData->getClusterKeyNum()];
    J3DClusterKey* blockClusterKey = JSUConvertOffsetToPtr<J3DClusterKey>(block, block->mClusterKeyPointer);
    for (int i = 0; i < mpDeformData->getClusterKeyNum(); i++) {
        mpDeformData->mClusterKeyPointer[i] = blockClusterKey[i];
    }

    mpDeformData->mClusterVertex = new J3DClusterVertex[mpDeformData->mClusterVertexNum];
    J3DClusterVertex* blockClusterVertex = JSUConvertOffsetToPtr<J3DClusterVertex>(block, block->mClusterVertex);
    for (int i = 0; i < mpDeformData->mClusterVertexNum; i++) {
        mpDeformData->mClusterVertex[i] = blockClusterVertex[i];
    }

    for (int i = 0; i < mpDeformData->getClusterNum(); i++) {
        J3DCluster* cluster = &mpDeformData->mClusterPointer[i];
        cluster->mClusterKey = JSUConvertOffsetToPtr<J3DClusterKey>(block, cluster->mClusterKey);
        cluster->mPosDstIdx = JSUConvertOffsetToPtr<u16>(block, cluster->mPosDstIdx);
        J3DClusterVertex* clusterVertex = JSUConvertOffsetToPtr<J3DClusterVertex>(block, cluster->mClusterVertex);
        u32 vertexIdx = (clusterVertex - blockClusterVertex) / sizeof(J3DClusterVertex);
        cluster->mClusterVertex = &mpDeformData->mClusterVertex[vertexIdx];
        J3DDeformer* deformer = new J3DDeformer(mpDeformData);
        if (cluster->mNrmNum != 0) {
            deformer->field_0x0c = new f32[cluster->mNrmNum * 3];
        } else {
            deformer->field_0x0c = NULL;
        }
        deformer->mFlags = cluster->mFlags;
        deformer->mWeightList = new f32[cluster->mKeyNum];
        cluster->setDeformer(deformer);
    }

    for (int i = 0; i < mpDeformData->getClusterKeyNum(); i++) {
        J3DClusterKey* clusterKey = &mpDeformData->mClusterKeyPointer[i];
        clusterKey->mPosFlag = JSUConvertOffsetToPtr<u16>(block, clusterKey->mPosFlag);
        clusterKey->mNrmFlag = JSUConvertOffsetToPtr<u16>(block, clusterKey->mNrmFlag);
    }

    for (int i = 0; i < mpDeformData->mClusterVertexNum; i++) {
        J3DClusterVertex* clusterVertex = &mpDeformData->mClusterVertex[i];
        clusterVertex->mSrcIdx = JSUConvertOffsetToPtr<u16>(block, clusterVertex->mSrcIdx);
        clusterVertex->mDstIdx = JSUConvertOffsetToPtr<u16>(block, clusterVertex->mDstIdx);
    }
}
