/*
 * 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_http_simple_response.h>
#include <axis2_http_transport.h>
#include <axutil_string.h>
#include <stdio.h>
#include <string.h>
#include <axutil_types.h>
#include <axiom_mime_part.h>

#define AXIS2_HTTP_SIMPLE_RESPONSE_READ_SIZE 2048

struct axis2_http_simple_response
{
    axis2_http_status_line_t *status_line;
    axutil_array_list_t *header_group;
    axutil_stream_t *stream;
    axis2_bool_t stream_owned;
    axutil_array_list_t *mime_parts;
    axis2_char_t *mtom_sending_callback_name;
};

AXIS2_EXTERN axis2_http_simple_response_t *AXIS2_CALL
axis2_http_simple_response_create(
    const axutil_env_t * env,
    axis2_http_status_line_t * status_line,
    const axis2_http_header_t ** http_headers,
    const axis2_ssize_t http_hdr_count,
    axutil_stream_t * content)
{
    axis2_http_simple_response_t *ret = NULL;
    ret = axis2_http_simple_response_create_default(env);
    if(!ret)
    {
        AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "axis2 http simple response creation failed");
        return NULL;
    }

    ret->status_line = status_line;
    if(http_hdr_count > 0 && http_headers)
    {
        int i = 0;
        ret->header_group = axutil_array_list_create(env, http_hdr_count);

        for(i = 0; i < (int)http_hdr_count; i++)
        /* We are sure that the difference lies within the int range */
        {
            axutil_array_list_add(ret->header_group, env, (void *)http_headers[i]);
        }
    }
    ret->stream = content;
    ret->stream_owned = AXIS2_FALSE;
    return ret;
}

AXIS2_EXTERN axis2_http_simple_response_t *AXIS2_CALL
axis2_http_simple_response_create_default(
    const axutil_env_t * env)
{
    axis2_http_simple_response_t *simple_response = NULL;
    simple_response = (axis2_http_simple_response_t *)AXIS2_MALLOC(env->allocator,
        sizeof(axis2_http_simple_response_t));
    if(!simple_response)
    {
        AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
        return NULL;
    }

    memset((void *)simple_response, 0, sizeof(axis2_http_simple_response_t));
    return simple_response;
}

void AXIS2_CALL
axis2_http_simple_response_free(
    axis2_http_simple_response_t * simple_response,
    const axutil_env_t * env)
{
    if(simple_response->status_line)
    {
        axis2_http_status_line_free(simple_response->status_line, env);
    }

    if(simple_response->header_group)
    {
        int i = 0;
        for(i = 0; i < axutil_array_list_size(simple_response->header_group, env); i++)
        {
            void *tmp = NULL;
            tmp = axutil_array_list_get(simple_response-> header_group, env, i);
            if(tmp)
            {
                axis2_http_header_free((axis2_http_header_t *)tmp, env);
            }
        }
        axutil_array_list_free(simple_response->header_group, env);
    }

    if(simple_response->mime_parts)
    {
        int i = 0;
        for(i = 0; i < axutil_array_list_size(simple_response->mime_parts, env); i++)
        {
            void *mime_part = NULL;
            mime_part = axutil_array_list_get(simple_response->mime_parts, env, i);
            if(mime_part)
            {
                axiom_mime_part_free((axiom_mime_part_t *)mime_part, env);
            }
        }
        axutil_array_list_free(simple_response->mime_parts, env);
    }

     /* Only free stream if we created it. */
    if (simple_response->stream_owned == AXIS2_TRUE)
    {
        axutil_stream_free(simple_response->stream, env);
        simple_response->stream = NULL;
        simple_response->stream_owned = AXIS2_FALSE;
    }

    AXIS2_FREE(env->allocator, simple_response);
}

axis2_status_t AXIS2_CALL
axis2_http_simple_response_set_status_line(
    struct axis2_http_simple_response * simple_response,
    const axutil_env_t * env,
    const axis2_char_t * http_ver,
    const int status_code,
    const axis2_char_t * phrase)
{
    if(!http_ver || !phrase || !status_code)
    {
        AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "invalid parameter given");
        return AXIS2_FAILURE;
    }

    if(simple_response->status_line)
    {
        axis2_http_status_line_free(simple_response->status_line, env);
    }

    simple_response->status_line = axis2_http_status_line_create_with_values(
        env, http_ver, status_code, phrase);
    if(!simple_response->status_line)
    {
        AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
            "http status line creation failed for string %s %3d %s", http_ver, status_code, phrase);
        return AXIS2_FAILURE;
    }
    return AXIS2_SUCCESS;
}

