/*
 * 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 <qpid/dispatch/ctools.h>
#include "alloc.h"
#include <qpid/dispatch/buffer.h>
#include <qpid/dispatch/amqp.h>
#include "compose_private.h"
#include <memory.h>

ALLOC_DEFINE(qd_composite_t);
ALLOC_DEFINE(qd_composed_field_t);


static void bump_count(qd_composed_field_t *field)
{
    qd_composite_t *comp = DEQ_HEAD(field->fieldStack);
    if (comp)
        comp->count++;
}

static void bump_length(qd_composed_field_t *field,
                        uint32_t length)
{
    qd_composite_t *comp = DEQ_HEAD(field->fieldStack);
    if (comp)
        comp->length += length;
}


static void qd_insert(qd_composed_field_t *field, const uint8_t *seq, size_t len)
{
    qd_buffer_t    *buf  = DEQ_TAIL(field->buffers);
    qd_composite_t *comp = DEQ_HEAD(field->fieldStack);

    while (len > 0) {
        if (buf == 0 || qd_buffer_capacity(buf) == 0) {
            buf = qd_buffer();
            if (buf == 0)
                return;
            DEQ_INSERT_TAIL(field->buffers, buf);
        }

        size_t to_copy = qd_buffer_capacity(buf);
        if (to_copy > len)
            to_copy = len;
        memcpy(qd_buffer_cursor(buf), seq, to_copy);
        qd_buffer_insert(buf, to_copy);
        len -= to_copy;
        seq += to_copy;
        if (comp)
            comp->length += to_copy;
    }
}


static void qd_insert_8(qd_composed_field_t *field, uint8_t value)
{
    qd_insert(field, &value, 1);
}


static void qd_insert_32(qd_composed_field_t *field, uint32_t value)
{
    uint8_t buf[4];
    buf[0] = (uint8_t) ((value & 0xFF000000) >> 24);
    buf[1] = (uint8_t) ((value & 0x00FF0000) >> 16);
    buf[2] = (uint8_t) ((value & 0x0000FF00) >> 8);
    buf[3] = (uint8_t)  (value & 0x000000FF);
    qd_insert(field, buf, 4);
}


static void qd_insert_64(qd_composed_field_t *field, uint64_t value)
{
    uint8_t buf[8];
    buf[0] = (uint8_t) ((value & 0xFF00000000000000L) >> 56);
    buf[1] = (uint8_t) ((value & 0x00FF000000000000L) >> 48);
    buf[2] = (uint8_t) ((value & 0x0000FF0000000000L) >> 40);
    buf[3] = (uint8_t) ((value & 0x000000FF00000000L) >> 32);
    buf[4] = (uint8_t) ((value & 0x00000000FF000000L) >> 24);
    buf[5] = (uint8_t) ((value & 0x0000000000FF0000L) >> 16);
    buf[6] = (uint8_t) ((value & 0x000000000000FF00L) >> 8);
    buf[7] = (uint8_t)  (value & 0x00000000000000FFL);
    qd_insert(field, buf, 8);
}


static void qd_overwrite(qd_buffer_t **buf, size_t *cursor, uint8_t value)
{
    while (*buf) {
        if (*cursor >= qd_buffer_size(*buf)) {
            *buf = (*buf)->next;
            *cursor = 0;
        } else {
            qd_buffer_base(*buf)[*cursor] = value;
            (*cursor)++;
            return;
        }
    }
}


static void qd_overwrite_32(qd_field_location_t *field, uint32_t value)
{
    qd_buffer_t *buf    = field->buffer;
    size_t       cursor = field->offset;

    qd_overwrite(&buf, &cursor, (uint8_t) ((value & 0xFF000000) >> 24));
    qd_overwrite(&buf, &cursor, (uint8_t) ((value & 0x00FF0000) >> 16));
    qd_overwrite(&buf, &cursor, (uint8_t) ((value & 0x0000FF00) >> 8));
    qd_overwrite(&buf, &cursor, (uint8_t)  (value & 0x000000FF));
}


static void qd_compose_start_composite(qd_composed_field_t *field, int isMap)
{
    if (isMap)
        qd_insert_8(field, QD_AMQP_MAP32);
    else
        qd_insert_8(field, QD_AMQP_LIST32);

    //
    // Push a composite descriptor on the field stack
    //
    qd_composite_t *comp = new_qd_composite_t();
    DEQ_ITEM_INIT(comp);
    comp->isMap = isMap;

    //
    // Mark the current location to later overwrite the length
    //
    comp->length_location.buffer = DEQ_TAIL(field->buffers);
    comp->length_location.offset = qd_buffer_size(comp->length_location.buffer);
    comp->length_location.length = 4;
    comp->length_location.parsed = 1;

    qd_insert(field, (const uint8_t*) "\x00\x00\x00\x00", 4);

    //
    // Mark the current location to later overwrite the count
    //
    comp->count_location.buffer = DEQ_TAIL(field->buffers);
    comp->count_location.offset = qd_buffer_size(comp->count_location.buffer);
    comp->count_location.length = 4;
    comp->count_location.parsed = 1;

    qd_insert(field, (const uint8_t*) "\x00\x00\x00\x00", 4);

    comp->length = 4; // Include the length of the count field
    comp->count = 0;

    DEQ_INSERT_HEAD(field->fieldStack, comp);
}


static void qd_compose_end_composite(qd_composed_field_t *field)
{
    qd_composite_t *comp = DEQ_HEAD(field->fieldStack);
    assert(comp);

    qd_overwrite_32(&comp->length_location, comp->length);
    qd_overwrite_32(&comp->count_location,  comp->count);

    DEQ_REMOVE_HEAD(field->fieldStack);

    //
    // If there is an enclosing composite, update its length and count
    //
    qd_composite_t *enclosing = DEQ_HEAD(field->fieldStack);
    if (enclosing) {
        enclosing->length += (comp->length - 4); // the length and count were already accounted for
        enclosing->count++;
    }

    free_qd_composite_t(comp);
}


qd_composed_field_t *qd_compose_subfield(qd_composed_field_t *extend)
{
    qd_composed_field_t *field = extend;

    if (field) {
        assert(DEQ_SIZE(field->fieldStack) == 0);
    } else {
        field = new_qd_composed_field_t();
        if (!field)
            return 0;

        DEQ_INIT(field->buffers);
        DEQ_INIT(field->fieldStack);
    }

    return field;
}


qd_composed_field_t *qd_compose(uint64_t performative, qd_composed_field_t *extend)
{
    qd_composed_field_t *field = qd_compose_subfield(extend);

    if (field) {
        qd_insert_8(field, 0x00);
        qd_compose_insert_ulong(field, performative);
    }

    return field;
}


void qd_compose_free(qd_composed_field_t *field)
{
    if (!field) return;
    qd_buffer_t *buf = DEQ_HEAD(field->buffers);
    while (buf) {
        DEQ_REMOVE_HEAD(field->buffers);
        qd_buffer_free(buf);
        buf = DEQ_HEAD(field->buffers);
    }

    qd_composite_t *comp = DEQ_HEAD(field->fieldStack);
    while (comp) {
        DEQ_REMOVE_HEAD(field->fieldStack);
        free_qd_composite_t(comp);
        comp = DEQ_HEAD(field->fieldStack);
    }

    free_qd_composed_field_t(field);
}


void qd_compose_start_list(qd_composed_field_t *field)
{
    qd_compose_start_composite(field, 0);
}


void qd_compose_end_list(qd_composed_field_t *field)
{
    qd_compose_end_composite(field);
}


void qd_compose_empty_list(qd_composed_field_t *field)
{
    qd_insert_8(field, QD_AMQP_LIST0);
    bump_count(field);
}


void qd_compose_start_map(qd_composed_field_t *field)
{
    qd_compose_start_composite(field, 1);
}


void qd_compose_end_map(qd_composed_field_t *field)
{
    qd_compose_end_composite(field);
}


void qd_compose_insert_null(qd_composed_field_t *field)
{
    qd_insert_8(field, QD_AMQP_NULL);
    bump_count(field);
}


void qd_compose_insert_bool(qd_composed_field_t *field, int value)
{
    qd_insert_8(field, value ? QD_AMQP_TRUE : QD_AMQP_FALSE);
    bump_count(field);
}


void qd_compose_insert_uint(qd_composed_field_t *field, uint32_t value)
{
    if (value == 0) {
        qd_insert_8(field, QD_AMQP_UINT0);
    } else if (value < 256) {
        qd_insert_8(field, QD_AMQP_SMALLUINT);
        qd_insert_8(field, (uint8_t) value);
    } else {
        qd_insert_8(field, QD_AMQP_UINT);
        qd_insert_32(field, value);
    }
    bump_count(field);
}


void qd_compose_insert_ulong(qd_composed_field_t *field, uint64_t value)
{
    if (value == 0) {
        qd_insert_8(field, QD_AMQP_ULONG0);
    } else if (value < 256) {
        qd_insert_8(field, QD_AMQP_SMALLULONG);
        qd_insert_8(field, (uint8_t) value);
    } else {
        qd_insert_8(field, QD_AMQP_ULONG);
        qd_insert_64(field, value);
    }
    bump_count(field);
}


void qd_compose_insert_int(qd_composed_field_t *field, int32_t value)
{
    if (value >= -128 && value <= 127) {
        qd_insert_8(field, QD_AMQP_SMALLINT);
        qd_insert_8(field, (uint8_t) value);
    } else {
        qd_insert_8(field, QD_AMQP_INT);
        qd_insert_32(field, (uint32_t) value);
    }
    bump_count(field);
}


void qd_compose_insert_long(qd_composed_field_t *field, int64_t value)
{
    if (value >= -128 && value <= 127) {
        qd_insert_8(field, QD_AMQP_SMALLLONG);
        qd_insert_8(field, (uint8_t) value);
    } else {
        qd_insert_8(field, QD_AMQP_LONG);
        qd_insert_64(field, (uint64_t) value);
    }
    bump_count(field);
}


void qd_compose_insert_timestamp(qd_composed_field_t *field, uint64_t value)
{
    qd_insert_8(field, QD_AMQP_TIMESTAMP);
    qd_insert_64(field, value);
    bump_count(field);
}


void qd_compose_insert_uuid(qd_composed_field_t *field, const uint8_t *value)
{
    qd_insert_8(field, QD_AMQP_UUID);
    qd_insert(field, value, 16);
    bump_count(field);
}


void qd_compose_insert_binary(qd_composed_field_t *field, const uint8_t *value, uint32_t len)
{
    if (len < 256) {
        qd_insert_8(field, QD_AMQP_VBIN8);
        qd_insert_8(field, (uint8_t) len);
    } else {
        qd_insert_8(field, QD_AMQP_VBIN32);
        qd_insert_32(field, len);
    }
    qd_insert(field, value, len);
    bump_count(field);
}


void qd_compose_insert_binary_buffers(qd_composed_field_t *field, qd_buffer_list_t *buffers)
{
    qd_buffer_t *buf = DEQ_HEAD(*buffers);
    uint32_t     len = 0;

    //
    // Calculate the size of the binary field to be appended.
    //
    while (buf) {
        len += qd_buffer_size(buf);
        buf = DEQ_NEXT(buf);
    }

    //
    // Supply the appropriate binary tag for the length.
    //
    if (len < 256) {
        qd_insert_8(field, QD_AMQP_VBIN8);
        qd_insert_8(field, (uint8_t) len);
    } else {
        qd_insert_8(field, QD_AMQP_VBIN32);
        qd_insert_32(field, len);
    }

    //
    // Move the supplied buffers to the tail of the field's buffer list.
    //
    buf = DEQ_HEAD(*buffers);
    while (buf) {
        DEQ_REMOVE_HEAD(*buffers);
        DEQ_INSERT_TAIL(field->buffers, buf);
        buf = DEQ_HEAD(*buffers);
    }
    bump_length(field, len);
    bump_count(field);
}


void qd_compose_insert_string(qd_composed_field_t *field, const char *value)
{
    uint32_t len = strlen(value);

    if (len < 256) {
        qd_insert_8(field, QD_AMQP_STR8_UTF8);
        qd_insert_8(field, (uint8_t) len);
    } else {
        qd_insert_8(field, QD_AMQP_STR32_UTF8);
        qd_insert_32(field, len);
    }
    qd_insert(field, (const uint8_t*) value, len);
    bump_count(field);
}


void qd_compose_insert_string_iterator(qd_composed_field_t *field, qd_field_iterator_t *iter)
{
    uint32_t len = 0;

    qd_field_iterator_reset(iter);
    while (!qd_field_iterator_end(iter)) {
        qd_field_iterator_octet(iter);
        len++;
    }

    qd_field_iterator_reset(iter);
    if (len < 256) {
        qd_insert_8(field, QD_AMQP_STR8_UTF8);
        qd_insert_8(field, (uint8_t) len);
    } else {
        qd_insert_8(field, QD_AMQP_STR32_UTF8);
        qd_insert_32(field, len);
    }

    while (!qd_field_iterator_end(iter)) {
        uint8_t octet = qd_field_iterator_octet(iter);
        qd_insert_8(field, octet);
    }

    bump_count(field);
}


void qd_compose_insert_symbol(qd_composed_field_t *field, const char *value)
{
    uint32_t len = strlen(value);

    if (len < 256) {
        qd_insert_8(field, QD_AMQP_SYM8);
        qd_insert_8(field, (uint8_t) len);
    } else {
        qd_insert_8(field, QD_AMQP_SYM32);
        qd_insert_32(field, len);
    }
    qd_insert(field, (const uint8_t*) value, len);
    bump_count(field);
}


void qd_compose_insert_typed_iterator(qd_composed_field_t *field, qd_field_iterator_t *iter)
{
    while (!qd_field_iterator_end(iter)) {
        uint8_t octet = qd_field_iterator_octet(iter);
        qd_insert_8(field, octet);
    }

    bump_count(field);
}


qd_buffer_list_t *qd_compose_buffers(qd_composed_field_t *field)
{
    return &field->buffers;
}

void qd_compose_take_buffers(qd_composed_field_t *field,
                             qd_buffer_list_t *list)
{
    // assumption: extracting partially built containers is wrong:
    assert(DEQ_SIZE(field->fieldStack) == 0);
    *list = *qd_compose_buffers(field);
    DEQ_INIT(field->buffers); // Zero out the linkage to the now moved buffers.
}

void qd_compose_insert_buffers(qd_composed_field_t *field,
                               qd_buffer_list_t *list)
{
    uint32_t len = qd_buffer_list_length(list);
    if (len) {
        DEQ_APPEND(field->buffers, *list);
        bump_length(field, len);
        bump_count(field);
    }
}

