/*
 * 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 <rp_supporting_tokens_builder.h>
#include <neethi_operator.h>
#include <neethi_policy.h>
#include <neethi_exactlyone.h>
#include <neethi_all.h>
#include <neethi_engine.h>

/*private functions*/

axis2_status_t AXIS2_CALL
supporting_tokens_process_alternatives(
    const axutil_env_t *env,
    neethi_all_t *all,
    rp_supporting_tokens_t *supporting_tokens);

axis2_bool_t AXIS2_CALL
is_token_assertion(
    const axutil_env_t *env,
    neethi_assertion_type_t type);

/***********************************/

AXIS2_EXTERN neethi_assertion_t *AXIS2_CALL
rp_supporting_tokens_builder_build(
    const axutil_env_t *env,
    axiom_node_t *node,
    axiom_element_t *element)
{
    rp_supporting_tokens_t *supporting_tokens = NULL;
    neethi_policy_t *policy = NULL;
    axiom_node_t *child_node = NULL;
    axiom_element_t *child_element = NULL;
    axutil_array_list_t *alternatives = NULL;
    neethi_operator_t *component = NULL;
    neethi_all_t *all = NULL;
    neethi_assertion_t *assertion = NULL;
    axis2_char_t *local_name = NULL;
    neethi_policy_t *normalized_policy = NULL;

    supporting_tokens = rp_supporting_tokens_create(env);
    local_name = axiom_element_get_localname(element, env);

    if(local_name)
    {
        if(axutil_strcmp(local_name, RP_SIGNED_SUPPORTING_TOKENS) == 0)
        {
            rp_supporting_tokens_set_type(supporting_tokens, env,
                RP_PROPERTY_SIGNED_SUPPORTING_TOKEN);
        }
        else if(axutil_strcmp(local_name, RP_SIGNED_ENDORSING_SUPPORTING_TOKENS) == 0)
        {
            rp_supporting_tokens_set_type(supporting_tokens, env,
                RP_PROPERTY_SIGNED_ENDORSING_SUPPORTING_TOKEN);
        }
        else if(axutil_strcmp(local_name, RP_SUPPORTING_TOKENS) == 0)
        {
            rp_supporting_tokens_set_type(supporting_tokens, env,
                RP_PROPERTY_SUPPORTING_SUPPORTING_TOKEN);
        }
        else if(axutil_strcmp(local_name, RP_ENDORSING_SUPPORTING_TOKENS) == 0)
        {
            rp_supporting_tokens_set_type(supporting_tokens, env,
                RP_PROPERTY_ENDORSING_SUPPORTING_TOKEN);
        }
        else
            return NULL;
    }
    else
        return NULL;

    child_node = axiom_node_get_first_element(node, env);
    if(!child_node)
    {
        return NULL;
    }

    if(axiom_node_get_node_type(child_node, env) == AXIOM_ELEMENT)
    {
        child_element = (axiom_element_t *)axiom_node_get_data_element(child_node, env);
        if(child_element)
        {
            policy = neethi_engine_get_policy(env, child_node, child_element);
            if(!policy)
            {
                return NULL;
            }
            normalized_policy = neethi_engine_get_normalize(env, AXIS2_FALSE, policy);
            alternatives = neethi_policy_get_alternatives(normalized_policy, env);
            neethi_policy_free(policy, env);
            policy = NULL;
            component = (neethi_operator_t *)axutil_array_list_get(alternatives, env, 0);
            all = (neethi_all_t *)neethi_operator_get_value(component, env);
            supporting_tokens_process_alternatives(env, all, supporting_tokens);

            assertion = neethi_assertion_create_with_args(env,
                (AXIS2_FREE_VOID_ARG)rp_supporting_tokens_free, supporting_tokens,
                ASSERTION_TYPE_SUPPORTING_TOKENS);

            neethi_policy_free(normalized_policy, env);
            normalized_policy = NULL;

            return assertion;
        }
        else
            return NULL;
    }
    else
        return NULL;
}

axis2_status_t AXIS2_CALL
supporting_tokens_process_alternatives(
    const axutil_env_t *env,
    neethi_all_t *all,
    rp_supporting_tokens_t *supporting_tokens)
{
    neethi_operator_t *operator = NULL;
    axutil_array_list_t *arraylist = NULL;
    neethi_assertion_t *assertion = NULL;
    neethi_assertion_type_t type;
    void *value = NULL;

    int i = 0;

    arraylist = neethi_all_get_policy_components(all, env);

    for(i = 0; i < axutil_array_list_size(arraylist, env); i++)
    {
        operator = (neethi_operator_t *)axutil_array_list_get(arraylist, env, i);
        assertion = (neethi_assertion_t *)neethi_operator_get_value(operator, env);
        value = neethi_assertion_get_value(assertion, env);
        type = neethi_assertion_get_type(assertion, env);

        if(value)
        {
            if(type == ASSERTION_TYPE_ALGORITHM_SUITE)
            {
                rp_algorithmsuite_t *algorithmsuite = NULL;
                algorithmsuite = (rp_algorithmsuite_t *)neethi_assertion_get_value(assertion, env);
                if(algorithmsuite)
                {
                    rp_supporting_tokens_set_algorithmsuite(supporting_tokens, env, algorithmsuite);
                }
                else
                    return AXIS2_FAILURE;
            }
            else if(is_token_assertion(env, type))
            {
                rp_property_t *token = NULL;
                token = rp_property_create(env);
                rp_token_identifier_set_token(token, assertion, env);
                rp_supporting_tokens_add_token(supporting_tokens, env, token);
            }
            else
                return AXIS2_FAILURE;
        }
        else
            return AXIS2_FAILURE;
    }
    return AXIS2_SUCCESS;
}

axis2_bool_t AXIS2_CALL
is_token_assertion(
    const axutil_env_t *env,
    neethi_assertion_type_t type)
{
    if(type == ASSERTION_TYPE_USERNAME_TOKEN)
    {
        return AXIS2_TRUE;
    }
    else if(type == ASSERTION_TYPE_X509_TOKEN)
    {
        return AXIS2_TRUE;
    }
    else if(type == ASSERTION_TYPE_ISSUED_TOKEN)
    {
        return AXIS2_TRUE;
    }
    else if(type == ASSERTION_TYPE_SAML_TOKEN)
    {
        return AXIS2_TRUE;
    }
    else
        return AXIS2_FALSE;
}
