// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

#include "DFPlatform.h"
#include "DFHashTable.h"
#include "DFCommon.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct DFHashEntry DFHashEntry;

struct DFHashEntry {
    DFHashEntry *next;
    void *value;
    DFHashCode hash;
    char key[0];
};

struct DFHashTable {
    size_t retainCount;
    size_t binsCount;
    DFHashEntry **bins;
    DFCopyFunction copy;
    DFFreeFunction free;
};

DFHashTable *DFHashTableNew(DFCopyFunction copy, DFFreeFunction free)
{
    return DFHashTableNew2(copy,free,53);
}

DFHashTable *DFHashTableNew2(DFCopyFunction copy, DFFreeFunction free, int binsCount)
{
    DFHashTable *table = (DFHashTable *)xcalloc(1,sizeof(DFHashTable));
    table->retainCount = 1;
    table->binsCount = binsCount;
    table->bins = (DFHashEntry **)xcalloc(1,table->binsCount*sizeof(DFHashEntry *));
    table->copy = copy;
    table->free = free;
    return table;
}

DFHashTable *DFHashTableRetain(DFHashTable *table)
{
    if (table != NULL)
        table->retainCount++;
    return table;
}

void DFHashTableRelease(DFHashTable *table)
{
    if (table == NULL)
        return;

    table->retainCount--;
    if (table->retainCount > 0)
        return;

    for (DFHashCode bin = 0; bin < table->binsCount; bin++) {
        DFHashEntry *entry = table->bins[bin];
        while (entry != NULL) {
            DFHashEntry *next = entry->next;
            if (table->free != NULL)
                table->free(entry->value);
            free(entry);
            entry = next;
        }
    }
    free(table->bins);
    free(table);
}

DFHashTable *DFHashTableCopy(DFHashTable *src)
{
    DFHashTable *result = DFHashTableNew(src->copy,src->free);
    for (DFHashCode bin = 0; bin < src->binsCount; bin++) {
        for (DFHashEntry *entry = src->bins[bin]; entry != NULL; entry = entry->next)
            DFHashTableAdd(result,entry->key,entry->value);
    }
    return result;
}

int DFHashTableCount(DFHashTable *table)
{
    int count = 0;
    for (DFHashCode bin = 0; bin < table->binsCount; bin++) {
        for (DFHashEntry *entry = table->bins[bin]; entry != NULL; entry = entry->next)
            count++;
    }
    return count;
}

const char **DFHashTableCopyKeys(DFHashTable *table)
{
    // This function returns a block of memory divided into two parts. The first part contains an array of string
    // pointers (terminated by a NULL pointer), while the second part contains the actual string data. All pointers
    // in the first part of the memory block refer to locations in the second part of the memory block.
    //
    // By placing all pointers and values in a single block of memory, the caller has to make only one call to
    // free after using this function; they do not (and cannot) free the individual string pointers. Thus a typical
    // usage of the function is as follows:
    //
    // const char **keys = DFHashTableCopyKeys(table);
    // for (int i = 0; keys[i]; i++) {
    //     ... do stuff with the current key ...
    // }
    // free(keys);
    //
    // Because the returned array is a const char ** (i.e. an array pointing to char * values that cannot be changed),
    // the compiler will issue a warning if an attempt is made to free individual keys. Ignoring this warning will
    // result in a crash when calling free.

    int count = DFHashTableCount(table);
    size_t numBytes = (count+1)*sizeof(char *);
    for (DFHashCode bin = 0; bin < table->binsCount; bin++) {
        for (DFHashEntry *entry = table->bins[bin]; entry != NULL; entry = entry->next)
            numBytes += strlen(entry->key)+1;
    }

    void *mem = xmalloc(numBytes);
    char **pointers = mem;
    char *storage = (char *)mem + (count+1)*sizeof(char *);

    size_t index = 0;
    for (DFHashCode bin = 0; bin < table->binsCount; bin++) {
        for (DFHashEntry *entry = table->bins[bin]; entry != NULL; entry = entry->next) {
            pointers[index++] = storage;
            size_t len = strlen(entry->key);
            memcpy(storage,entry->key,len);
            storage += len;
            *storage = '\0';
            storage += 1;
        }
    }
    assert(index == count);
    assert(storage == (char *)mem + numBytes);
    pointers[index++] = NULL;
    return (const char **)pointers;
}

static DFHashEntry **DFHashTableLookupEntry(DFHashTable *table, const char *key, DFHashCode hash)
{
    DFHashCode bin = hash % table->binsCount;
    for (DFHashEntry **ptr = &table->bins[bin]; *ptr != NULL; ptr = &(*ptr)->next) {
        DFHashEntry *entry = *ptr;
        if (entry->hash != hash)
            continue;
        if (strcmp(entry->key,key))
            continue;
        return ptr;
    }
    return NULL;
}

static DFHashCode DFHashString(const char *str)
{
    DFHashCode hash = 0;
    DFHashBegin(hash);
    while (*str != '\0') {
        DFHashUpdate(hash,*str);
        str++;
    }
    DFHashEnd(hash);
    return hash;
}

void *DFHashTableLookup(DFHashTable *table, const char *key)
{
    DFHashCode hash = DFHashString(key);
    DFHashEntry **ptr = DFHashTableLookupEntry(table,key,hash);
    if (ptr != NULL)
        return (*ptr)->value;
    else
        return NULL;
}

void DFHashTableAdd(DFHashTable *table, const char *key, const void *constValue)
{
    void *value = (void *)constValue;
    if (table->copy != NULL) {
        value = table->copy(value);
    }

    DFHashCode hash = DFHashString(key);
    DFHashEntry **ptr = DFHashTableLookupEntry(table,key,hash);
    if (ptr != NULL) {
        DFHashEntry *entry = *ptr;
        void *oldValue = entry->value;
        entry->value = value;
        if (table->free != NULL)
            table->free(oldValue);
    }
    else {
        size_t len = strlen(key);
        DFHashEntry *entry = (DFHashEntry *)xmalloc(sizeof(DFHashEntry)+len*sizeof(char)+1);
        entry->value = value;
        entry->hash = hash;
        memcpy(&entry->key[0],key,len);
        entry->key[len] = '\0';

        DFHashCode bin = hash % table->binsCount;
        entry->next = table->bins[bin];
        table->bins[bin] = entry;
    }
}

void DFHashTableRemove(DFHashTable *table, const char *key)
{
    DFHashCode hash = DFHashString(key);
    DFHashEntry **ptr = DFHashTableLookupEntry(table,key,hash);
    if (ptr != NULL) {
        DFHashEntry *entry = *ptr;
        *ptr = entry->next;
        if (table->free)
            table->free(entry->value);
        free(entry);
    }
}

void *DFHashTableLookupInt(DFHashTable *table, int key)
{
    char strkey[40];
    snprintf(strkey,40,"%d",key);
    return DFHashTableLookup(table,strkey);
}

void DFHashTableAddInt(DFHashTable *table, int key, void *value)
{
    char strkey[40];
    snprintf(strkey,40,"%d",key);
    DFHashTableAdd(table,strkey,value);
}

void DFHashTableRemoveInt(DFHashTable *table, int key)
{
    char strkey[40];
    snprintf(strkey,40,"%d",key);
    DFHashTableRemove(table,strkey);
}
