#include <axiom.h>
#include <axutil_utils.h>
#include <axutil_env.h>
#include <axutil_log_default.h>
#include <axutil_error_default.h>
#include <stdio.h>
#include <axiom_xml_reader.h>
#include <neethi_engine.h>
#include <axutil_array_list.h>

axis2_status_t AXIS2_CALL om_node_serialize(
    axiom_node_t * node,
    const axutil_env_t * env);

int
main(
    int argc,
    char **argv)
{
    /*axutil_allocator_t *allocator = axutil_allocator_init(NULL);
    axutil_error_t *error = axutil_error_create(allocator);
    const axutil_env_t *env = axutil_env_create_with_error(allocator, error);*/
    const axutil_env_t *env = NULL;
    axiom_xml_reader_t *reader = NULL;
    axiom_stax_builder_t *builder = NULL;
    axiom_document_t *document = NULL;
    axiom_node_t *root = NULL;
    axiom_element_t *root_ele = NULL;

    env = axutil_env_create_all("test.log", AXIS2_LOG_LEVEL_TRACE);

    reader = axiom_xml_reader_create_for_file(env, argv[1], NULL);

    if (!reader)
    {
        AXIS2_ERROR_SET(env->error, AXIS2_ERROR_CREATING_XML_STREAM_READER,
                        AXIS2_FAILURE);
        printf("xml reader creation failed\n");
        return 0;
    }

    builder = axiom_stax_builder_create(env, reader);
    if (!builder)
    {
        axiom_xml_reader_free(reader, env);
        printf("Builder creation failed\n");
        return 0;
    }
    document = axiom_stax_builder_get_document(builder, env);
    if (!document)
    {
        axiom_stax_builder_free(builder, env);
        printf("Document creation failed\n");
        return 0;
    }

    /*root = axiom_document_get_root_element(document, env); */
    root = axiom_document_build_all(document, env);
    if (!root)
    {
        axiom_stax_builder_free(builder, env);
        return 0;
    }

    if (root)
    {
        if (axiom_node_get_node_type(root, env) == AXIOM_ELEMENT)
        {
            root_ele =
                (axiom_element_t *) axiom_node_get_data_element(root, env);
            if (root_ele)
            {
                neethi_policy_t *neethi_policy = NULL;
                neethi_policy = neethi_engine_get_policy(env, root, root_ele);
                if (!neethi_policy)
                {
                    printf("Policy Creation fails\n");
                    return 0;
                }

                if(neethi_policy)
                {
                    axis2_char_t *id = NULL;
                    axis2_char_t *name = NULL;

                    id = neethi_policy_get_id(neethi_policy, env); 
                    if(id)
                    {
                        printf("Id is : %s\n", id);
                    }   
                    name = neethi_policy_get_name(neethi_policy, env);
                    if(name)
                    {
                        printf("Name is : %s\n", name);
                    }
                    neethi_policy_free(neethi_policy, env);
                    neethi_policy = NULL;

                    printf("Successful \n");
                }

                /*else
                {
                    axiom_node_t *s_node = NULL;
                    s_node = neethi_engine_serialize(neethi_policy, env);
                    if (!s_node)
                    {
                        printf("Serializing failed\n");
                        return 0;
                    }
                    if (om_node_serialize(s_node, env) != AXIS2_SUCCESS)
                        return 0;
                }*/
            }
        }
    }

    if(builder)
    {
        axiom_stax_builder_free(builder, env);
        builder = NULL;
    }

    axutil_env_free((axutil_env_t *)env);
    env = NULL;    

    printf("Successful\n");
    return 0;

}

axis2_status_t AXIS2_CALL
om_node_serialize(
    axiom_node_t * node,
    const axutil_env_t * env)
{

    axiom_output_t *om_output = NULL;
    axiom_xml_writer_t *writer = NULL;
    axis2_char_t *output_buffer = NULL;
    axis2_status_t status = AXIS2_FAILURE;

    writer = axiom_xml_writer_create_for_memory(env, NULL, AXIS2_TRUE, 0,
                                                AXIS2_XML_PARSER_TYPE_BUFFER);
    om_output = axiom_output_create(env, writer);

    status = axiom_node_serialize(node, env, om_output);
    if (status != AXIS2_SUCCESS)
    {
        printf("\naxiom_node_serialize failed\n");
        return 0;
    }
    else
        printf("\naxiom_node_serialize success\n");
    /* end serializing stuff */

    /*axiom_node_free_tree(node1, environment); */
    output_buffer = (axis2_char_t *) axiom_xml_writer_get_xml(writer, env);

    printf("\nend test_om_serialize\n");

    return AXIS2_SUCCESS;

}

axutil_array_list_t *AXIS2_CALL
load_policy_array(
    int argc,
    char **argv,
    const axutil_env_t * env)
{

    axiom_xml_reader_t *reader = NULL;
    axiom_stax_builder_t *builder = NULL;
    axiom_document_t *document = NULL;
    axiom_node_t *root = NULL;
    axiom_element_t *root_ele = NULL;
    int i = 0;
    axutil_array_list_t *arraylist = NULL;

    arraylist = axutil_array_list_create(env, 0);

    for (i = 1; i < argc; i++)
    {
        reader = axiom_xml_reader_create_for_file(env, argv[i], NULL);

        if (!reader)
        {
            AXIS2_ERROR_SET(env->error, AXIS2_ERROR_CREATING_XML_STREAM_READER,
                            AXIS2_FAILURE);
            printf("xml reader creation failed\n");
            return NULL;
        }

        builder = axiom_stax_builder_create(env, reader);
        if (!builder)
        {
            axiom_xml_reader_free(reader, env);
            printf("Builder creation failed\n");
            return NULL;
        }
        document = axiom_stax_builder_get_document(builder, env);
        if (!document)
        {
            axiom_stax_builder_free(builder, env);
            printf("Document creation failed\n");
            return NULL;
        }

        /*root = axiom_document_get_root_element(document, env); */
        root = axiom_document_build_all(document, env);
        if (!root)
        {
            axiom_stax_builder_free(builder, env);
            return NULL;
        }
        if (root)
        {
            if (axiom_node_get_node_type(root, env) == AXIOM_ELEMENT)
            {
                root_ele =
                    (axiom_element_t *) axiom_node_get_data_element(root, env);
                if (root_ele)
                {
                    neethi_policy_t *neethi_policy = NULL;
                    neethi_policy =
                        neethi_engine_get_policy(env, root, root_ele);
                    if (!neethi_policy)
                    {
                        printf("Policy Creation fails\n");
                        return NULL;
                    }
                    axutil_array_list_add(arraylist, env, neethi_policy);
                }
            }
        }
    }
    return arraylist;
}
