/*
 * 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 "config.h"
#include "guac_list.h"
#include "proc.h"
#include "proc-map.h"
#include "user.h"

#include <guacamole/client.h>

#include <stdlib.h>
#include <string.h>

/**
 * Returns a hash code based on the given connection ID.
 *
 * @param str
 *     The string containing the connection ID.
 *
 * @return
 *     A reasonably well-distributed hash code for the given string.
 */
static unsigned int __guacd_client_hash(const char* str) {

    unsigned int hash_value = 0;
    int c;

    /* Apply each character in string to the hash code */
    while ((c = *(str++)))
        hash_value = hash_value * 65599 + c;

    return hash_value;

}

/**
 * Locates the bucket corresponding to the hash code indicated by the given id,
 * where the hash code is dictated by __guacd_client_hash().  Each bucket is an
 * instance of guac_common_list.
 *
 * @param map
 *     The map to retrieve the hash bucket from.
 *
 * @param id
 *     The ID whose hash code determines the bucket being retrieved.
 *
 * @return
 *     The bucket corresponding to the hash code for the given ID, represented
 *     by a guac_common_list.
 */
static guac_common_list* __guacd_proc_find_bucket(guacd_proc_map* map,
        const char* id) {

    const int index = __guacd_client_hash(id) % GUACD_PROC_MAP_BUCKETS;
    return map->__buckets[index];

}

/**
 * Given a bucket of guacd_proc instances, returns the guacd_proc having the
 * guac_client with the given ID, or NULL if no such client is stored.
 *
 * @param bucket
 *     The bucket of guacd_proc instances to search, represented as a
 *     guac_common_list.
 *
 * @param id
 *     The ID of the guac_client whose corresponding guacd_proc instance should
 *     be located within the bucket.
 *
 * @return
 *     The guac_common_list_element containing the guacd_proc instance
 *     corresponding to the guac_client having the given ID, or NULL of no such
 *     element exists.
 */
static guac_common_list_element* __guacd_proc_find(guac_common_list* bucket,
        const char* id) {

    guac_common_list_element* current = bucket->head;

    /* Search for matching element within bucket */
    while (current != NULL) {

        /* Check connection ID */
        guacd_proc* proc = (guacd_proc*) current->data;
        if (strcmp(proc->client->connection_id, id) == 0)
            break;

        current = current->next;
    }

    return current;

}

guacd_proc_map* guacd_proc_map_alloc() {

    guacd_proc_map* map = malloc(sizeof(guacd_proc_map));
    guac_common_list** current;

    int i;

    /* Init all buckets */
    current = map->__buckets;

    for (i=0; i<GUACD_PROC_MAP_BUCKETS; i++) {
        *current = guac_common_list_alloc();
        current++;
    }

    return map;

}

int guacd_proc_map_add(guacd_proc_map* map, guacd_proc* proc) {

    const char* identifier = proc->client->connection_id;
    guac_common_list* bucket = __guacd_proc_find_bucket(map, identifier);
    guac_common_list_element* found;

    /* Retrieve corresponding element, if any */
    guac_common_list_lock(bucket);
    found = __guacd_proc_find(bucket, identifier);

    /* If no such element, we can add the new client successfully */
    if (found == NULL) {
        guac_common_list_add(bucket, proc);
        guac_common_list_unlock(bucket);
        return 0;
    }

    /* Otherwise, fail - already exists */
    guac_common_list_unlock(bucket);
    return 1;

}

guacd_proc* guacd_proc_map_retrieve(guacd_proc_map* map, const char* id) {

    guacd_proc* proc;

    guac_common_list* bucket = __guacd_proc_find_bucket(map, id);
    guac_common_list_element* found;

    /* Retrieve corresponding element, if any */
    guac_common_list_lock(bucket);
    found = __guacd_proc_find(bucket, id);

    /* If no such element, fail */
    if (found == NULL) {
        guac_common_list_unlock(bucket);
        return NULL;
    }

    proc = (guacd_proc*) found->data;

    guac_common_list_unlock(bucket);
    return proc;

}

guacd_proc* guacd_proc_map_remove(guacd_proc_map* map, const char* id) {

    guacd_proc* proc;

    guac_common_list* bucket = __guacd_proc_find_bucket(map, id);
    guac_common_list_element* found;

    /* Retrieve corresponding element, if any */
    guac_common_list_lock(bucket);
    found = __guacd_proc_find(bucket, id);

    /* If no such element, fail */
    if (found == NULL) {
        guac_common_list_unlock(bucket);
        return NULL;
    }

    proc = (guacd_proc*) found->data;
    guac_common_list_remove(bucket, found);

    guac_common_list_unlock(bucket);
    return proc;

}

