#ifndef __QUEUE_H
#define __QUEUE_H

typedef enum
{
    Q_OK,
    Q_ERR,
    Q_FULL,
    Q_EMPTY,
} QUEUE_STATUS;

#define queue_entry(type, size) \
    struct                      \
    {                           \
        uint8_t head;           \
        uint8_t tail;           \
        uint8_t count;          \
        type    message[size];  \
    }

#define queue_init(name)                 \
    {                                    \
        (name)->head = (name)->tail = 0; \
        (name)->count               = 0; \
    }

/* List functions. */
#define queue_empty(name) ((name)->count == 0)
#define queue_max(name)   ((sizeof((name)->message)) / (sizeof((name)->message[0])))
#define queue_full(name)  ((name)->count == ((sizeof((name)->message)) / (sizeof((name)->message[0]))))
#define en_queue(name, field, ret)                                                \
    do                                                                            \
    {                                                                             \
        if (queue_full(name))                                                     \
        {                                                                         \
            ret = Q_FULL;                                                         \
        }                                                                         \
        else                                                                      \
        {                                                                         \
            (name)->count++;                                                      \
            (name)->message[(name)->head] = field;                                \
            (name)->head                  = ((name)->head + 1) % queue_max(name); \
            ret                           = Q_OK;                                 \
        }                                                                         \
    } while (0)

#define de_queue(name, field, ret)                               \
    do                                                           \
    {                                                            \
        if (queue_empty(name))                                   \
        {                                                        \
            ret = Q_EMPTY;                                       \
        }                                                        \
        else                                                     \
        {                                                        \
            field        = (name)->message[(name)->tail];        \
            (name)->tail = ((name)->tail + 1) % queue_max(name); \
            (name)->count--;                                     \
            ret = Q_OK;                                          \
        }                                                        \
    } while (0)

#endif
