/* 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 "apr_pools.h"
#include "apr_hash.h"
#include "apr_tables.h"
#include "apr_strings.h"

#include "ap_provider.h"

static apr_hash_t *global_providers = NULL;
static apr_hash_t *global_providers_names = NULL;


static apr_status_t cleanup_global_providers(void *ctx)
{
    global_providers = NULL;
    global_providers_names = NULL;
    return APR_SUCCESS;
}

AP_DECLARE(apr_status_t) ap_register_provider(apr_pool_t *pool,
                                              const char *provider_group,
                                              const char *provider_name,
                                              const char *provider_version,
                                              const void *provider)
{
    apr_hash_t *provider_group_hash, *provider_version_hash;

    if (global_providers == NULL) {
        global_providers = apr_hash_make(pool);
        global_providers_names = apr_hash_make(pool);
        apr_pool_cleanup_register(pool, NULL, cleanup_global_providers,
                                  apr_pool_cleanup_null);
    }

    /* First, deal with storing the provider away */
    provider_group_hash = apr_hash_get(global_providers, provider_group,
                                       APR_HASH_KEY_STRING);

    if (!provider_group_hash) {
        provider_group_hash = apr_hash_make(pool);
        apr_hash_set(global_providers, provider_group, APR_HASH_KEY_STRING,
                     provider_group_hash);
    }

    provider_version_hash = apr_hash_get(provider_group_hash, provider_name,
                                         APR_HASH_KEY_STRING);

    if (!provider_version_hash) {
        provider_version_hash = apr_hash_make(pool);
        apr_hash_set(provider_group_hash, provider_name, APR_HASH_KEY_STRING,
                     provider_version_hash);
    }

    /* just set it. no biggy if it was there before. */
    apr_hash_set(provider_version_hash, provider_version, APR_HASH_KEY_STRING,
                 provider);

    /* Now, tuck away the provider names in an easy-to-get format */
    provider_group_hash = apr_hash_get(global_providers_names, provider_group,
                                       APR_HASH_KEY_STRING);

    if (!provider_group_hash) {
        provider_group_hash = apr_hash_make(pool);
        apr_hash_set(global_providers_names, provider_group, APR_HASH_KEY_STRING,
                     provider_group_hash);
    }

    provider_version_hash = apr_hash_get(provider_group_hash, provider_version,
                                         APR_HASH_KEY_STRING);

    if (!provider_version_hash) {
        provider_version_hash = apr_hash_make(pool);
        apr_hash_set(provider_group_hash, provider_version, APR_HASH_KEY_STRING,
                     provider_version_hash);
    }

    /* just set it. no biggy if it was there before. */
    apr_hash_set(provider_version_hash, provider_name, APR_HASH_KEY_STRING,
                 provider_name);

    return APR_SUCCESS;
}

AP_DECLARE(void *) ap_lookup_provider(const char *provider_group,
                                      const char *provider_name,
                                      const char *provider_version)
{
    apr_hash_t *provider_group_hash, *provider_name_hash;

    if (global_providers == NULL) {
        return NULL;
    }

    provider_group_hash = apr_hash_get(global_providers, provider_group,
                                       APR_HASH_KEY_STRING);

    if (provider_group_hash == NULL) {
        return NULL;
    }

    provider_name_hash = apr_hash_get(provider_group_hash, provider_name,
                                      APR_HASH_KEY_STRING);

    if (provider_name_hash == NULL) {
        return NULL;
    }

    return apr_hash_get(provider_name_hash, provider_version,
                        APR_HASH_KEY_STRING);
}

AP_DECLARE(apr_array_header_t *) ap_list_provider_names(apr_pool_t *pool,
                                              const char *provider_group,
                                              const char *provider_version)
{
    apr_array_header_t *ret = NULL;
    ap_list_provider_names_t *entry;
    apr_hash_t *provider_group_hash, *h;
    apr_hash_index_t *hi;
    char *val;

    if (global_providers_names == NULL) {
        goto out;
    }

    provider_group_hash = apr_hash_get(global_providers_names, provider_group,
                                       APR_HASH_KEY_STRING);

    if (provider_group_hash == NULL) {
        goto out;
    }

    h = apr_hash_get(provider_group_hash, provider_version, APR_HASH_KEY_STRING);

    if (h == NULL) {
        goto out;
    }

    ret = apr_array_make(pool, apr_hash_count(h), sizeof(ap_list_provider_names_t));
    for (hi = apr_hash_first(pool, h); hi; hi = apr_hash_next(hi)) {
        apr_hash_this(hi, NULL, NULL, (void *)&val);
        entry = apr_array_push(ret);
        entry->provider_name = apr_pstrdup(pool, val);
    }
    
out:
    if (ret == NULL) {
        ret = apr_array_make(pool, 1, sizeof(ap_list_provider_names_t));
    }
    return ret;
}

AP_DECLARE(apr_array_header_t *) ap_list_provider_groups(apr_pool_t *pool)
{
    apr_array_header_t *ret = apr_array_make(pool, 10, sizeof(ap_list_provider_groups_t));
    ap_list_provider_groups_t *entry;
    apr_hash_t *provider_group_hash;
    apr_hash_index_t *groups_hi, *vers_hi;
    char *group, *version;

    if (global_providers_names == NULL)
        return ret;

    for (groups_hi = apr_hash_first(pool, global_providers_names);
         groups_hi;
         groups_hi = apr_hash_next(groups_hi))
    {
        apr_hash_this(groups_hi, (void *)&group, NULL, (void *)&provider_group_hash);
        if (provider_group_hash == NULL)
            continue;
        for (vers_hi = apr_hash_first(pool, provider_group_hash);
             vers_hi;
             vers_hi = apr_hash_next(vers_hi))
        {
            apr_hash_this(vers_hi, (void *)&version, NULL, NULL);

            entry = apr_array_push(ret);
            entry->provider_group = group;
            entry->provider_version = version;
        }
    }
    return ret;
}
