/*
 * 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 <axiom_soap_const.h>
#include "_axiom_soap_header_block.h"
#include "_axiom_soap_header.h"
#include <axiom_soap_envelope.h>
#include <axiom_soap_builder.h>

struct axiom_soap_header_block
{

    /** om_element node corresponding to this headerblock */
    axiom_node_t *om_ele_node;

    /** soap version */
    int soap_version;
    axis2_bool_t processed;
};

AXIS2_EXTERN axiom_soap_header_block_t *AXIS2_CALL
axiom_soap_header_block_create(
    const axutil_env_t * env)
{
    axiom_soap_header_block_t *header_block = NULL;
    AXIS2_ENV_CHECK(env, NULL);
    header_block = (axiom_soap_header_block_t *)AXIS2_MALLOC(env->allocator,
        sizeof(axiom_soap_header_block_t));
    if(!header_block)
    {
        AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
        AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "No memory. Cannot create SOAP header block");
        return NULL;
    }

    header_block->om_ele_node = NULL;
    header_block->soap_version = AXIOM_SOAP_VERSION_NOT_SET;
    header_block->processed = AXIS2_FALSE;

    return header_block;
}

AXIS2_EXTERN axiom_soap_header_block_t *AXIS2_CALL
axiom_soap_header_block_create_with_parent(
    const axutil_env_t * env,
    const axis2_char_t * localname,
    axiom_namespace_t * ns,
    axiom_soap_header_t * header)
{
    axiom_soap_header_block_t *header_block = NULL;
    axiom_node_t *this_node = NULL;
    axiom_node_t *parent_node = NULL;
    axiom_element_t *om_ele = NULL;
    AXIS2_PARAM_CHECK(env->error, localname, NULL);

    header_block = axiom_soap_header_block_create(env);
    if(!header_block)
    {
        return NULL;
    }
    parent_node = axiom_soap_header_get_base_node(header, env);
    if(!parent_node)
    {
        return NULL;
    }
    om_ele = axiom_element_create(env, parent_node, localname, ns, &this_node);
    if(!om_ele)
    {
        axiom_soap_header_block_free(header_block, env);
        return NULL;
    }
    header_block->om_ele_node = this_node;

    axiom_soap_header_set_header_block(header, env, header_block);

    header_block->soap_version = axiom_soap_header_get_soap_version(header, env);

    return header_block;
}

