#include <stdint.h>

#include "../core_memory/core_memory_private.h"
#include "../core_runtime/core_runtime_private.h"
#include "coduo_engine_structs.h"
#include "dobj_private.h"
#include "xanim_private.h"

void SV_DObjDumpInfo(int32_t entityNum)
{
    DObj *state;

    if (developer->integer == 0) {
        return;
    }

    state = DObjGetForEntity(entityNum);
    if (state == NULL) {
        Com_Printf("no model.\n");
    } else {
        DObjDumpInfo(state);
    }
}

qboolean SV_DObjCreateSkelForBone(int32_t entityNum,
                                  int32_t boneIndex)
{
    DObj *state;
    coduo_xanim_eval_storage_t *storage;
    int32_t storageSize;

    state = DObjGetForEntity(entityNum);
    if (DObjRefreshEvalStorageKey(state, dobj_skelCacheKey) != 0) {
        return DObjSkelIsBoneUpToDate(state, boneIndex);
    }

    storageSize = DObjEvalStorageSize(state);
    storage = Hunk_AllocateTempMemory(storageSize);
    DObjBindEvalStorage(state, storage);

    return 0;
}

qboolean SV_DObjCreateSkelForBones(int32_t entityNum,
                                   const uint32_t *partBits)
{
    DObj *state;
    coduo_xanim_eval_storage_t *storage;
    int32_t storageSize;

    state = DObjGetForEntity(entityNum);
    if (DObjRefreshEvalStorageKey(state, dobj_skelCacheKey) != 0) {
        return DObjSkelAreBonesUpToDate(state, partBits);
    }

    storageSize = DObjEvalStorageSize(state);
    storage = Hunk_AllocateTempMemory(storageSize);
    DObjBindEvalStorage(state, storage);

    return 0;
}

qboolean SV_DObjUpdateServerTime(int32_t entityNum,
                                 float serverTime,
                                 qboolean notify)
{
    DObj *state;

    state = DObjGetForEntity(entityNum);
    if (state == NULL) {
        return 0;
    }

    return DObjUpdateServerInfo(state, serverTime, notify);
}

void SV_DObjInitServerTime(int32_t entityNum,
                           float serverTime)
{
    DObj *state;

    state = DObjGetForEntity(entityNum);
    if (state != NULL) {
        DObjInitServerTime(state, serverTime);
    }
}

void SV_DObjGetHierarchyBits(int32_t entityNum,
                             int32_t boneIndex,
                             uint32_t *partBits)
{
    DObjGetHierarchyBits(DObjGetForEntity(entityNum), boneIndex, partBits);
}

void SV_DObjCalcAnim(int32_t entityNum, const uint32_t *partBits)
{
    DObjCalcAnim(DObjGetForEntity(entityNum), partBits);
}

void SV_DObjCalcSkel(int32_t entityNum, const uint32_t *partBits)
{
    DObjCalcSkel(DObjGetForEntity(entityNum), partBits);
}

int32_t SV_DObjNumBones(int32_t entityNum)
{
    return DObjNumBones(DObjGetForEntity(entityNum));
}

int32_t SV_DObjGetBoneIndex(int32_t entityNum,
                                            const char *tagName)
{
    DObj *state;

    state = DObjGetForEntity(entityNum);
    if (state == NULL) {
        return -1;
    }

    return DObjGetBoneIndex(state, tagName);
}

DObjSkelMat *SV_DObjGetMatrixArray(int32_t entityNum)
{
    return DObjBasePoseForChild(DObjGetForEntity(entityNum), 0);
}

void SV_DObjDisplayAnim(int32_t entityNum)
{
    DObj *state;

    state = DObjGetForEntity(entityNum);
    if (state != NULL) {
        DObjDisplayAnim(state);
    }
}

DObjAnimMat *SV_DObjGetRotTransArray(int32_t entityNum)
{
    return DObjEvalStorageSeedOutput(DObjGetForEntity(entityNum));
}

qboolean SV_DObjSetRotTransIndex(int32_t entityNum,
                                 const uint32_t *partBits,
                                 int32_t boneIndex)
{
    return DObjMarkRotTransIndex(DObjGetForEntity(entityNum), partBits,
                                 boneIndex);
}

qboolean SV_DObjSetControlRotTransIndex(int32_t entityNum,
                                        const uint32_t *partBits,
                                        int32_t boneIndex)
{
    return DObjMarkControlRotTransIndex(DObjGetForEntity(entityNum),
                                        partBits, boneIndex);
}

void SV_DObjGetBounds(int32_t entityNum, vec3_t mins, vec3_t maxs)
{
    DObjGetBounds(DObjGetForEntity(entityNum), mins, maxs);
}

XAnimTree *SV_DObjGetTree(int32_t entityNum)
{
    return DObjGetTree(DObjGetForEntity(entityNum));
}
