// ------------------------- VSPOOLS.C ------------------------------
// VSpace library
// Designed and written by Javier Ar‚valo Baeza.
// Object, material and texture pools.

#if 0
#include "vspools.h"
#include "vsfile.h"
#include "vspix.h"

extern VSNL_TNameTree VSPOOL_TexturePool  = NULL;
extern VSNL_TNameTree VSPOOL_MaterialPool = NULL;
extern VSNL_TNameTree VSPOOL_ObjectPool   = NULL;
extern VSNL_TNameTree VSPOOL_BitmapPool   = NULL;

VSMP_PPool VSPOOL_TextureMemory[VSPOOL_NPOWERS][VSPOOL_NPOWERS];

// -----------------------

extern bool VSPOOL_Init(void) {
//    int i, j;

    VSPOOL_TexturePool  = NULL;
    VSPOOL_MaterialPool = NULL;
    VSPOOL_ObjectPool   = NULL;
    VSPOOL_BitmapPool   = NULL;
    memset(VSPOOL_TextureMemory, 0, sizeof(VSPOOL_TextureMemory));
/*
    for (i = VSPOOL_MINPOWER; i <= VSPOOL_MAXPOWER; i++)
        for (j = VSPOOL_MINPOWER; j <= VSPOOL_MAXPOWER; j++) {
            VSMP_PPool mp;

            mp = VSMP_Init(NULL, VSPOOL_TextureMemory[i-VSPOOL_MINPOWER][j-VSPOOL_MINPOWER],
                           VSPOOL_MAXSIZE >> j, 1 << j, 1 << i);
            if (mp == NULL) {
                VSPOOL_End();
                return FALSE;
            }
            VSPOOL_TextureMemory[i-VSPOOL_MINPOWER][j-VSPOOL_MINPOWER] = mp;
        }
*/
    return TRUE;
}

extern void VSPOOL_End(void) {
    int i, j;

    for (i = VSPOOL_MINPOWER; i <= VSPOOL_MAXPOWER; i++)
        for (j = VSPOOL_MINPOWER; j <= VSPOOL_MAXPOWER; j++)
            VSMP_End(VSPOOL_TextureMemory[i-VSPOOL_MINPOWER][j-VSPOOL_MINPOWER]);
    memset(VSPOOL_TextureMemory, 0, sizeof(VSPOOL_TextureMemory));

    VSNL_End(&VSPOOL_TexturePool);
    VSNL_End(&VSPOOL_MaterialPool);
    VSNL_End(&VSPOOL_ObjectPool);
}

extern byte *VSPOOL_NewTexture(int w, int h, void **addr) {
    int i, j;

    if (w < VSPOOL_MINSIZE || w > VSPOOL_MAXSIZE
     || h < VSPOOL_MINSIZE || h > VSPOOL_MAXSIZE
     || addr == NULL)
        return NULL;

    for (i = VSPOOL_MINPOWER; i <= VSPOOL_MAXPOWER; i++) {
        if (h != (1 << i))
            continue;
        for (j = VSPOOL_MINPOWER; j <= VSPOOL_MAXPOWER; j++) {
            if (w != (1 << j))
                continue;
//            VSLOG("Found pool at i = %d, j = %d\n", i, j);
            if (VSMP_Alloc(&VSPOOL_TextureMemory[i-VSPOOL_MINPOWER][j-VSPOOL_MINPOWER],
                           addr, VSPOOL_MAXSIZE >> j, 1 << j, 1 << i, VSMPA_CREATE)
                     == NULL)
                return NULL;
//printf("Texture allocated at 0x%08X\n", *addr);
            return *addr;
        }
    }
    return NULL;
}


extern void VSPOOL_FreeTexture(void *addr) {
    int i, j;

    for (i = VSPOOL_MINPOWER; i <= VSPOOL_MAXPOWER; i++)
        for (j = VSPOOL_MINPOWER; j <= VSPOOL_MAXPOWER; j++)
            if (VSMP_Free(VSPOOL_TextureMemory[i-VSPOOL_MINPOWER][j-VSPOOL_MINPOWER],
                          addr))
                return;
}

