/*
 * 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_asymmetric_binding_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 asymmetric_binding_process_alternatives(
    const axutil_env_t *env,
    neethi_all_t *all,
    rp_asymmetric_binding_t *asymmetric_binding);

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

AXIS2_EXTERN neethi_assertion_t *AXIS2_CALL
rp_asymmetric_binding_builder_build(
    const axutil_env_t *env,
    axiom_node_t *node,
    axiom_element_t *element)
{
    rp_asymmetric_binding_t *asymmetric_binding = 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;
    neethi_policy_t *normalized_policy = NULL;

    asymmetric_binding = rp_asymmetric_binding_create(env);

    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);
            asymmetric_binding_process_alternatives(env, all,
                                                    asymmetric_binding);

            assertion =
                neethi_assertion_create_with_args(env,
                                                  (AXIS2_FREE_VOID_ARG)rp_asymmetric_binding_free,
                                                  asymmetric_binding,
                                                  ASSERTION_TYPE_ASSYMMETRIC_BINDING);
            neethi_policy_free(normalized_policy, env);
            normalized_policy = NULL;

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

axis2_status_t AXIS2_CALL
asymmetric_binding_process_alternatives(
    const axutil_env_t *env,
    neethi_all_t *all,
    rp_asymmetric_binding_t * asymmetric_binding)
{

    neethi_operator_t *operator = NULL;
    axutil_array_list_t *arraylist = NULL;
    neethi_assertion_t *assertion = NULL;
    neethi_assertion_type_t type;
    void *value = NULL;
    rp_binding_commons_t *commons = NULL;
    rp_symmetric_asymmetric_binding_commons_t *as_commons = NULL;

    int i = 0;

    arraylist = neethi_all_get_policy_components(all, env);
    commons = rp_binding_commons_create(env);
    as_commons = rp_symmetric_asymmetric_binding_commons_create(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 (type == ASSERTION_TYPE_INITIATOR_TOKEN)
        {
            rp_property_t *initiator_token = NULL;
            initiator_token =
                (rp_property_t *) neethi_assertion_get_value(assertion, env);
            if (initiator_token)
            {
                rp_asymmetric_binding_set_initiator_token(asymmetric_binding,
                                                          env, initiator_token);
            }
            else
                return AXIS2_FAILURE;
        }
        else if (type == ASSERTION_TYPE_RECIPIENT_TOKEN)
        {
            rp_property_t *recipient_token = NULL;
            recipient_token =
                (rp_property_t *) neethi_assertion_get_value(assertion, env);
            if (recipient_token)
            {
                rp_asymmetric_binding_set_recipient_token(asymmetric_binding,
                                                          env, recipient_token);
            }
            else
                return AXIS2_FAILURE;
        }
        else if (type == ASSERTION_TYPE_ALGORITHM_SUITE)
        {
            rp_algorithmsuite_t *algorithmsuite = NULL;
            algorithmsuite =
                (rp_algorithmsuite_t *) neethi_assertion_get_value(assertion,
                                                                   env);
            if (algorithmsuite)
            {
                rp_binding_commons_set_algorithmsuite(commons, env,
                                                      algorithmsuite);
            }
            else
                return AXIS2_FAILURE;
        }
        else if (type == ASSERTION_TYPE_INCLUDE_TIMESTAMP)
        {
            rp_binding_commons_set_include_timestamp(commons, env, AXIS2_TRUE);
        }
        else if (type == ASSERTION_TYPE_LAYOUT)
        {
            rp_layout_t *layout = NULL;
            layout = (rp_layout_t *) neethi_assertion_get_value(assertion, env);
            if (layout)
            {
                rp_binding_commons_set_layout(commons, env, layout);
            }
            else
                return AXIS2_FAILURE;
        }
        else if (type == ASSERTION_TYPE_ENCRYPT_BEFORE_SIGNING)
        {
            rp_symmetric_asymmetric_binding_commons_set_protection_order
                (as_commons, env, RP_ENCRYPT_BEFORE_SIGNING);
        }
        else if (type == ASSERTION_TYPE_SIGN_BEFORE_ENCRYPTING)
        {
            rp_symmetric_asymmetric_binding_commons_set_protection_order
                (as_commons, env, RP_SIGN_BEFORE_ENCRYPTING);
        }
        else if (type == ASSERTION_TYPE_ENCRYPT_SIGNATURE)
        {
            rp_symmetric_asymmetric_binding_commons_set_signature_protection
                (as_commons, env, AXIS2_TRUE);
        }
        else if (type == ASSERTION_TYPE_PROTECT_TOKENS)
        {
            rp_symmetric_asymmetric_binding_commons_set_token_protection
                (as_commons, env, AXIS2_TRUE);
        }
        else if (type == ASSERTION_TYPE_ONLY_SIGN_ENTIRE_HEADERS_AND_BODY)
        {
            rp_symmetric_asymmetric_binding_commons_set_entire_headers_and_body_signatures
                (as_commons, env, AXIS2_TRUE);
        }
        else if (type == ASSERTION_TYPE_SUPPORTING_TOKENS)
        {
            rp_supporting_tokens_t *supporting_tokens = NULL;
            supporting_tokens =
                (rp_supporting_tokens_t *) neethi_assertion_get_value(assertion,
                                                                      env);
            if (supporting_tokens)
            {
                rp_property_type_t type;
                type = rp_supporting_tokens_get_type(supporting_tokens, env);
                if (type == RP_PROPERTY_SIGNED_SUPPORTING_TOKEN)
                {
                    rp_binding_commons_set_signed_supporting_tokens(commons,
                                                                    env,
                                                                    supporting_tokens);
                }
                else if (type == RP_PROPERTY_SIGNED_ENDORSING_SUPPORTING_TOKEN)
                {
                    rp_binding_commons_set_signed_endorsing_supporting_tokens
                        (commons, env, supporting_tokens);
                }
                else if (type == RP_PROPERTY_SUPPORTING_SUPPORTING_TOKEN)
                {
                    rp_binding_commons_set_supporting_tokens
                        (commons, env, supporting_tokens);
                }
                else if (type == RP_PROPERTY_ENDORSING_SUPPORTING_TOKEN)
                {
                    rp_binding_commons_set_endorsing_supporting_tokens
                        (commons, env, supporting_tokens);
                }
                else
                    return AXIS2_FAILURE;
            }
            else
                return AXIS2_FAILURE;
        }
        else
            return AXIS2_FAILURE;
    }
    rp_symmetric_asymmetric_binding_commons_set_binding_commons(as_commons, env,
                                                                commons);
    rp_asymmetric_binding_set_symmetric_asymmetric_binding_commons
        (asymmetric_binding, env, as_commons);

    return AXIS2_SUCCESS;
}
