/*
 * prime.c
 *
 * Copyright (C) 2015 James Booth <boothj5@gmail.com>
 *
 * This file is part of Stabber.
 *
 * Stabber is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Stabber is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Stabber.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include <stdlib.h>
#include <stdio.h>
#include <glib.h>

#include <string.h>
#include <fnmatch.h>

#include "server/stanza.h"
#include "server/stanzas.h"
#include "server/log.h"

static char *required_passwd = NULL;
static GHashTable *idstubs = NULL;
static GHashTable *querystubs = NULL;
static GHashTable *xmlnsstubs = NULL;

void
prime_init(void)
{
    if (idstubs) {
        return;
    }
    required_passwd = strdup("password");
    idstubs = g_hash_table_new_full(g_str_hash, g_str_equal, free, free);
    querystubs = g_hash_table_new_full(g_str_hash, g_str_equal, free, (GDestroyNotify)stanza_free);
    xmlnsstubs = g_hash_table_new_full(g_str_hash, g_str_equal, free, (GDestroyNotify)stanza_free);
}

void
prime_free_all(void)
{
    free(required_passwd);
    required_passwd = NULL;

    if (idstubs) {
        g_hash_table_destroy(idstubs);
    }
    idstubs = NULL;

    if (querystubs) {
        g_hash_table_destroy(querystubs);
    }
    querystubs = NULL;

    if (xmlnsstubs) {
        g_hash_table_destroy(xmlnsstubs);
    }
    xmlnsstubs = NULL;
}

void
prime_required_passwd(char *password)
{
    free(required_passwd);
    required_passwd = strdup(password);
}

char*
prime_get_passwd(void)
{
    return required_passwd;
}

void
prime_for_id(const char *id, char *stream)
{
    if (!idstubs) {
        prime_init();
    }

    g_hash_table_insert(idstubs, strdup(id), strdup(stream));
}

char*
prime_get_for_id(const char *id)
{
    char *exact_match = g_hash_table_lookup(idstubs, id);
    if (exact_match) {
        return exact_match;
    }

    // Fallback to wildcard matching
    GList *keys = g_hash_table_get_keys(idstubs);
    GList *curr = keys;
    char *match = NULL;

    while (curr) {
        char *key = (char *)curr->data;
        if (fnmatch(key, id, 0) == 0) {
            match = g_hash_table_lookup(idstubs, key);
            break;
        }
        curr = g_list_next(curr);
    }

    g_list_free(keys);
    return match;
}

void
prime_for_query(const char *query, char *stream)
{
    if (!querystubs) {
        prime_init();
    }

    XMPPStanza *stanza = stanza_parse(stream);
    g_hash_table_insert(querystubs, strdup(query), stanza);
}

XMPPStanza*
prime_get_for_query(const char *query)
{
    return g_hash_table_lookup(querystubs, query);
}

void
prime_for_xmlns(const char *xmlns, char *stream)
{
    if (!xmlnsstubs) {
        prime_init();
    }

    XMPPStanza *stanza = stanza_parse(stream);
    g_hash_table_insert(xmlnsstubs, strdup(xmlns), stanza);
}

XMPPStanza*
prime_get_for_xmlns(const char *xmlns)
{
    return g_hash_table_lookup(xmlnsstubs, xmlns);
}