AXIS2_EXTERN void AXIS2_CALL
axiom_soap_header_block_free(
    axiom_soap_header_block_t * header_block,
    const axutil_env_t * env)
{
    AXIS2_FREE(env->allocator, header_block);
    return;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
axiom_soap_header_block_set_role(
    axiom_soap_header_block_t * header_block,
    const axutil_env_t * env,
    axis2_char_t * role_uri)
{
    const axis2_char_t *attr_localname = NULL;
    const axis2_char_t *attr_nsuri = NULL;

    if(header_block->soap_version == AXIOM_SOAP_VERSION_NOT_SET)
    {
        return AXIS2_FAILURE;
    }
    if(header_block->soap_version == AXIOM_SOAP11)
    {
        attr_localname = AXIOM_SOAP11_ATTR_ACTOR;
        attr_nsuri = AXIOM_SOAP11_SOAP_ENVELOPE_NAMESPACE_URI;
    }
    if(header_block->soap_version == AXIOM_SOAP12)
    {
        attr_localname = AXIOM_SOAP12_SOAP_ROLE;
        attr_nsuri = AXIOM_SOAP12_SOAP_ENVELOPE_NAMESPACE_URI;
    }
    axiom_soap_header_block_set_attribute(header_block, env, attr_localname, role_uri, attr_nsuri);
    return AXIS2_SUCCESS;
}

AXIS2_EXTERN axis2_char_t *AXIS2_CALL axiom_soap_header_block_get_role(
    axiom_soap_header_block_t * header_block,
    const axutil_env_t * env)
{
    const axis2_char_t *attr_localname = NULL;
    const axis2_char_t *attr_nsuri = NULL;

    if (header_block->soap_version == AXIOM_SOAP_VERSION_NOT_SET)
    {
        return NULL;
    }
    if (header_block->soap_version == AXIOM_SOAP11)
    {
        attr_localname = AXIOM_SOAP11_ATTR_ACTOR;
        attr_nsuri = AXIOM_SOAP11_SOAP_ENVELOPE_NAMESPACE_URI;
    }
    if (header_block->soap_version == AXIOM_SOAP12)
    {
        attr_localname = AXIOM_SOAP12_SOAP_ROLE;
        attr_nsuri = AXIOM_SOAP12_SOAP_ENVELOPE_NAMESPACE_URI;
    }
    return axiom_soap_header_block_get_attribute(header_block, env,
        attr_localname, attr_nsuri);
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
axiom_soap_header_block_set_must_understand_with_bool(
    axiom_soap_header_block_t * header_block,
    const axutil_env_t * env,
    axis2_bool_t must_understand)
{
    const axis2_char_t *attr_nsuri = NULL;
    const axis2_char_t *attr_value = NULL;

    if(header_block->soap_version == AXIOM_SOAP_VERSION_NOT_SET)
    {
        return AXIS2_FAILURE;
    }
    if(header_block->soap_version == AXIOM_SOAP11)
    {
        attr_nsuri = AXIOM_SOAP11_SOAP_ENVELOPE_NAMESPACE_URI;
    }
    if(header_block->soap_version == AXIOM_SOAP12)
    {
        attr_nsuri = AXIOM_SOAP12_SOAP_ENVELOPE_NAMESPACE_URI;
    }
    if(must_understand)
    {
        attr_value = "1";
    }
    else
    {
        attr_value = "0";
    }
    return axiom_soap_header_block_set_attribute(header_block, env,
        AXIOM_SOAP_ATTR_MUST_UNDERSTAND, attr_value, attr_nsuri);

}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
axiom_soap_header_block_set_must_understand_with_string(
    axiom_soap_header_block_t * header_block,
    const axutil_env_t * env,
    axis2_char_t * must_understand)
{
    const axis2_char_t *attr_nsuri = NULL;

    AXIS2_PARAM_CHECK(env->error, must_understand, AXIS2_FAILURE);

    if(header_block->soap_version == AXIOM_SOAP_VERSION_NOT_SET)
    {
        return AXIS2_FAILURE;
    }
    if(header_block->soap_version == AXIOM_SOAP11)
    {
        attr_nsuri = AXIOM_SOAP11_SOAP_ENVELOPE_NAMESPACE_URI;
    }
    if(header_block->soap_version == AXIOM_SOAP12)
    {
        attr_nsuri = AXIOM_SOAP12_SOAP_ENVELOPE_NAMESPACE_URI;
    }

    if(axutil_strcmp(AXIOM_SOAP_ATTR_MUST_UNDERSTAND_TRUE, must_understand) == 0 || axutil_strcmp(
        AXIOM_SOAP_ATTR_MUST_UNDERSTAND_FALSE, must_understand) == 0 || axutil_strcmp(
        AXIOM_SOAP_ATTR_MUST_UNDERSTAND_0, must_understand) == 0 || axutil_strcmp(
        AXIOM_SOAP_ATTR_MUST_UNDERSTAND_1, must_understand) == 0)
    {

        axiom_soap_header_block_set_attribute(header_block, env, AXIOM_SOAP_ATTR_MUST_UNDERSTAND,
            must_understand, attr_nsuri);
        return AXIS2_SUCCESS;
    }
    else
    {
        AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_MUST_UNDERSTAND_SHOULD_BE_1_0_TRUE_FALSE, AXIS2_FAILURE);
        return AXIS2_FAILURE;
    }
}

AXIS2_EXTERN axis2_bool_t AXIS2_CALL
axiom_soap_header_block_get_must_understand(
    axiom_soap_header_block_t * header_block,
    const axutil_env_t * env)
{
    const axis2_char_t *must_understand = NULL;
    const axis2_char_t *attr_nsuri = NULL;

    if(header_block->soap_version == AXIOM_SOAP_VERSION_NOT_SET)
    {
        return AXIS2_FAILURE;
    }
    if(header_block->soap_version == AXIOM_SOAP11)
    {
        attr_nsuri = AXIOM_SOAP11_SOAP_ENVELOPE_NAMESPACE_URI;
    }
    if(header_block->soap_version == AXIOM_SOAP12)
    {
        attr_nsuri = AXIOM_SOAP12_SOAP_ENVELOPE_NAMESPACE_URI;
    }
    must_understand = axiom_soap_header_block_get_attribute(header_block, env,
        AXIOM_SOAP_ATTR_MUST_UNDERSTAND, attr_nsuri);
    if(!must_understand)
    {
        return AXIS2_FALSE;
    }
    if(axutil_strcmp(must_understand, AXIOM_SOAP_ATTR_MUST_UNDERSTAND_1) == 0 || axutil_strcmp(
        must_understand, AXIOM_SOAP_ATTR_MUST_UNDERSTAND_TRUE) == 0)
    {
        return AXIS2_TRUE;
    }
    else if(axutil_strcmp(must_understand, AXIOM_SOAP_ATTR_MUST_UNDERSTAND_0) == 0
        || axutil_strcmp(must_understand, AXIOM_SOAP_ATTR_MUST_UNDERSTAND_FALSE) == 0)
    {
        return AXIS2_FALSE;
    }
    AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_INVALID_VALUE_FOUND_IN_MUST_UNDERSTAND, AXIS2_FAILURE);
    return AXIS2_FALSE;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
axiom_soap_header_block_set_attribute(
    axiom_soap_header_block_t * header_block,
    const axutil_env_t * env,
    const axis2_char_t * attr_name,
    const axis2_char_t * attr_value,
    const axis2_char_t * soap_envelope_namespace_uri)
{
    axiom_attribute_t *om_attr = NULL;
    axiom_node_t *header_node = NULL;
    axiom_element_t *header_ele = NULL;
    axiom_namespace_t *header_ns = NULL;
    axis2_char_t *prefix = NULL;
    axutil_qname_t *qn = NULL;
    axiom_namespace_t *om_ns = NULL;
    axiom_element_t *om_ele = NULL;

    AXIS2_PARAM_CHECK(env->error, attr_name, AXIS2_FAILURE);

    header_node = axiom_node_get_parent(header_block->om_ele_node, env);
    if(!header_node)
    {
        return AXIS2_FAILURE;
    }
    if(axiom_node_get_node_type(header_node, env) == AXIOM_ELEMENT)
    {
        header_ele = (axiom_element_t *)axiom_node_get_data_element(header_node, env);
        if(!header_ele)
        {
            return AXIS2_FAILURE;
        }
        header_ns = axiom_element_get_namespace(header_ele, env, header_node);
        if(!header_ns)
        {
            return AXIS2_FAILURE;
        }
        prefix = axiom_namespace_get_prefix(header_ns, env);
    }

    qn = axutil_qname_create(env, attr_name, soap_envelope_namespace_uri, prefix);

    if(!qn)
    {
        return AXIS2_FAILURE;
    }
    if(!header_block->om_ele_node)
    {
        return AXIS2_FAILURE;
    }
    om_ele = (axiom_element_t *)axiom_node_get_data_element(header_block-> om_ele_node, env);

    om_attr = axiom_element_get_attribute(om_ele, env, qn);

    axutil_qname_free(qn, env);
    if(om_attr)
    {
        return axiom_attribute_set_value(om_attr, env, attr_value);
    }
    if(soap_envelope_namespace_uri)
    {
        if(prefix)
        {
            om_ns = axiom_namespace_create(env, soap_envelope_namespace_uri, prefix);
        }
        else
        {
            om_ns = axiom_namespace_create(env, soap_envelope_namespace_uri,
                AXIOM_SOAP_DEFAULT_NAMESPACE_PREFIX);
        }
    }
    om_attr = axiom_attribute_create(env, attr_name, attr_value, om_ns);
    if(!om_attr && om_ns)
    {
        axiom_namespace_free(om_ns, env);
        return AXIS2_FAILURE;
    }

    return axiom_element_add_attribute(om_ele, env, om_attr, header_block->om_ele_node);
}

AXIS2_EXTERN axis2_char_t *AXIS2_CALL
axiom_soap_header_block_get_attribute(
    axiom_soap_header_block_t * header_block,
    const axutil_env_t * env,
    const axis2_char_t * attr_name,
    const axis2_char_t * soap_envelope_namespace_uri)
{
    axiom_attribute_t *om_attr = NULL;
    axis2_char_t *attr_value = NULL;
    axiom_node_t *header_node = NULL;
    axiom_element_t *header_ele = NULL;
    axiom_namespace_t *header_ns = NULL;
    axis2_char_t *prefix = NULL;
    axutil_qname_t *qn = NULL;
    axiom_element_t *om_ele = NULL;
    AXIS2_PARAM_CHECK(env->error, attr_name, NULL);
    AXIS2_PARAM_CHECK(env->error, soap_envelope_namespace_uri, NULL);

    header_node = axiom_node_get_parent(header_block->om_ele_node, env);
    if(!header_node)
    {
        return NULL;
    }
    if(axiom_node_get_node_type(header_node, env) == AXIOM_ELEMENT)
    {
        header_ele = (axiom_element_t *)axiom_node_get_data_element(header_node, env);
        if(!header_ele)
        {
            return NULL;
        }
        header_ns = axiom_element_get_namespace(header_ele, env, header_node);
        if(!header_ns)
        {
            return NULL;
        }
        prefix = axiom_namespace_get_prefix(header_ns, env);
    }
    qn = axutil_qname_create(env, attr_name, soap_envelope_namespace_uri, prefix);
    if(!qn)
    {
        return NULL;
    }
    om_ele = (axiom_element_t *)axiom_node_get_data_element(header_block-> om_ele_node, env);
    om_attr = axiom_element_get_attribute(om_ele, env, qn);
    if(om_attr)
    {
        attr_value = axiom_attribute_get_value(om_attr, env);
    }
    axutil_qname_free(qn, env);
    return attr_value;
}

AXIS2_EXTERN axis2_bool_t AXIS2_CALL
axiom_soap_header_block_is_processed(
    axiom_soap_header_block_t * header_block,
    const axutil_env_t * env)
{
    return header_block->processed;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
axiom_soap_header_block_set_processed(
    axiom_soap_header_block_t * header_block,
    const axutil_env_t * env)
{
    header_block->processed = AXIS2_TRUE;
    return AXIS2_SUCCESS;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
axiom_soap_header_block_set_base_node(
    axiom_soap_header_block_t * header_block,
    const axutil_env_t * env,
    axiom_node_t * node)
{
    AXIS2_PARAM_CHECK(env->error, node, AXIS2_FAILURE);

    if(axiom_node_get_node_type(node, env) != AXIOM_ELEMENT)
    {
        AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_INVALID_BASE_TYPE, AXIS2_FAILURE);
        return AXIS2_FAILURE;
    }
    header_block->om_ele_node = node;
    return AXIS2_SUCCESS;

}

AXIS2_EXTERN axiom_node_t *AXIS2_CALL axiom_soap_header_block_get_base_node(
    axiom_soap_header_block_t * header_block,
    const axutil_env_t * env)
{
    return header_block->om_ele_node;
}

AXIS2_EXTERN int AXIS2_CALL axiom_soap_header_block_get_soap_version(
    axiom_soap_header_block_t * header_block,
    const axutil_env_t * env)
{
    return header_block->soap_version;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
axiom_soap_header_block_set_soap_version(
    axiom_soap_header_block_t * header_block,
    const axutil_env_t * env,
    int soap_version)
{

    header_block->soap_version = soap_version;
    return AXIS2_SUCCESS;
}