axis2_char_t *AXIS2_CALL
axis2_http_simple_response_get_phrase(
    axis2_http_simple_response_t * simple_response,
    const axutil_env_t * env)
{
    if(!(simple_response->status_line))
    {
        AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
            "axis2 simple response , status line is not available");
        return NULL;
    }

    return axis2_http_status_line_get_reason_phrase(simple_response-> status_line, env);
}

int AXIS2_CALL
axis2_http_simple_response_get_status_code(
    axis2_http_simple_response_t * simple_response,
    const axutil_env_t * env)
{
    if(!(simple_response->status_line))
    {
        AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
            "axis2 simple response , status line is not available");
        return -1;
    }
    return axis2_http_status_line_get_status_code(simple_response->status_line, env);
}

axis2_char_t *AXIS2_CALL
axis2_http_simple_response_get_http_version(
    axis2_http_simple_response_t * simple_response,
    const axutil_env_t * env)
{
    if(!(simple_response->status_line))
    {
        AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
            "axis2 simple response , status line is not available");

        return NULL;
    }
    return axis2_http_status_line_get_http_version(simple_response->status_line, env);
}

axis2_status_t AXIS2_CALL
axis2_http_simple_response_set_http_version(
    axis2_http_simple_response_t * simple_response,
    const axutil_env_t * env,
    axis2_char_t *http_version)
{
    if(!(simple_response->status_line))
    {
        AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
            "axis2 simple response , status line is not available");

        return AXIS2_FAILURE;
    }
    axis2_http_status_line_set_http_version(simple_response->status_line, env, http_version);
    return AXIS2_SUCCESS;
}

axis2_char_t *AXIS2_CALL
axis2_http_simple_response_get_status_line(
    axis2_http_simple_response_t * simple_response,
    const axutil_env_t * env)
{

    if(!(simple_response->status_line))
    {
        AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
            "axis2 simple response , status line is not available");

        return NULL;
    }
    return axis2_http_status_line_to_string(simple_response->status_line, env);
}

AXIS2_EXTERN axutil_array_list_t *AXIS2_CALL
axis2_http_simple_response_get_headers(
    axis2_http_simple_response_t * simple_response,
    const axutil_env_t * env)
{
    return simple_response->header_group;
}

axutil_array_list_t *AXIS2_CALL
axis2_http_simple_response_extract_headers(
    axis2_http_simple_response_t * simple_response,
    const axutil_env_t * env)
{
    axutil_array_list_t *temp = NULL;
    temp = simple_response->header_group;
    if(temp)
    {
        simple_response->header_group = NULL;
    }
    return temp;
}

axis2_http_header_t *AXIS2_CALL
axis2_http_simple_response_get_first_header(
    axis2_http_simple_response_t * simple_response,
    const axutil_env_t * env,
    const axis2_char_t * str)
{
    axis2_http_header_t *tmp_header = NULL;
    axis2_char_t *tmp_name = NULL;
    int i = 0;
    int count = 0;
    axutil_array_list_t *header_group = NULL;

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

    header_group = simple_response->header_group;
    if(!simple_response->header_group)
    {
        AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "axis2 simple response , headers not available");
        return NULL;
    }

    if(0 == axutil_array_list_size(header_group, env))
    {
        AXIS2_LOG_WARNING(env->log, AXIS2_LOG_SI, "axis2 simple response , contains zero headers");

        return NULL;
    }

    count = axutil_array_list_size(header_group, env);

    for(i = 0; i < count; i++)
    {
        tmp_header = (axis2_http_header_t *)axutil_array_list_get(header_group, env, i);
        tmp_name = axis2_http_header_get_name(tmp_header, env);
        if(0 == axutil_strcasecmp(str, tmp_name))
        {
            return tmp_header;
        }
    }
    return NULL;

}

axis2_status_t AXIS2_CALL
axis2_http_simple_response_remove_headers(
    axis2_http_simple_response_t * simple_response,
    const axutil_env_t * env,
    const axis2_char_t * str)
{
    axutil_array_list_t *header_group = NULL;
    int i = 0;
    int count = 0;

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

    header_group = simple_response->header_group;
    if(!header_group)
    {
        /* Even though we couldn't complete the op, we are sure that the
         * required header is no more in the request. So we can proceed without a
         * problem.
         */
        return AXIS2_SUCCESS;
    }

    count = axutil_array_list_size(header_group, env);
    for(i = 0; i < count; i++)
    {
        axis2_http_header_t *tmp_header = NULL;
        axis2_char_t *tmp_name = NULL;
        tmp_header = (axis2_http_header_t *)axutil_array_list_get(header_group, env, i);
        tmp_name = axis2_http_header_get_name(tmp_header, env);
        if(0 == axutil_strcasecmp(str, tmp_name))
        {
            axis2_http_header_free(tmp_header, env);
            axutil_array_list_remove(header_group, env, i);
            break;
        }
    }
    return AXIS2_SUCCESS;
}

