/*
 * 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 <axis2_arch_reader.h>
#include <string.h>
#include <axutil_class_loader.h>
#include <axis2_svc_builder.h>
#include <axis2_module_builder.h>
#include <axis2_svc.h>

struct axis2_arch_reader
{
    axis2_desc_builder_t *desc_builder;
};

AXIS2_EXTERN axis2_arch_reader_t *AXIS2_CALL
axis2_arch_reader_create(
    const axutil_env_t * env)
{
    axis2_arch_reader_t *arch_reader = NULL;

    arch_reader = (axis2_arch_reader_t *)AXIS2_MALLOC(env-> allocator, sizeof(axis2_arch_reader_t));

    if(!arch_reader)
    {
        AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
        return NULL;
    }

    arch_reader->desc_builder = NULL;

    return arch_reader;
}

AXIS2_EXTERN void AXIS2_CALL
axis2_arch_reader_free(
    axis2_arch_reader_t * arch_reader,
    const axutil_env_t * env)
{
    /* Description builder is owned by dep_engine, so do not free it here */

    if(arch_reader)
    {
        AXIS2_FREE(env->allocator, arch_reader);
    }

    return;
}

AXIS2_EXTERN struct axis2_svc *AXIS2_CALL
axis2_arch_reader_create_svc(
    const axutil_env_t * env,
    struct axis2_arch_file_data *file)
{
    axis2_svc_t *svc = NULL;
    svc = axis2_svc_create(env);
    return svc;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
axis2_arch_reader_process_svc_grp(
    axis2_arch_reader_t * arch_reader,
    const axutil_env_t * env,
    axis2_char_t * file_name,
    struct axis2_dep_engine * dep_engine,
    axis2_svc_grp_t * svc_grp)
{
    axis2_status_t status = AXIS2_FAILURE;
    axis2_char_t *svc_grp_xml = NULL;
    axis2_char_t *repos_path = NULL;
    axis2_bool_t file_flag = AXIS2_FALSE;
    AXIS2_PARAM_CHECK(env->error, file_name, AXIS2_FAILURE);
    AXIS2_PARAM_CHECK(env->error, dep_engine, AXIS2_FAILURE);
    AXIS2_PARAM_CHECK(env->error, svc_grp, AXIS2_FAILURE);

    file_flag = axis2_dep_engine_get_file_flag(dep_engine, env);

    if(!file_flag)
    {

        repos_path = axis2_dep_engine_get_repos_path(dep_engine, env);

        svc_grp_xml = axutil_strcat(env, repos_path, AXIS2_PATH_SEP_STR, AXIS2_SERVICE_FOLDER,
            AXIS2_PATH_SEP_STR, file_name, AXIS2_PATH_SEP_STR, AXIS2_SVC_XML, NULL);
    }
    else
    {
        repos_path = axis2_dep_engine_get_svc_dir(dep_engine, env);
        svc_grp_xml = axutil_strcat(env, repos_path, AXIS2_PATH_SEP_STR, file_name,
            AXIS2_PATH_SEP_STR, AXIS2_SVC_XML, NULL);
    }

    if(!svc_grp_xml)
    {
        AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
        AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Service xml file not found for %s", file_name);
        return AXIS2_FAILURE;
    }
    status = axutil_file_handler_access(svc_grp_xml, AXIS2_F_OK);
    if(AXIS2_SUCCESS == status)
    {
        struct axis2_arch_file_data *arch_file_data = NULL;
        axis2_char_t *svc_name = NULL;

        status
            = axis2_arch_reader_build_svc_grp(arch_reader, env, svc_grp_xml, dep_engine, svc_grp);
        if(AXIS2_SUCCESS != status)
        {
            return status;
        }
        arch_file_data = axis2_dep_engine_get_current_file_item(dep_engine, env);
        svc_name = axis2_arch_file_data_get_svc_name(arch_file_data, env);
        axis2_svc_grp_set_name(svc_grp, env, svc_name);
    }
    else
    {
        AXIS2_ERROR_SET(env->error, AXIS2_ERROR_SERVICE_XML_NOT_FOUND, AXIS2_FAILURE);
        AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Access to  service configuration file %s failed",
            file_name);
        status = AXIS2_FAILURE;
    }
    AXIS2_FREE(env->allocator, svc_grp_xml);
    return status;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
axis2_arch_reader_build_svc_grp(
    axis2_arch_reader_t * arch_reader,
    const axutil_env_t * env,
    axis2_char_t * svc_xml,
    axis2_dep_engine_t * dep_engine,
    axis2_svc_grp_t * svc_grp)
{
    axis2_char_t *root_element_name = NULL;
    axiom_node_t *svc_grp_node = NULL;
    axiom_element_t *svc_grp_element = NULL;
    axis2_status_t status = AXIS2_FAILURE;

    AXIS2_PARAM_CHECK(env->error, svc_xml, AXIS2_FAILURE);
    AXIS2_PARAM_CHECK(env->error, dep_engine, AXIS2_FAILURE);
    AXIS2_PARAM_CHECK(env->error, svc_grp, AXIS2_FAILURE);

    arch_reader->desc_builder = axis2_desc_builder_create_with_file_and_dep_engine(env, svc_xml,
        dep_engine);
    if(!arch_reader->desc_builder)
    {
        AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
            "Creating description builder for service file %s failed", svc_xml);
        return AXIS2_FAILURE;
    }
    axis2_dep_engine_add_desc_builder(dep_engine, env, arch_reader->desc_builder);

    svc_grp_node = axis2_desc_builder_build_om(arch_reader->desc_builder, env);

