/*****************************************************************************
    This code will test whether hash tables entries can be removed correctly.
 
    NOTE: Add code to test whether duplicates are handled correctly.
 *****************************************************************************/
#include <stdio.h>
#include <string.h>
#include "pslib.h"
#include "psTest.h"
#include "psHash.h"
#include "psMemory.h"
#define NUM_HASH_TABLE_BUCKETS 100
int imGlobal = 0;
int currentId = 0;

typedef struct
{
    char *name;
}
ID;
static void IdFree(ID *id);

// NOTE: This is my own little routine I used in debugging a memory
// leak.  I will take this out of this file later.
void printMemBlocks(char *myString)
{
    psMemBlock **memBlocks = NULL;
    psMemBlock *tmp = NULL;
    int numBlocks = 0;

    numBlocks = psMemCheckLeaks(currentId, &memBlocks, NULL);
    printf("******************** %s ********************\n", myString);
    printf("%d mem blocks\n", psMemCheckLeaks(currentId,NULL,stderr));
    printf("%d blocks\n", numBlocks);
    printf("*  ");
    if (memBlocks != NULL) {
        for (tmp = *memBlocks; tmp != NULL; tmp = tmp->nextBlock) {
            printf("%d ", (int) tmp->id);
        }
    }
    printf("*\n");
    printf("*************************************************\n");
    psFree(memBlocks);
}

static ID *IdAlloc(const char *name)
{
    ID *id = NULL;

    id = psAlloc(sizeof(ID));
    p_psMemSetDeallocator(id,(psFreeFcn)IdFree);

    id->name = psStringCopy(name);

    return id;
}

static void IdFree(ID *id)
{
    imGlobal++;
    psFree(id->name);
}

int main()
{
    psHash *myHashTable = NULL;
    int testStatus      = true;
    int i               = 0;
    int TotalKeys       = 0;
    bool retVal         = false;
    ID *id = NULL;
    ID *ids[4];
    char *myKeys[] = {"ENTRY00", "ENTRY01", "ENTRY02", "ENTRY03", NULL
                     };
    char *myData[] = {"IDA", "IDB", "IDC", "IDD", NULL
                     };
    int memLeaks        = 0;

    currentId = psMemGetId();

    printPositiveTestHeader(stdout,
                            "psHash functions",
                            "psHashRemove()");

    myHashTable = psHashAlloc(NUM_HASH_TABLE_BUCKETS);

    i = 0;
    while (myKeys[i] != NULL) {
        ids[i] = IdAlloc(myData[i]);
        psHashAdd(myHashTable, myKeys[i], ids[i]);
        i++;
    }
    TotalKeys = i - 1;

    i = TotalKeys;
    while (i >= 0) {

        id = psHashLookup(myHashTable, myKeys[i]);
        if (0 != strcmp(myData[i], id->name)) {
            fprintf(stderr, "%s: Hash table entry for key %s was %s (should be %s).\n",
                    __func__, myKeys[i], id->name, myData[i]);
        }
        i--;
    }

    i = 0;
    while (myKeys[i] != NULL) {
        // The psHashRemove() procedure removes the entry from the hash
        // table and deletes the data.
        retVal = psHashRemove(myHashTable, myKeys[i]);
        if (!retVal) {
            fprintf(stderr,"%s: Hash table entry not removed.\n",__func__);
        }
        id = psHashLookup(myHashTable, myKeys[i]);
        if (id != NULL) {
            fprintf(stderr, "%s: Hash table entry for key %s not removed.\n",
                    __func__, "IDA");
        }
        i++;
    }

    printFooter(stdout,
                "psHash functions",
                "psHashRemove()",
                testStatus);

    psFree(myHashTable);
    for(i=0; i<(TotalKeys+1); i++) {
        psFree(ids[i]);
    }
    memLeaks = psMemCheckLeaks(currentId,NULL,stdout);
    if (0 != memLeaks) {
        psAbort(__func__,"Memory Leaks! (%d leaks)", memLeaks);
    }
    psMemCheckCorruption(true);

    return (!testStatus);
}