extern VSPLY_PTexture VSPOOL_LoadTexture(const char *fname) {
    VSNL_PName pn = NULL;
    FILE *f = NULL;
    char buf[300];
    VSPOOL_TTextureHeader h;
    int i;
    VSPLY_PTexture tex = NULL;

//    VSLOG("LoadTexture %s\n", fname);
    pn = VSNL_AddName(&VSPOOL_TexturePool, fname);
    if (pn == NULL)
        goto error;
//    VSLOG("Name %s added\n", fname);
    if (pn->data != NULL)
        return (VSPLY_PTexture)pn->data;
    tex = NEW(sizeof(*tex));
    if (tex == NULL)
        goto error;
    memset(tex, 0, sizeof(*tex));
    pn->data = tex;
    sprintf(buf, "TEXTURES\\%s.TEX", fname);
    f = VSF_Open(buf);
    if (f == NULL)
        goto error;
    memset(&h, 0, sizeof(h));
    fread(&h, sizeof(h), 1, f);
    if (h.magic != VSPTM_MAGIC)
        goto error;
    if (VSPOOL_NewTexture(h.w, h.h, &tex->pix) == NULL)
        goto error;
    VSLOG("Reading texture pix %s (%d,%d)\n", buf, h.w, h.h);
    strncpy(tex->name, fname, sizeof(tex->name));
    tex->w = h.w;
    tex->h = h.h;
    tex->flags = h.flags;
    tex->mask = ((h.h - 1) << 8) | (h.w - 1);
    for (i = 0; i < h.h; i++)
        fread(tex->pix + i*VSPOOL_MAXSIZE, h.w, 1, f);
    VSF_Close(f);
    return tex;

  error:
    VSLOG("Error reading texture %s\n", fname);
    if (f != NULL)
        VSF_Close(f);
    if (tex != NULL) {
        if (tex->pix != NULL)
            VSPOOL_FreeTexture((void*)tex->pix);
        DISPOSE(tex);
    }
    if (pn != NULL) {
        VSNL_DelName(&VSPOOL_TexturePool, fname);
    }
    return NULL;
}

extern VSO_PObj VSPOOL_LoadObject(const char *fname) {
    VSNL_PName pn = NULL;
    char buf[300];
    VSO_PObj obj;
    int i;

//    VSLOG("Loading mesh %s\n", fname);

    pn = VSNL_AddName(&VSPOOL_ObjectPool, fname);
    if (pn == NULL)
        goto error;
    if (pn->data != NULL) {
//        VSLOG("Name already there\n", fname);
        return (VSO_PObj)pn->data;
    }
    obj = NEW(sizeof(*obj));
    if (obj == NULL)
        goto error;
    memset(obj, 0, sizeof(*obj));
    pn->data = obj;
    sprintf(buf, "VSO\\%s.VSO", fname);
    VSLOG("Reading mesh %s\n", buf);
    if (VSO_ReadVSO(obj, buf) <= 0)
        goto error;

        // Process mesh hierarchy.
    for (i = 0; i < obj->nmesh; i++) {
        VSO_GenerateNormals(obj->mesh + i);
    }
    VSO_CopyRotations(obj->mesh);
    VSO_RotateHierarchy(obj->mesh);
    obj->radius = VSO_CalcRadius(obj->mesh);
    VSLOG("Mesh %s has radius of %f\n", fname, obj->radius);

    return obj;

  error:
    VSLOG("Error reading object %s\n", fname);
    if (obj != NULL) {
        DISPOSE(obj);
    }
    if (pn != NULL) {
        VSNL_DelName(&VSPOOL_ObjectPool, fname);
    }
    return NULL;
}

extern VSB_PBitmap VSPOOL_LoadBitmap(const char *fname) {
    VSNL_PName pn = NULL;
    char buf[300];
    VSB_PBitmap bm;
    int i;

    pn = VSNL_AddName(&VSPOOL_BitmapPool, fname);
    if (pn == NULL)
        goto error;
    if (pn->data != NULL)
        return (VSB_PBitmap)pn->data;
    bm = NEW(sizeof(*bm));
    if (bm == NULL)
        goto error;
    memset(bm, 0, sizeof(*bm));
    pn->data = bm;
    sprintf(buf, "BITMAPS\\%s.BIT", fname);
    if (!VSPIX_Load(buf, NULL, NULL, &bm->w, &bm->h))
        goto error;
    bm->pix = NEW(bm->w*bm->h);
    if (bm->pix == NULL)
        goto error;
    if (!VSPIX_Load(buf, bm->pix, NULL, NULL, NULL))
        goto error;

    return bm;

  error:
    VSLOG("Error reading bitmap %s\n", fname);
    if (bm != NULL) {
        if (bm->pix != NULL)
            DISPOSE(bm->pix);
        DISPOSE(bm);
    }
    if (pn != NULL) {
        VSNL_DelName(&VSPOOL_BitmapPool, fname);
    }
    return NULL;
}


// ------------------------- VSPOOLS.C ------------------------------
#endif