/************************************************************
* Details: 消息队列
* Encode: UTF-8
* Platform: Android & Linux
* Author: R&D 2
* Date: 2018-4-2
************************************************************/
#ifndef __GT_CORE_MESSAGE_QUEUE_H__
#define __GT_CORE_MESSAGE_QUEUE_H__
#include <pthread.h>

#define SENDER_MTU 10240

typedef struct __stMessageTag
{
    unsigned long ulType;//通信类型
    unsigned long ulVersion;//协议版本
    unsigned long ulTransSN;//交易流水号
    unsigned long ulTransCode;//交易码
    unsigned long ulDataSize;//报文内容大小
    long lCRC;//通信CRC校验码
}stMessageTag;

typedef struct __stMessage
{
    stMessageTag msgTag;//通信报文标签
    unsigned char strData[SENDER_MTU + 8];//通信报文数据
}stMessage;

typedef struct __stMessageItem
{
    unsigned int unStatus;//0-空，1-待处理，2-已接收服务器应答，3-已处理
    long lTime;//插入队列时间
    int nValidTime;//在队列的有效时间
    int nRoute;//返回数据的链路
    stMessage msg;//队列数据
}stMessageItem;

typedef struct __stMessageQueue
{
    stMessageItem item;
    struct __stMessageQueue *next;
}stMessageQueue;

class GtMessageQueue
{
    public:
        virtual ~GtMessageQueue();
        static GtMessageQueue *instance();

        /************************************************************
        *功能：构建消息队列
        *输入：maxSize消息队列最大长度
        *输出：无
        *返回：true成功
        */
        bool initMessageQueue(int maxSize);

        /************************************************************
        *功能：释放消息队列
        *输入：无
        *输出：无
        *返回：无
        */
        void releaseMessageQueue();

        /************************************************************
        *功能：获取消息队列中空的节点
        *输入：无
        *输出：offset节点索引
        *返回：true成功
        */
        bool getEmptyNodeSecure(int *offset, stMessageItem *item);

        /************************************************************
        *功能：获取指定位置的消息队列节点
        *输入：index消息队列索引
        *输出：item消息队列节点属性
        *返回：true成功
        */
        bool getNodeSecure(int index, stMessageItem *item);

        /************************************************************
        *功能：刷新指定位置的消息队列节点
        *输入：index消息队列索引
        *输入：item消息队列节点属性
        *输出：无
        *返回：true成功
        */
        bool setNodeSecure(int index, stMessageItem *item);

        /************************************************************
        *功能：将指定位置的消息节点移动到消息队列末尾，并清除其属性数据
        *输入：index消息队列索引
        *输出：无
        *返回：true成功
        */
        bool recycleNodeSecure(int index);


    private:
        GtMessageQueue();
        static GtMessageQueue *_instance;
        static pthread_mutex_t _mutex;
        stMessageQueue *_messageQueue;

        /************************************************************
        *功能：插入消息节点到消息队列末尾
        *输入：node消息节点
        *输出：无
        *返回：!=0错误
        */
        bool appendNode(stMessageQueue *node);

        /************************************************************
        *功能：队列加锁
        *输入：无
        *输出：无
        *返回：true成功
        */
        bool lock();

        /************************************************************
        *功能：队列解锁
        *输入：无
        *输出：无
        *返回：true成功
        */
        bool unlock();

        /************************************************************
        *功能：获取消息队列中空的节点
        *输入：无
        *输出：offset节点索引
        *返回：true成功
        */
        bool getEmptyNode(int *offset, stMessageItem *item);

        /************************************************************
        *功能：获取指定位置的消息队列节点
        *输入：index消息队列索引
        *输出：item消息队列节点属性
        *返回：true成功
        */
        bool getNode(int index, stMessageItem *item);

        /************************************************************
        *功能：刷新指定位置的消息队列节点
        *输入：index消息队列索引
        *输入：item消息队列节点属性
        *输出：无
        *返回：true成功
        */
        bool setNode(int index, stMessageItem *item);

        /************************************************************
        *功能：将指定位置的消息节点移动到消息队列末尾，并清除其属性数据
        *输入：index消息队列索引
        *输出：无
        *返回：true成功
        */
        bool recycleNode(int index);
};

#endif
