/*
 * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
 *
 * This software is dual-licensed to you under the MIT License (MIT) and
 * the Universal Permissive License (UPL). See the LICENSE file in the root
 * directory for license terms. You may choose either license, or both.
 */


#ifndef UTIL_ARRAY_QUEUE_H
#define UTIL_ARRAY_QUEUE_H

#include "iotcs.h"
#include "advanced/iotcs_message.h"

/**
 * @brief Common private header
 */

#ifdef __cplusplus
extern "C" {
#endif

    /**
     * @brief Returns 1 if queue is full; 0 otherwise.
     * @param array handle to the util_array_queue
     */
#define UTIL_ARRAY_QUEUE_IS_FULL(queue) ((queue)->capacity == (queue)->item_cnt)

    /**
     * @brief Returns 0 if queue is empty; 0 otherwise.
     * @param array handle to the util_array_queue
     */
#define UTIL_ARRAY_QUEUE_IS_EMPTY(queue) (0 == (queue)->item_cnt)


    /**
     * @brief Returns number of the items in the queue.
     * @param array handle to the util_array_queue
     */
#define UTIL_ARRAY_QUEUE_COUNT(queue) ((queue)->item_cnt)

    /**
     * @brief Returns queue capacity.
     * @param array handle to the util_array_queue
     */
#define UTIL_ARRAY_QUEUE_CAPACITY(queue) ((queue)->capacity)

    /**
     * @brief Array Queue structure.
     * @typedef util_array_queue
     */
    typedef struct {
        int push_idx;
        int pop_idx;
        int capacity;
        int item_cnt;
        size_t item_size;
        int8_t* buffer;
    } util_array_queue;

    typedef void* util_array_queue_item_addr;

    /**
     * @brief Creates a new util_array_queue.
     * @param queue pointer to the util_array_queue
     * @param capacity number of items in util_array_queue
     * @param item_size size of each item in bytes
     * @param buffer buffer to store data. Must have size (length)*item_size.
     */
    void util_array_queue_init(util_array_queue *queue, size_t capacity, size_t item_size, int8_t* buffer);

    /**
     * @brief Pushes new item to the queue.
     * @param queue handle to the util_array_queue
     * @param msg address of the message (item_size bytes will be copied)
     * @return IOTCS_RESULT_OK or IOTCS_RESULT_FAIL if these is no free space
     */
    iotcs_result util_array_queue_push(util_array_queue* queue, util_array_queue_item_addr msg);

    /**
     * @brief Pops item from the queue
     * @param queue handle to the util_array_queue
     * @param msg address of the message (item_size bytes will be copied)
     * @return IOTCS_RESULT_OK or IOTCS_RESULT_FAIL if these is no items in the queue 
     */
    iotcs_result util_array_queue_pop(util_array_queue* queue, util_array_queue_item_addr msg);

#ifdef __cplusplus
}
#endif

#endif /* UTIL_ARRAY_QUEUE_H */