    if(svc_grp_node)
    {
        svc_grp_element = axiom_node_get_data_element(svc_grp_node, env);
        if(svc_grp_element)
        {
            root_element_name = axiom_element_get_localname(svc_grp_element, env);
        }
    }

    if(root_element_name && 0 == axutil_strcmp(AXIS2_SVC_ELEMENT, root_element_name))
    {
        /* If service group is actually a service. In this case service group 
         * contain only single service */
        axis2_svc_t *svc = NULL;
        axis2_svc_builder_t *svc_builder = NULL;
        axis2_arch_file_data_t *file_data = NULL;
        axutil_array_list_t *dep_svcs = NULL;
        axis2_char_t *svc_name = NULL;

        file_data = axis2_dep_engine_get_current_file_item(dep_engine, env);
        svc_name = axis2_arch_file_data_get_name(file_data, env);
        svc = axis2_arch_file_data_get_svc(file_data, env, svc_name);
        if(!svc)
        {
            axutil_qname_t *svc_qname = NULL;

            svc_qname = axutil_qname_create(env, svc_name, NULL, NULL);
            svc = axis2_svc_create_with_qname(env, svc_qname);
            status = axis2_arch_file_data_add_svc(file_data, env, svc);
            axutil_qname_free(svc_qname, env);
            if(AXIS2_SUCCESS != status)
            {
                axis2_svc_free(svc, env);
                return status;
            }
        }
        axis2_svc_set_parent(svc, env, svc_grp);

        svc_builder = axis2_svc_builder_create_with_dep_engine_and_svc(env, dep_engine, svc);
        status = axis2_svc_builder_populate_svc(svc_builder, env, svc_grp_node);
        axis2_dep_engine_add_svc_builder(dep_engine, env, svc_builder);
        if(AXIS2_SUCCESS != status)
        {
            AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Populating service failed for %s", svc_name);
            return AXIS2_FAILURE;
        }

        dep_svcs = axis2_arch_file_data_get_deployable_svcs(file_data, env);
        if(!dep_svcs)
        {
            AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
                "Deployable services list is NULL within arch file data");
            return AXIS2_FAILURE;
        }
        status = axutil_array_list_add(dep_svcs, env, svc);
        if(AXIS2_SUCCESS != status)
        {
            return AXIS2_FAILURE;
        }

    }
    else if(root_element_name && 0 == axutil_strcmp(AXIS2_SVC_GRP_ELEMENT, root_element_name))
    {
        axis2_svc_grp_builder_t *grp_builder = NULL;
        grp_builder = axis2_svc_grp_builder_create_with_svc_and_dep_engine(env, svc_grp_node,
            dep_engine);
        status = axis2_svc_grp_builder_populate_svc_grp(grp_builder, env, svc_grp);
        axis2_dep_engine_add_svc_grp_builder(dep_engine, env, grp_builder);
    }
    return status;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
axis2_arch_reader_read_module_arch(
    const axutil_env_t * env,
    axis2_char_t * file_name,
    axis2_dep_engine_t * dep_engine,
    axis2_module_desc_t * module_desc)
{
    axis2_status_t status = AXIS2_FAILURE;
    axis2_char_t *module_xml = NULL;
    axis2_char_t *repos_path = NULL;
    axis2_bool_t file_flag;

    AXIS2_PARAM_CHECK(env->error, file_name, AXIS2_FAILURE);
    AXIS2_PARAM_CHECK(env->error, dep_engine, AXIS2_FAILURE);
    AXIS2_PARAM_CHECK(env->error, module_desc, AXIS2_FAILURE);

    file_flag = axis2_dep_engine_get_file_flag(dep_engine, env);
    if(!file_flag)
    {
        repos_path = axis2_dep_engine_get_repos_path(dep_engine, env);
        module_xml = axutil_strcat(env, repos_path, AXIS2_PATH_SEP_STR, AXIS2_MODULE_FOLDER,
            AXIS2_PATH_SEP_STR, file_name, AXIS2_PATH_SEP_STR, AXIS2_MODULE_XML, NULL);
    }
    else
    {
        repos_path = axis2_dep_engine_get_module_dir(dep_engine, env);
        module_xml = axutil_strcat(env, repos_path, AXIS2_PATH_SEP_STR, file_name,
            AXIS2_PATH_SEP_STR, AXIS2_MODULE_XML, NULL);
    }

    if(!module_xml)
    {
        AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
        AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "No memory");
        return AXIS2_FAILURE;
    }
    status = axutil_file_handler_access(module_xml, AXIS2_F_OK);

    if(AXIS2_SUCCESS == status)
    {
        axis2_module_builder_t *module_builder = NULL;
        module_builder = axis2_module_builder_create_with_file_and_dep_engine_and_module(env,
            module_xml, dep_engine, module_desc);
        status = axis2_module_builder_populate_module(module_builder, env);
        axis2_dep_engine_add_module_builder(dep_engine, env, module_builder);
    }
    else
    {
        AXIS2_ERROR_SET(env->error, AXIS2_ERROR_MODULE_XML_NOT_FOUND_FOR_THE_MODULE, AXIS2_FAILURE);
        AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
            "Module configuration file access failed for module file %s", module_xml);
        status = AXIS2_FAILURE;
    }
    AXIS2_FREE(env->allocator, module_xml);
    return status;
}

AXIS2_EXTERN axutil_file_t *AXIS2_CALL
axis2_arch_reader_create_module_arch(
    const axutil_env_t * env,
    axis2_char_t * module_name)
{
    axutil_file_t *file = NULL;

    file = axutil_file_create(env);
    if(!file)
    {
        return NULL;
    }
    axutil_file_set_name(file, env, module_name);
    return file;
}

