/*
 * 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_handler_desc.h>
#include <axutil_string.h>
#include <axis2_svc.h>
#include <axis2_conf_ctx.h>

const axis2_char_t *AXIS2_CTX_HANDLER_NAME = "context_handler";

/**
 * By the time the control comes to this handler, the dispatching must have
 * happened so that the message context contains the service group, service and
 * operation. This will then try to find the contexts for service group, service
 * and the operation.
 */

axis2_status_t AXIS2_CALL
axis2_ctx_handler_invoke(
    axis2_handler_t * handler,
    const axutil_env_t * env,
    struct axis2_msg_ctx *msg_ctx);

axis2_handler_t *AXIS2_CALL
axis2_ctx_handler_create(
    const axutil_env_t * env,
    const axutil_string_t * string)
{
    axis2_handler_t *handler = NULL;
    axis2_handler_desc_t *handler_desc = NULL;
    axutil_string_t *handler_string = NULL;

    if(string)
    {
        handler_string = axutil_string_clone((axutil_string_t *)string, env);
        if(!(handler_string))
        {
            AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
            return NULL;
        }
    }
    else
    {
        /* create default string */
        handler_string = axutil_string_create_const(env, (axis2_char_t **)&AXIS2_CTX_HANDLER_NAME);
        if(!handler_string)
        {
            return NULL;
        }
    }

    handler = axis2_handler_create(env);
    if(!handler)
    {
        return NULL;
    }

    /* handler desc of base handler */
    handler_desc = axis2_handler_desc_create(env, handler_string);
    axutil_string_free(handler_string, env);
    if(!handler_desc)
    {
        axis2_handler_free(handler, env);
        return NULL;
    }

    axis2_handler_init(handler, env, handler_desc);

    /* set the base struct's invoke op */
    axis2_handler_set_invoke(handler, env, axis2_ctx_handler_invoke);

    return handler;
}

axis2_status_t AXIS2_CALL
axis2_ctx_handler_invoke(
    axis2_handler_t * handler,
    const axutil_env_t * env,
    struct axis2_msg_ctx * msg_ctx)
{
    axis2_op_t *op = NULL;
    axis2_svc_ctx_t *svc_ctx = NULL;
    axis2_op_ctx_t *op_ctx = NULL;
    axis2_svc_grp_ctx_t *svc_grp_ctx = NULL;

    AXIS2_PARAM_CHECK(env->error, msg_ctx, AXIS2_FAILURE);
    AXIS2_LOG_TRACE(env->log, AXIS2_LOG_SI, "Entry:axis2_ctx_handler_invoke");

    op_ctx = axis2_msg_ctx_get_op_ctx(msg_ctx, env);
    svc_ctx = axis2_msg_ctx_get_svc_ctx(msg_ctx, env);

    if(op_ctx && svc_ctx)
    {
        svc_grp_ctx = axis2_svc_ctx_get_parent(svc_ctx, env);
        if(svc_grp_ctx)
        {
            axutil_string_t *svc_grp_ctx_id_str = axutil_string_create(env,
                axis2_svc_grp_ctx_get_id(svc_grp_ctx, env));
            axis2_msg_ctx_set_svc_grp_ctx_id(msg_ctx, env, svc_grp_ctx_id_str);
            axutil_string_free(svc_grp_ctx_id_str, env);
        }
        return AXIS2_SUCCESS;
    }

    op = axis2_msg_ctx_get_op(msg_ctx, env);
    if(op)
    {
        op_ctx = axis2_op_find_existing_op_ctx(op, env, msg_ctx);
    }

    if(op_ctx)
    {
        axis2_op_register_op_ctx(op, env, msg_ctx, op_ctx);
        svc_ctx = axis2_op_ctx_get_parent(op_ctx, env);
        if(svc_ctx)
        {
            axutil_string_t *svc_grp_ctx_id_str = NULL;
            const axis2_char_t *grp_ctx_id = NULL;

            svc_grp_ctx = axis2_svc_ctx_get_parent(svc_ctx, env);
            axis2_msg_ctx_set_svc_ctx(msg_ctx, env, svc_ctx);
            axis2_msg_ctx_set_svc_grp_ctx(msg_ctx, env, svc_grp_ctx);
            grp_ctx_id = axis2_svc_grp_ctx_get_id(svc_grp_ctx, env);
            svc_grp_ctx_id_str = axutil_string_create(env, grp_ctx_id);
            axis2_msg_ctx_set_svc_grp_ctx_id(msg_ctx, env, svc_grp_ctx_id_str);
            axutil_string_free(svc_grp_ctx_id_str, env);
        }

        return AXIS2_SUCCESS;
    }
    else if(op) /*  2. if no op_ctx, create new op_ctx */
    {
        axis2_conf_ctx_t *conf_ctx = NULL;
        axis2_bool_t use_pools = AXIS2_FALSE;
        axutil_param_t *param = axis2_msg_ctx_get_parameter(msg_ctx, env, AXIS2_PERSIST_OP_CTX);

        use_pools = (param && 0 == axutil_strcmp(AXIS2_VALUE_TRUE, axutil_param_get_value(param,
            env)));

        if(use_pools)
        {
            axutil_allocator_switch_to_global_pool(env->allocator);
        }
        op_ctx = axis2_op_ctx_create(env, op, NULL);
        if(!op_ctx)
        {
            axis2_char_t *op_name = axutil_qname_get_localpart(axis2_op_get_qname(op, env), env);
            AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
                "Could not create Operation context for operatoin %s", op_name);

            return AXIS2_FAILURE;
        }

        axis2_msg_ctx_set_op_ctx(msg_ctx, env, op_ctx);

        axis2_op_register_op_ctx(op, env, msg_ctx, op_ctx);

        conf_ctx = axis2_msg_ctx_get_conf_ctx(msg_ctx, env);
        if(conf_ctx)
        {
            if(!use_pools)
            {
                axutil_allocator_switch_to_global_pool(env->allocator);
            }

            svc_grp_ctx = axis2_conf_ctx_fill_ctxs(conf_ctx, env, msg_ctx);

            if(!use_pools)
            {
                axutil_allocator_switch_to_local_pool(env->allocator);
            }
        }

        if(use_pools)
        {
            axutil_allocator_switch_to_local_pool(env->allocator);
        }
    }

    if(!svc_grp_ctx && (axis2_msg_ctx_get_server_side(msg_ctx, env)))
    {
        AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Service group context not found");
        return AXIS2_FAILURE;
    }

    AXIS2_LOG_TRACE(env->log, AXIS2_LOG_SI, "Exit:axis2_ctx_handler_invoke");

    return AXIS2_SUCCESS;
}

