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

struct rp_symmetric_asymmetric_binding_commons_t
{
    rp_binding_commons_t *binding_commons;
    axis2_char_t *protection_order;
    axis2_bool_t signature_protection;
    axis2_bool_t token_protection;
    axis2_bool_t entire_headers_and_body_signatures;

};

AXIS2_EXTERN rp_symmetric_asymmetric_binding_commons_t *AXIS2_CALL
rp_symmetric_asymmetric_binding_commons_create(
    const axutil_env_t * env)
{
    rp_symmetric_asymmetric_binding_commons_t *symmetric_asymmetric_binding_commons = NULL;

    AXIS2_ENV_CHECK(env, NULL);

    symmetric_asymmetric_binding_commons
        = (rp_symmetric_asymmetric_binding_commons_t *)AXIS2_MALLOC(env-> allocator,
            sizeof(rp_symmetric_asymmetric_binding_commons_t));

    if(symmetric_asymmetric_binding_commons == NULL)
    {
        AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
        return NULL;
    }
    symmetric_asymmetric_binding_commons->binding_commons = NULL;
    symmetric_asymmetric_binding_commons->protection_order = RP_SIGN_BEFORE_ENCRYPTING;
    symmetric_asymmetric_binding_commons->signature_protection = AXIS2_FALSE;
    symmetric_asymmetric_binding_commons->token_protection = AXIS2_FALSE;
    symmetric_asymmetric_binding_commons->entire_headers_and_body_signatures = AXIS2_FALSE;

    return symmetric_asymmetric_binding_commons;
}

AXIS2_EXTERN void AXIS2_CALL
rp_symmetric_asymmetric_binding_commons_free(
    rp_symmetric_asymmetric_binding_commons_t * symmetric_asymmetric_binding_commons,
    const axutil_env_t * env)
{
    AXIS2_ENV_CHECK(env, AXIS2_FAILURE);

    if(symmetric_asymmetric_binding_commons)
    {
        if(symmetric_asymmetric_binding_commons->binding_commons)
        {
            rp_binding_commons_free(symmetric_asymmetric_binding_commons-> binding_commons, env);
            symmetric_asymmetric_binding_commons->binding_commons = NULL;
        }
        AXIS2_FREE(env->allocator, symmetric_asymmetric_binding_commons);
        symmetric_asymmetric_binding_commons = NULL;
    }
    return;
}

/* Implementations */
AXIS2_EXTERN rp_binding_commons_t *AXIS2_CALL
rp_symmetric_asymmetric_binding_commons_get_binding_commons(
    rp_symmetric_asymmetric_binding_commons_t * symmetric_asymmetric_binding_commons,
    const axutil_env_t * env)
{
    AXIS2_ENV_CHECK(env, NULL);

    return symmetric_asymmetric_binding_commons->binding_commons;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
rp_symmetric_asymmetric_binding_commons_set_binding_commons(
    rp_symmetric_asymmetric_binding_commons_t * symmetric_asymmetric_binding_commons,
    const axutil_env_t * env,
    rp_binding_commons_t * binding_commons)
{
    AXIS2_ENV_CHECK(env, AXIS2_FAILURE);
    AXIS2_PARAM_CHECK(env->error, binding_commons, AXIS2_FAILURE);

    symmetric_asymmetric_binding_commons->binding_commons = binding_commons;
    return AXIS2_SUCCESS;
}

AXIS2_EXTERN axis2_bool_t AXIS2_CALL
rp_symmetric_asymmetric_binding_commons_get_signature_protection(
    rp_symmetric_asymmetric_binding_commons_t * symmetric_asymmetric_binding_commons,
    const axutil_env_t * env)
{
    AXIS2_ENV_CHECK(env, AXIS2_FALSE);

    return symmetric_asymmetric_binding_commons->signature_protection;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
rp_symmetric_asymmetric_binding_commons_set_signature_protection(
    rp_symmetric_asymmetric_binding_commons_t * symmetric_asymmetric_binding_commons,
    const axutil_env_t * env,
    axis2_bool_t signature_protection)
{
    AXIS2_ENV_CHECK(env, AXIS2_FAILURE);
    AXIS2_PARAM_CHECK(env->error, signature_protection, AXIS2_FAILURE);
    symmetric_asymmetric_binding_commons->signature_protection = signature_protection;

    return AXIS2_SUCCESS;
}

AXIS2_EXTERN axis2_bool_t AXIS2_CALL
rp_symmetric_asymmetric_binding_commons_get_token_protection(
    rp_symmetric_asymmetric_binding_commons_t * symmetric_asymmetric_binding_commons,
    const axutil_env_t * env)
{
    AXIS2_ENV_CHECK(env, AXIS2_FALSE);

    return symmetric_asymmetric_binding_commons->token_protection;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
rp_symmetric_asymmetric_binding_commons_set_token_protection(
    rp_symmetric_asymmetric_binding_commons_t * symmetric_asymmetric_binding_commons,
    const axutil_env_t * env,
    axis2_bool_t token_protection)
{
    AXIS2_ENV_CHECK(env, AXIS2_FAILURE);
    AXIS2_PARAM_CHECK(env->error, token_protection, AXIS2_FAILURE);

    symmetric_asymmetric_binding_commons->token_protection = token_protection;
    return AXIS2_SUCCESS;
}

AXIS2_EXTERN axis2_bool_t AXIS2_CALL
rp_symmetric_asymmetric_binding_commons_get_entire_headers_and_body_signatures(
    rp_symmetric_asymmetric_binding_commons_t * symmetric_asymmetric_binding_commons,
    const axutil_env_t * env)
{
    AXIS2_ENV_CHECK(env, AXIS2_FALSE);

    return symmetric_asymmetric_binding_commons-> entire_headers_and_body_signatures;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
rp_symmetric_asymmetric_binding_commons_set_entire_headers_and_body_signatures(
    rp_symmetric_asymmetric_binding_commons_t * symmetric_asymmetric_binding_commons,
    const axutil_env_t * env,
    axis2_bool_t entire_headers_and_body_signatures)
{
    AXIS2_ENV_CHECK(env, AXIS2_FAILURE);
    AXIS2_PARAM_CHECK(env->error, entire_headers_and_body_signatures, AXIS2_FAILURE);

    symmetric_asymmetric_binding_commons->entire_headers_and_body_signatures
        = entire_headers_and_body_signatures;

    return AXIS2_SUCCESS;
}

AXIS2_EXTERN axis2_char_t *AXIS2_CALL
rp_symmetric_asymmetric_binding_commons_get_protection_order(
    rp_symmetric_asymmetric_binding_commons_t * symmetric_asymmetric_binding_commons,
    const axutil_env_t * env)
{
    AXIS2_ENV_CHECK(env, NULL);

    return symmetric_asymmetric_binding_commons->protection_order;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
rp_symmetric_asymmetric_binding_commons_set_protection_order(
    rp_symmetric_asymmetric_binding_commons_t * symmetric_asymmetric_binding_commons,
    const axutil_env_t * env,
    axis2_char_t * protection_order)
{
    AXIS2_ENV_CHECK(env, AXIS2_FAILURE);
    AXIS2_PARAM_CHECK(env->error, protection_order, AXIS2_FAILURE);

    symmetric_asymmetric_binding_commons->protection_order = protection_order;
    return AXIS2_SUCCESS;
}
