/*
 * 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 <axutil_http_chunked_stream.h>
#include <axutil_string.h>
#include <string.h>
#include <stdlib.h>

#define AXIS2_HTTP_CRLF "\r\n"

struct axutil_http_chunked_stream
{
    axutil_stream_t *stream;
    int current_chunk_size;
    int unread_len;
    axis2_bool_t end_of_chunks;
    axis2_bool_t chunk_started;
};

static axis2_status_t
axutil_http_chunked_stream_start_chunk(
    axutil_http_chunked_stream_t * chunked_stream,
    const axutil_env_t *env);

AXIS2_EXTERN axutil_http_chunked_stream_t *AXIS2_CALL
axutil_http_chunked_stream_create(
    const axutil_env_t *env,
    axutil_stream_t *stream)
{
    axutil_http_chunked_stream_t *chunked_stream = NULL;
    AXIS2_PARAM_CHECK(env->error, stream, NULL);

    chunked_stream = (axutil_http_chunked_stream_t *)AXIS2_MALLOC(env->allocator,
        sizeof(axutil_http_chunked_stream_t));
    if(!chunked_stream)
    {
        AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
        AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Out of memory");
        return NULL;
    }
    chunked_stream->stream = stream;
    chunked_stream->current_chunk_size = -1;
    chunked_stream->unread_len = -1;
    chunked_stream->end_of_chunks = AXIS2_FALSE;
    chunked_stream->chunk_started = AXIS2_FALSE;

    return chunked_stream;
}

AXIS2_EXTERN void AXIS2_CALL
axutil_http_chunked_stream_free(
    axutil_http_chunked_stream_t *chunked_stream,
    const axutil_env_t *env)
{
    AXIS2_FREE(env->allocator, chunked_stream);
}

AXIS2_EXTERN int AXIS2_CALL
axutil_http_chunked_stream_read(
    axutil_http_chunked_stream_t *chunked_stream,
    const axutil_env_t *env,
    void *buffer,
    size_t count)
{
    int len = -1;
    int yet_to_read = 0;
    axutil_stream_t *stream = chunked_stream->stream;

    if(!buffer)
    {
        return -1;
    }
    if(!stream)
    {
        AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NULL_STREAM_IN_CHUNKED_STREAM, AXIS2_FAILURE);
        return -1;
    }
    if(AXIS2_TRUE == chunked_stream->end_of_chunks)
    {
        return 0;
    }
    if(AXIS2_FALSE == chunked_stream->chunk_started)
    {
        axutil_http_chunked_stream_start_chunk(chunked_stream, env);
    }
    yet_to_read = (int)count;
    /* We are sure that the difference lies within the int range */
    while(AXIS2_FALSE == chunked_stream->end_of_chunks && yet_to_read > 0)
    {
        if(chunked_stream->unread_len < yet_to_read)
        {
            len = axutil_stream_read(chunked_stream->stream, env, (axis2_char_t *)buffer + count
                - yet_to_read, chunked_stream->unread_len);
            yet_to_read -= len;
            chunked_stream->unread_len -= len;
            if(chunked_stream->unread_len <= 0)
            {
                axutil_http_chunked_stream_start_chunk(chunked_stream, env);
            }
        }
        else
        {
            len = axutil_stream_read(chunked_stream->stream, env, (axis2_char_t *)buffer + count
                - yet_to_read, yet_to_read);
            yet_to_read -= len;
            chunked_stream->unread_len -= len;
        }
    }
    return ((int)count - yet_to_read);
    /* We are sure that the difference lies within the int range */
}

AXIS2_EXTERN int AXIS2_CALL
axutil_http_chunked_stream_write(
    axutil_http_chunked_stream_t *chunked_stream,
    const axutil_env_t *env,
    const void *buffer,
    size_t count)
{
    axutil_stream_t *stream = chunked_stream->stream;
    int len = -1;
    axis2_char_t tmp_buf[10];

    if(!buffer)
    {
        return -1;
    }
    if(!stream)
    {
        AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NULL_STREAM_IN_CHUNKED_STREAM, AXIS2_FAILURE);
        return -1;
    }
    sprintf(tmp_buf, "%x%s", (unsigned int)count, AXIS2_HTTP_CRLF);
    axutil_stream_write(stream, env, tmp_buf, axutil_strlen(tmp_buf));
    len = axutil_stream_write(stream, env, buffer, count);
    axutil_stream_write(stream, env, AXIS2_HTTP_CRLF, 2);
    return len;
}

AXIS2_EXTERN int AXIS2_CALL
axutil_http_chunked_stream_get_current_chunk_size(
    const axutil_http_chunked_stream_t *chunked_stream,
    const axutil_env_t *env)
{
    return chunked_stream->current_chunk_size;
}

static axis2_status_t
axutil_http_chunked_stream_start_chunk(
    axutil_http_chunked_stream_t *chunked_stream,
    const axutil_env_t *env)
{
    axis2_char_t tmp_buf[3] = "";
    axis2_char_t str_chunk_len[512] = "";
    axis2_char_t *tmp = NULL;
    int read = -1;

    /* remove the last CRLF of the previous chunk if any */
    if(AXIS2_TRUE == chunked_stream->chunk_started)
    {
        read = axutil_stream_read(chunked_stream->stream, env, tmp_buf, 2);
        chunked_stream->chunk_started = AXIS2_FALSE;
    }
    /* read the len and chunk extension */
    while((read = axutil_stream_read(chunked_stream->stream, env, tmp_buf, 1)) > 0)
    {
        tmp_buf[read] = '\0';
        strcat(str_chunk_len, tmp_buf);
        if(0 != strstr(str_chunk_len, AXIS2_HTTP_CRLF))
        {
            break;
        }
    }
    /* check whether we have extensions */
    tmp = strchr(str_chunk_len, ';');
    if(tmp)
    {
        /* we don't use extensions right now */
        *tmp = '\0';
    }
    chunked_stream->current_chunk_size = strtol(str_chunk_len, NULL, 16);
    if(0 == chunked_stream->current_chunk_size)
    {
        /* Read the last CRLF */
        read = axutil_stream_read(chunked_stream->stream, env, tmp_buf, 2);
        chunked_stream->end_of_chunks = AXIS2_TRUE;
    }
    else
    {
        chunked_stream->chunk_started = AXIS2_TRUE;
        chunked_stream->unread_len = chunked_stream->current_chunk_size;
    }
    return AXIS2_SUCCESS;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
axutil_http_chunked_stream_write_last_chunk(
    axutil_http_chunked_stream_t *chunked_stream,
    const axutil_env_t *env)
{
    axutil_stream_t *stream = NULL;

    stream = chunked_stream->stream;
    if(axutil_stream_write(stream, env, "0\r\n\r\n", 5) == 5)
    {
        return AXIS2_SUCCESS;
    }
    return AXIS2_FAILURE;
}

AXIS2_EXTERN axis2_bool_t AXIS2_CALL
axutil_http_chunked_stream_get_end_of_chunks(
    axutil_http_chunked_stream_t *chunked_stream,
    const axutil_env_t *env)
{
    return chunked_stream->end_of_chunks;
}

