/*
 * 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 <axis2_desc.h>
#include <axutil_property.h>
#include <axis2_policy_include.h>
#include <axis2_msg.h>

struct axis2_desc
{

    /** parameter container */
    axutil_param_container_t *param_container;

    /** children of this description */
    axutil_hash_t *children;

    axis2_desc_t *parent;

    axis2_policy_include_t *policy_include;
};

AXIS2_EXTERN axis2_desc_t *AXIS2_CALL
axis2_desc_create(
    const axutil_env_t * env)
{
    axis2_desc_t *desc = NULL;

    desc = (axis2_desc_t *)AXIS2_MALLOC(env->allocator, sizeof(axis2_desc_t));

    if(!desc)
    {
        AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
        return NULL;
    }

    desc->param_container = NULL;
    desc->children = NULL;
    desc->parent = NULL;
    desc->policy_include = NULL;

    desc->param_container = (axutil_param_container_t *)axutil_param_container_create(env);
    if(!(desc->param_container))
    {
        axis2_desc_free(desc, env);
        return NULL;
    }

    desc->children = axutil_hash_make(env);
    if(!(desc->children))
    {
        axis2_desc_free(desc, env);
        return NULL;
    }

    desc->policy_include = axis2_policy_include_create_with_desc(env, desc);

    return desc;
}

AXIS2_EXTERN void AXIS2_CALL
axis2_desc_free(
    axis2_desc_t * desc,
    const axutil_env_t * env)
{
    if(desc->children)
    {
        axutil_hash_index_t *hi = NULL;
        void *val = NULL;

        for(hi = axutil_hash_first(desc->children, env); hi; hi = axutil_hash_next(env, hi))
        {
            axutil_hash_this(hi, NULL, NULL, &val);

            if(val)
            {
                axis2_msg_free((axis2_msg_t *)val, env);
            }
        }

        axutil_hash_free(desc->children, env);
    }

    if(desc->param_container)
    {
        axutil_param_container_free(desc->param_container, env);
    }

    if(desc->policy_include)
    {
        axis2_policy_include_free(desc->policy_include, env);
    }

    if(desc)
    {
        AXIS2_FREE(env->allocator, desc);
    }

    return;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
axis2_desc_add_param(
    axis2_desc_t * desc,
    const axutil_env_t * env,
    axutil_param_t * param)
{
    AXIS2_PARAM_CHECK(env->error, param, AXIS2_FALSE);

    return axutil_param_container_add_param(desc->param_container, env, param);
}

AXIS2_EXTERN axutil_param_t *AXIS2_CALL
axis2_desc_get_param(
    const axis2_desc_t * desc,
    const axutil_env_t * env,
    const axis2_char_t * param_name)
{
    AXIS2_PARAM_CHECK(env->error, param_name, NULL);
    return axutil_param_container_get_param(desc->param_container, env, param_name);
}

AXIS2_EXTERN axutil_array_list_t *AXIS2_CALL
axis2_desc_get_all_params(
    const axis2_desc_t * desc,
    const axutil_env_t * env)
{
    AXIS2_PARAM_CHECK(env->error, desc->param_container, AXIS2_FALSE);

    return axutil_param_container_get_params(desc->param_container, env);
}

AXIS2_EXTERN axis2_bool_t AXIS2_CALL
axis2_desc_is_param_locked(
    const axis2_desc_t * desc,
    const axutil_env_t * env,
    const axis2_char_t * param_name)
{
    axutil_param_t *param_l = NULL;

    AXIS2_PARAM_CHECK(env->error, param_name, AXIS2_FALSE);

    param_l = axis2_desc_get_param(desc, env, param_name);

    return (param_l && axutil_param_is_locked(param_l, env));
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
axis2_desc_add_child(
    const axis2_desc_t * desc,
    const axutil_env_t * env,
    const axis2_char_t * key,
    const axis2_msg_t *child)
{
    if(desc->children)
    {
        axis2_msg_t* msg = (axis2_msg_t *)axutil_hash_get(desc->children, key,
            AXIS2_HASH_KEY_STRING);
        if(msg != NULL)
        {
            axis2_msg_free(msg, env);
            msg = NULL;
        }
        axutil_hash_set(desc->children, key, AXIS2_HASH_KEY_STRING, (void *)child);
        return AXIS2_SUCCESS;
    }
    return AXIS2_FAILURE;
}

AXIS2_EXTERN axutil_hash_t *AXIS2_CALL
axis2_desc_get_all_children(
    const axis2_desc_t * desc,
    const axutil_env_t * env)
{
    return desc->children;
}

AXIS2_EXTERN void *AXIS2_CALL
axis2_desc_get_child(
    const axis2_desc_t * desc,
    const axutil_env_t * env,
    const axis2_char_t * key)
{
    return axutil_hash_get(desc->children, key, AXIS2_HASH_KEY_STRING);
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
axis2_desc_remove_child(
    const axis2_desc_t * desc,
    const axutil_env_t * env,
    const axis2_char_t * key)
{
    if(desc->children)
    {
        axutil_hash_set(desc->children, key, AXIS2_HASH_KEY_STRING, NULL);
        return AXIS2_SUCCESS;
    }
    return AXIS2_FAILURE;
}

AXIS2_EXTERN axis2_desc_t *AXIS2_CALL
axis2_desc_get_parent(
    const axis2_desc_t * desc,
    const axutil_env_t * env)
{
    return desc->parent;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
axis2_desc_set_parent(
    axis2_desc_t * desc,
    const axutil_env_t * env,
    axis2_desc_t * parent)
{
    desc->parent = parent;
    return AXIS2_SUCCESS;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
axis2_desc_set_policy_include(
    axis2_desc_t * desc,
    const axutil_env_t * env,
    axis2_policy_include_t * policy_include)
{
    if(desc->policy_include)
    {
        axis2_policy_include_free(desc->policy_include, env);
        desc->policy_include = NULL;
    }

    desc->policy_include = policy_include;
    return AXIS2_SUCCESS;
}

AXIS2_EXTERN axis2_policy_include_t *AXIS2_CALL
axis2_desc_get_policy_include(
    axis2_desc_t * desc,
    const axutil_env_t * env)
{
    if(!desc->policy_include)
    {
        /*desc->policy_include = axis2_policy_include_create(env); */
        desc->policy_include = axis2_policy_include_create_with_desc(env, desc);
    }
    return desc->policy_include;
}

