/*
 * 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_disp.h>
#include <axis2_handler_desc.h>
#include <axutil_string.h>
#include <axis2_relates_to.h>
#include <axis2_svc.h>
#include <axis2_const.h>
#include <axis2_conf_ctx.h>
#include <axis2_addr.h>
#include <axutil_utils.h>

const axis2_char_t *AXIS2_REQ_URI_DISP_NAME = "request_uri_based_dispatcher";

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

axis2_svc_t *AXIS2_CALL axis2_req_uri_disp_find_svc(
    axis2_msg_ctx_t * msg_ctx,
    const axutil_env_t * env);

axis2_op_t *AXIS2_CALL axis2_req_uri_disp_find_op(
    axis2_msg_ctx_t * msg_ctx,
    const axutil_env_t * env,
    axis2_svc_t * svc);

AXIS2_EXTERN axis2_disp_t *AXIS2_CALL
axis2_req_uri_disp_create(
    const axutil_env_t * env)
{
    axis2_disp_t *disp = NULL;
    axis2_handler_t *handler = NULL;
    axutil_string_t *name = NULL;

    name = axutil_string_create_const(env, (axis2_char_t **)&AXIS2_REQ_URI_DISP_NAME);

    disp = axis2_disp_create(env, name);
    if(!disp)
    {
        AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
        return NULL;
    }

    handler = axis2_disp_get_base(disp, env);
    if(!handler)
    {
        AXIS2_ERROR_SET(env->error, AXIS2_ERROR_INVALID_HANDLER_STATE, AXIS2_FAILURE);
        return NULL;
    }

    axis2_handler_set_invoke(handler, env, axis2_req_uri_disp_invoke);

    axutil_string_free(name, env);

    return disp;
}

axis2_svc_t *AXIS2_CALL
axis2_req_uri_disp_find_svc(
    axis2_msg_ctx_t * msg_ctx,
    const axutil_env_t * env)
{
    axis2_endpoint_ref_t *endpoint_ref = NULL;
    axis2_svc_t *svc = NULL;

    if(axis2_msg_ctx_get_doing_rest(msg_ctx, env))
        return NULL;

    endpoint_ref = axis2_msg_ctx_get_to(msg_ctx, env);

    if(endpoint_ref)
    {
        const axis2_char_t *address = NULL;

        address = axis2_endpoint_ref_get_address(endpoint_ref, env);
        if(address)
        {
            axis2_char_t **url_tokens = NULL;
            AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI,
                "Checking for service using target endpoint address : %s", address);

            url_tokens = axutil_parse_request_url_for_svc_and_op(env, address);

            if(url_tokens)
            {
                if(url_tokens[0])
                {
                    axis2_conf_ctx_t *conf_ctx = NULL;

                    conf_ctx = axis2_msg_ctx_get_conf_ctx(msg_ctx, env);
                    if(conf_ctx)
                    {
                        axis2_conf_t *conf = NULL;
                        conf = axis2_conf_ctx_get_conf(conf_ctx, env);
                        if(conf)
                        {
                            svc = axis2_conf_get_svc(conf, env, url_tokens[0]);
                            if(svc)
                                AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI,
                                    "Service found using target endpoint address");
                        }
                    }
                    AXIS2_FREE(env->allocator, url_tokens[0]);

                    if(url_tokens[1])
                    {
                        AXIS2_FREE(env->allocator, url_tokens[1]);
                    }

                }
                AXIS2_FREE(env->allocator, url_tokens);
                url_tokens = NULL;
            }
        }
    }

    return svc;
}

axis2_op_t *AXIS2_CALL
axis2_req_uri_disp_find_op(
    axis2_msg_ctx_t * msg_ctx,
    const axutil_env_t * env,
    axis2_svc_t * svc)
{
    axis2_endpoint_ref_t *endpoint_ref = NULL;
    axis2_op_t *op = NULL;

    AXIS2_PARAM_CHECK(env->error, svc, NULL);

    if(axis2_msg_ctx_get_doing_rest(msg_ctx, env))
        return NULL;

    endpoint_ref = axis2_msg_ctx_get_to(msg_ctx, env);

    if(endpoint_ref)
    {
        const axis2_char_t *address = NULL;

        address = axis2_endpoint_ref_get_address(endpoint_ref, env);
        if(address)
        {
            axis2_char_t **url_tokens = NULL;

            url_tokens = axutil_parse_request_url_for_svc_and_op(env, address);

            if(url_tokens)
            {
                if(url_tokens[1])
                {
                    axutil_qname_t *op_qname = NULL;
                    AXIS2_LOG_DEBUG(
                        env->log,
                        AXIS2_LOG_SI,
                        "Checking for operation using \
                             target endpoint uri fragment : %s",
                        url_tokens[1]);
                    op_qname = axutil_qname_create(env, url_tokens[1], NULL, NULL);
                    op = axis2_svc_get_op_with_name(svc, env, axutil_qname_get_localpart(op_qname,
                        env));
                    axutil_qname_free(op_qname, env);
                    if(op)
                        AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI,
                            "Operation found using target endpoint uri fragment");
                }
                if(url_tokens[0])
                    AXIS2_FREE(env->allocator, url_tokens[0]);
                if(url_tokens[1])
                    AXIS2_FREE(env->allocator, url_tokens[1]);
                AXIS2_FREE(env->allocator, url_tokens);
            }
        }
    }

    return op;
}

axis2_status_t AXIS2_CALL
axis2_req_uri_disp_invoke(
    axis2_handler_t * handler,
    const axutil_env_t * env,
    struct axis2_msg_ctx * msg_ctx)
{
    axis2_msg_ctx_set_find_svc(msg_ctx, env, axis2_req_uri_disp_find_svc);
    axis2_msg_ctx_set_find_op(msg_ctx, env, axis2_req_uri_disp_find_op);
    return axis2_disp_find_svc_and_op(handler, env, msg_ctx);
}

