/*
 * 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_x509_token_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 x509_token_process_alternatives(
    const axutil_env_t *env,
    neethi_all_t *all,
    rp_x509_token_t *x509_token);

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

AXIS2_EXTERN neethi_assertion_t *AXIS2_CALL
rp_x509_token_builder_build(
    const axutil_env_t *env,
    axiom_node_t *node,
    axiom_element_t *element)
{
    rp_x509_token_t *x509_token = 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;
    axis2_char_t *inclusion_value = NULL;
    axutil_qname_t *qname = NULL;
    neethi_assertion_t *assertion = NULL;
    neethi_policy_t *normalized_policy = NULL;

    x509_token = rp_x509_token_create(env);
    qname = axutil_qname_create(env, RP_INCLUDE_TOKEN, RP_SP_NS_11, RP_SP_PREFIX);
    inclusion_value = axiom_element_get_attribute_value(element, env, qname);
    axutil_qname_free(qname, env);
    qname = NULL;

    if(!inclusion_value)
    {
        /* we can try whether WS-SP1.2 specific inclusion value */
        qname = axutil_qname_create(env, RP_INCLUDE_TOKEN, RP_SP_NS_12, RP_SP_PREFIX);
        inclusion_value = axiom_element_get_attribute_value(element, env, qname);
        axutil_qname_free(qname, env);
        qname = NULL;
    }

    rp_x509_token_set_inclusion(x509_token, env, inclusion_value);

    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);
            neethi_policy_free(policy, env);
            policy = NULL;
            alternatives =
                neethi_policy_get_alternatives(normalized_policy, env);
            component =
                (neethi_operator_t *) axutil_array_list_get(alternatives, env,
                                                            0);
            all = (neethi_all_t *) neethi_operator_get_value(component, env);
            x509_token_process_alternatives(env, all, x509_token);

            assertion =
                neethi_assertion_create_with_args(env,
                                                  (AXIS2_FREE_VOID_ARG)rp_x509_token_free,
                                                  x509_token,
                                                  ASSERTION_TYPE_X509_TOKEN);

            neethi_policy_free(normalized_policy, env);
            normalized_policy = NULL;

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

axis2_status_t AXIS2_CALL
x509_token_process_alternatives(
    const axutil_env_t *env,
    neethi_all_t *all,
    rp_x509_token_t *x509_token)
{
    neethi_operator_t *operator = NULL;
    axutil_array_list_t *arraylist = NULL;
    neethi_assertion_t *assertion = NULL;
    neethi_assertion_type_t type;

    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);
        type = neethi_assertion_get_type(assertion, env);

        if(type == ASSERTION_TYPE_REQUIRE_DERIVED_KEYS_SC10)
        {
            rp_x509_token_set_derivedkey(x509_token, env, DERIVEKEY_NEEDED);
            rp_x509_token_set_derivedkey_version(x509_token, env, DERIVEKEY_VERSION_SC10);
        }  
        else if(type == ASSERTION_TYPE_REQUIRE_DERIVED_KEYS_SC13)
        {
            rp_x509_token_set_derivedkey(x509_token, env, DERIVEKEY_NEEDED);
            rp_x509_token_set_derivedkey_version(x509_token, env, DERIVEKEY_VERSION_SC13);
        }
        else if (type == ASSERTION_TYPE_REQUIRE_KEY_IDENTIFIRE_REFERENCE)
        {
            rp_x509_token_set_require_key_identifier_reference(x509_token, env,
                                                               AXIS2_TRUE);
        }
        else if (type == ASSERTION_TYPE_REQUIRE_ISSUER_SERIAL_REFERENCE)
        {
            rp_x509_token_set_require_issuer_serial_reference(x509_token, env,
                                                              AXIS2_TRUE);
        }
        else if (type == ASSERTION_TYPE_REQUIRE_EMBEDDED_TOKEN_REFERENCE)
        {
            rp_x509_token_set_require_embedded_token_reference(x509_token, env,
                                                               AXIS2_TRUE);
        }
        else if (type == ASSERTION_TYPE_REQUIRE_THUMBPRINT_REFERENCE)
        {
            rp_x509_token_set_require_thumb_print_reference(x509_token, env,
                                                            AXIS2_TRUE);
        }
        else if (type == ASSERTION_TYPE_WSS_X509_V1_TOKEN_10)
        {
            rp_x509_token_set_token_version_and_type(x509_token, env,
                                                     RP_WSS_X509_V1_TOKEN_10);
        }
        else if (type == ASSERTION_TYPE_WSS_X509_V3_TOKEN_10)
        {
            rp_x509_token_set_token_version_and_type(x509_token, env,
                                                     RP_WSS_X509_V3_TOKEN_10);
        }
        else
            return AXIS2_FAILURE;
    }
    return AXIS2_SUCCESS;
}
