#define QUEUE_C
// Author: Ershov V.
// Modified: Sychov. A / 12/2020
#include "app/queue/queue.h"

int queue_pushback(queue_t * self, queue_record_t * record)
{
    my_assert(record);
    my_assert(self);
    RING_BUFFER_RC_TYPE freeSpace = ringbuf_free_space(self);
    if(freeSpace < record->size)
    {
        return QUEUE_RC_NO_MEMORY;
    }

    RING_BUFFER_RC_TYPE rc = ringbuf_write(self, (void *)record, record->size);
    my_assert(record->size == rc);
    (void)rc;

    return QUEUE_RC_NOERROR;
}

int queue_pushfront(queue_t * self, queue_record_t * record)
{
    my_assert(self);
    my_assert(record);
    RING_BUFFER_RC_TYPE freeSpace = ringbuf_free_space(self);
    if(freeSpace < record->size)
    {
        return QUEUE_RC_NO_MEMORY;
    }

    RING_BUFFER_RC_TYPE rc = ringbuf_write_front(self, (void *)record, record->size);
    my_assert(record->size == rc);
    (void)rc;

    return QUEUE_RC_NOERROR;
}

int queue_peek(const queue_t * self, queue_record_t * record, int16_t size)
{
    // Reading t struct first and getting size of whole
    // record struct. Then reading entire record struct.

    my_assert(self);
    my_assert(record);
    my_assert(sizeof(*record) <= size);

    RING_BUFFER_RC_TYPE rc = ringbuf_peek(self, (void *)record, sizeof(*record));
    my_assert(sizeof(*record) == rc);
    if(sizeof(*record) != rc)
    {
        return QUEUE_RC_EMPTY;
    }

    my_assert(record->size <= ringbuf_size(self));
    int16_t record_size = record->size;

    if(record_size > size)
    {
        return QUEUE_RC_NO_MEMORY;
    }

    rc = ringbuf_peek(self, (void *)record, record_size);
    my_assert(record_size == rc);
    if(record_size != rc)
    {
        return QUEUE_RC_INTERNAL_ERROR;
    }

    return record->size;
}

int queue_removefront(queue_t * self)
{
    my_assert(self);

    queue_record_t record;
    RING_BUFFER_RC_TYPE rc = ringbuf_peek(self, (void *)&record, sizeof(record));
    my_assert(0 <= rc);
    if(0 == rc)
    {
        return 0;
    }

    my_assert(record.size <= ringbuf_size(self));
    rc = ringbuf_erase(self, record.size);
    my_assert(0 <= rc);

    return rc;
}