axis2_status_t AXIS2_CALL
axis2_http_simple_response_set_header(
    axis2_http_simple_response_t * simple_response,
    const axutil_env_t * env,
    axis2_http_header_t * header)
{
    int i = 0;
    int count = 0;
    axutil_array_list_t *header_group = NULL;

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

    if(!simple_response->header_group)
    {
        simple_response->header_group = axutil_array_list_create(env, 10);
        axutil_array_list_add(simple_response->header_group, env, header);
        return AXIS2_SUCCESS;
    }

    /* If a header with the same name exists search and remove the old header */
    header_group = simple_response->header_group;
    count = axutil_array_list_size(header_group, env);
    for(i = 0; i < count; i++)
    {
        axis2_http_header_t *tmp_header = NULL;
        axis2_char_t *tmp_name = NULL;
        tmp_header = (axis2_http_header_t *)axutil_array_list_get(header_group, env, i);
        tmp_name = axis2_http_header_get_name(tmp_header, env);
        if(0 == axutil_strcasecmp(axis2_http_header_get_name(header, env), tmp_name))
        {
            axis2_http_header_free(tmp_header, env);
            axutil_array_list_set(header_group, env, i, header);
            return AXIS2_SUCCESS;
        }
    }

    /* if header is not found, then we have to add it */
    axutil_array_list_add(header_group, env, header);
    return AXIS2_SUCCESS;
}

const axis2_char_t *AXIS2_CALL
axis2_http_simple_response_get_charset(
    axis2_http_simple_response_t * simple_response,
    const axutil_env_t * env)
{
    axis2_http_header_t *tmp_header = NULL;

    tmp_header = axis2_http_simple_response_get_first_header(simple_response, env,
        AXIS2_HTTP_HEADER_CONTENT_TYPE);
    if(tmp_header)
    {
        axis2_char_t *value = axis2_http_header_get_value(tmp_header, env);
        axis2_char_t *charset = (axis2_char_t *)strstr((char *)value,
            (char *)AXIS2_HTTP_CHAR_SET_ENCODING);
        if(charset)
        {
            charset = strchr((char *)charset, AXIS2_EQ);
            return charset;
        }
    }

    return AXIS2_HTTP_DEFAULT_CONTENT_CHARSET;
}

axis2_ssize_t AXIS2_CALL
axis2_http_simple_response_get_content_length(
    axis2_http_simple_response_t * simple_response,
    const axutil_env_t * env)
{
    axis2_http_header_t *tmp_header = NULL;
    int error_return = -1;

    tmp_header = axis2_http_simple_response_get_first_header(simple_response, env,
        AXIS2_HTTP_HEADER_CONTENT_LENGTH);
    if(tmp_header)
    {
        return AXIS2_ATOI(axis2_http_header_get_value(tmp_header, env));
    }
    return error_return;
}

const axis2_char_t *AXIS2_CALL
axis2_http_simple_response_get_content_type(
    axis2_http_simple_response_t * simple_response,
    const axutil_env_t * env)
{
    axis2_http_header_t *tmp_header = NULL;

    tmp_header = axis2_http_simple_response_get_first_header(simple_response, env,
        AXIS2_HTTP_HEADER_CONTENT_TYPE);
    if(tmp_header)
    {
        return axis2_http_header_get_value(tmp_header, env);
    }

    return AXIS2_HTTP_HEADER_ACCEPT_TEXT_PLAIN;
}

axis2_status_t AXIS2_CALL
axis2_http_simple_response_set_body_string(
    axis2_http_simple_response_t * simple_response,
    const axutil_env_t * env,
    axis2_char_t * str)
{
    axutil_stream_t *body_stream = NULL;

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

    body_stream = simple_response->stream;
    if(!body_stream)
    {
        body_stream = axutil_stream_create_basic(env);
        if(!body_stream)
        {
            AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "unable to create basic stream for string %s",
                str);
            return AXIS2_FAILURE;
        }
        simple_response->stream = body_stream;
	simple_response->stream_owned = AXIS2_TRUE;
    }
    axutil_stream_write(body_stream, env, str, axutil_strlen(str));
    return AXIS2_SUCCESS;
}

