/*
 * 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 <neethi_all.h>

struct neethi_all_t
{
    axutil_array_list_t *policy_components;
};

AXIS2_EXTERN neethi_all_t *AXIS2_CALL
neethi_all_create(
    const axutil_env_t *env)
{
    neethi_all_t *neethi_all = NULL;

    AXIS2_ENV_CHECK(env, NULL);

    neethi_all = (neethi_all_t *) AXIS2_MALLOC(env->allocator,
                                               sizeof(neethi_all_t));

    if (neethi_all == NULL)
    {
        AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
        AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Out of memory");
        return NULL;
    }
    neethi_all->policy_components = NULL;

    neethi_all->policy_components = axutil_array_list_create(env, 0);
    if (!(neethi_all->policy_components))
    {
        neethi_all_free(neethi_all, env);
        AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
        AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Out of memory");
        return NULL;
    }
    return neethi_all;
}

AXIS2_EXTERN void AXIS2_CALL
neethi_all_free(
    neethi_all_t *neethi_all,
    const axutil_env_t *env)
{
    if (neethi_all)
    {
        if (neethi_all->policy_components)
        {
            int i = 0;
            int size = 0;

            size = axutil_array_list_size(neethi_all->policy_components, env);

            for (i = 0; i < size; i++)
            {
                neethi_operator_t *operator = NULL;
                operator =(neethi_operator_t *)
                    axutil_array_list_get(neethi_all->policy_components, env,
                                          i);
                if (operator)
                {
                    neethi_operator_free(operator, env);
                    operator = NULL;    
                }
                operator = NULL;
            }
            axutil_array_list_free(neethi_all->policy_components, env);
            neethi_all->policy_components = NULL;
        }
        AXIS2_FREE(env->allocator, neethi_all);
        neethi_all = NULL;
    }
    return;
}

/* Implementations */

AXIS2_EXTERN axutil_array_list_t *AXIS2_CALL
neethi_all_get_policy_components(
    neethi_all_t *neethi_all,
    const axutil_env_t *env)
{
    return neethi_all->policy_components;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
neethi_all_add_policy_components(
    neethi_all_t *all,
    axutil_array_list_t *arraylist,
    const axutil_env_t *env)
{

    int size = axutil_array_list_size(arraylist, env);
    int i = 0;

    if (axutil_array_list_ensure_capacity(all->policy_components, env, size + 1)
        != AXIS2_SUCCESS)
        return AXIS2_FAILURE;

    for (i = 0; i < size; i++)
    {
        void *value = NULL;
        value = axutil_array_list_get(arraylist, env, i);
        neethi_operator_increment_ref((neethi_operator_t *) value, env);
        axutil_array_list_add(all->policy_components, env, value);
    }
    return AXIS2_SUCCESS;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
neethi_all_add_operator(
    neethi_all_t *neethi_all,
    const axutil_env_t *env,
    neethi_operator_t *operator)
{
    neethi_operator_increment_ref(operator, env);
    axutil_array_list_add(neethi_all->policy_components, env, operator);
    return AXIS2_SUCCESS;
}

AXIS2_EXTERN axis2_bool_t AXIS2_CALL
neethi_all_is_empty(
    neethi_all_t *all,
    const axutil_env_t *env)
{
    return axutil_array_list_is_empty(all->policy_components, env);
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
neethi_all_serialize(
    neethi_all_t *neethi_all,
    axiom_node_t *parent,
    const axutil_env_t *env)
{

    axiom_node_t *all_node = NULL;
    axiom_element_t *all_ele = NULL;
    axiom_namespace_t *policy_ns = NULL;
    axutil_array_list_t *components = NULL;
    axis2_status_t status = AXIS2_FAILURE;

    policy_ns = axiom_namespace_create(env, NEETHI_NAMESPACE, NEETHI_PREFIX);

    all_ele =
        axiom_element_create(env, parent, NEETHI_ALL, policy_ns, &all_node);
    if (!all_node)
    {
        return AXIS2_FAILURE;
    }
    components = neethi_all_get_policy_components(neethi_all, env);

    if (components)
    {
        int i = 0;
        for (i = 0; i < axutil_array_list_size(components, env); i++)
        {
            neethi_operator_t *operator = NULL;
            operator =(neethi_operator_t *) axutil_array_list_get(components,
                                                                  env, i);
            if (operator)
            {
                status = neethi_operator_serialize(operator, env, all_node);
                if (status != AXIS2_SUCCESS)
                {
                    return status;
                }
            }
        }
    }
    return status;
}