axis2_status_t AXIS2_CALL
axis2_http_simple_response_set_body_stream(
    axis2_http_simple_response_t * simple_response,
    const axutil_env_t * env,
    axutil_stream_t * stream)
{
    /*
     * We don't free the stream
     * Problem in freeing is most of the time the stream doesn't belong
     * to the http_simple_response
     */
    simple_response->stream = stream;
    return AXIS2_SUCCESS;
}

axutil_stream_t *AXIS2_CALL
axis2_http_simple_response_get_body(
    axis2_http_simple_response_t * simple_response,
    const axutil_env_t * env)
{
    return simple_response->stream;
}

axis2_ssize_t AXIS2_CALL
axis2_http_simple_response_get_body_bytes(
    axis2_http_simple_response_t * simple_response,
    const axutil_env_t * env,
    axis2_char_t ** buffer)
{
    axutil_stream_t *tmp_stream = NULL;
    axis2_bool_t loop_state = AXIS2_TRUE;
    int return_size = -1;

    if(!simple_response->stream)
    {
        AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NULL_BODY, AXIS2_FAILURE);
        return return_size;
    }
    tmp_stream = axutil_stream_create_basic(env);
    while(loop_state)
    {
        int read = 0;
        int write = 0;
        char buf[AXIS2_HTTP_SIMPLE_RESPONSE_READ_SIZE];

        read = axutil_stream_read(simple_response->stream, env, buf,
            AXIS2_HTTP_SIMPLE_RESPONSE_READ_SIZE);
        if(read < 0)
        {
            break;
        }
        write = axutil_stream_write(tmp_stream, env, buf, read);
        if(write < (AXIS2_HTTP_SIMPLE_RESPONSE_READ_SIZE - 1))
        {
            break;
        }
    }
    return_size = axutil_stream_get_len(tmp_stream, env);

    if(return_size > 0)
    {
        *buffer = (char *)AXIS2_MALLOC(env->allocator, sizeof(char) * (return_size + 1));

        if(!buffer)
        {
            AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
            return -1;
        }

        return_size = axutil_stream_read(tmp_stream, env, *buffer, return_size + 1);
    }
    axutil_stream_free(tmp_stream, env);
    return return_size;
}

axis2_bool_t AXIS2_CALL
axis2_http_simple_response_contains_header(
    axis2_http_simple_response_t * simple_response,
    const axutil_env_t * env,
    const axis2_char_t * name)
{
    axis2_char_t *header_name = NULL;
    int count = 0;
    int i = 0;

    AXIS2_PARAM_CHECK(env->error, name, AXIS2_FAILURE);
    if(!simple_response->header_group)
    {
        AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "axis2 simple response , headers not available");
        return AXIS2_FALSE;
    }

    count = axutil_array_list_size(simple_response->header_group, env);
    if(0 == count)
    {
        AXIS2_LOG_WARNING(env->log, AXIS2_LOG_SI, "axis2 simple response , contains zero headers");
        return AXIS2_FALSE;
    }

    for(i = 0; i < count; i++)
    {
        axis2_http_header_t *header = (axis2_http_header_t *)axutil_array_list_get(
            simple_response->header_group, env, i);
        header_name = axis2_http_header_get_name(header, env);
        if(0 == axutil_strcasecmp(name, header_name))
        {
            return AXIS2_TRUE;
        }
    }
    return AXIS2_FALSE;
}

AXIS2_EXTERN axutil_array_list_t *AXIS2_CALL
axis2_http_simple_response_get_mime_parts(
    axis2_http_simple_response_t * simple_response,
    const axutil_env_t * env)
{

    return simple_response->mime_parts;

}

void AXIS2_EXTERN AXIS2_CALL
axis2_http_simple_response_set_mime_parts(
    axis2_http_simple_response_t * simple_response,
    const axutil_env_t * env,
    axutil_array_list_t *mime_parts)
{

    simple_response->mime_parts = mime_parts;

}

AXIS2_EXTERN axis2_char_t *AXIS2_CALL
axis2_http_simple_response_get_mtom_sending_callback_name(
    axis2_http_simple_response_t * simple_response,
    const axutil_env_t * env)
{
    return simple_response->mtom_sending_callback_name;
}

void AXIS2_EXTERN AXIS2_CALL
axis2_http_simple_response_set_mtom_sending_callback_name(
    axis2_http_simple_response_t * simple_response,
    const axutil_env_t * env,
    axis2_char_t *mtom_sending_callback_name)
{
    simple_response->mtom_sending_callback_name =
    mtom_sending_callback_name;
}
