#ifndef POSORDERPOOL_H
#define POSORDERPOOL_H

#include <QObject>
#include <QString>
#include <QMutex>
#include <QTimer>
#include <QMap>

#include <QDateTime>

#include "Model/orderObject.h"

#define UPDATEORDERINFO(oldorder, neworder, info) do {                      \
        info.order_id = neworder.order_id;                                  \
        info.order_data = neworder;                                         \
        if(oldorder.order_refund != neworder.refund_status)                 \
        {                                                                   \
            info.order_refund = (Order_Status)neworder.refund_status;       \
            /*info.order_last_refund = oldorder.order_refund;*/             \
        }                                                                   \
        else                                                                \
        {                                                                   \
            info.order_refund = (Order_Status)oldorder.order_refund;        \
            /*info.order_last_refund = oldorder.order_last_refund;*/        \
        }                                                                   \
        if(oldorder.order_status != neworder.status)                        \
        {                                                                   \
            /*info.order_last_status = oldorder.order_status;*/             \
            info.order_status = (Order_Status)neworder.status;              \
        }                                                                   \
        else                                                                \
        {                                                                   \
            /*info.order_last_status = oldorder.order_last_status;*/        \
            info.order_status = oldorder.order_status;                      \
        }                                                                   \
        info.order_write_status = oldorder.order_write_status;              \
        info.order_refund_status = oldorder.order_refund_status;            \
        info.order_print_status = oldorder.order_print_status;              \
        info.order_change_time = QDateTime::currentDateTime().toTime_t();   \
    } while (0)

#define INITORDERINFO(neworder, info) do {                                  \
        info.order_id = neworder.order_id;                                  \
        info.order_data = neworder;                                         \
        info.order_refund = (Order_Status)neworder.refund_status;           \
        /*info.order_last_refund = DefaultOrder;*/                          \
        /*info.order_last_status = DefaultOrder;*/                          \
        info.order_status = (Order_Status)neworder.status;                  \
        info.order_write_status = 0;                                        \
        info.order_refund_status = 0;                                       \
        info.order_print_status = 0;                                        \
        info.order_change_time = QDateTime::currentDateTime().toTime_t();   \
    } while (0)

#define INCTAKEOUT(tmpstatus, tk_new, tk_make, tk_send, tk_refund) do {                             \
        if(tmpstatus == NewOrder)                                                                   \
            ++ tk_new;                                                                              \
        else if(tmpstatus == FirmOrder)                                                             \
            ++ tk_make;                                                                             \
        else if(tmpstatus == DispatchingOrder)                                                      \
            ++ tk_send;                                                                             \
        else if(tmpstatus == ApplicationRefundOrder || tmpstatus == ApplicationPartialRefundOrder)  \
            ++ tk_refund;                                                                           \
} while (0)

#define INCSELF(tmpstatus, self_new, self_make, self_refund) do {                                   \
        if(tmpstatus == NewOrder)                                                                   \
            ++ self_new;                                                                            \
        else if(tmpstatus == FirmOrder)                                                             \
            ++ self_make;                                                                           \
        else if(tmpstatus == ApplicationRefundOrder || tmpstatus == ApplicationPartialRefundOrder)  \
            ++ self_refund;                                                                         \
} while (0)

#define DECTAKEOUT(tmpstatus, tk_new, tk_make, tk_send, tk_refund) do {                             \
        if(tmpstatus == NewOrder)                                                                   \
            -- tk_new;                                                                              \
        else if(tmpstatus == FirmOrder)                                                             \
            -- tk_make;                                                                             \
        else if(tmpstatus == DispatchingOrder)                                                      \
            -- tk_send;                                                                             \
        else if(tmpstatus == ApplicationRefundOrder || tmpstatus == ApplicationPartialRefundOrder)  \
            -- tk_refund;                                                                           \
} while (0)

#define DECSELF(tmpstatus, self_new, self_make, self_refund) do {                                   \
        if(tmpstatus == NewOrder)                                                                   \
            -- self_new;                                                                            \
        else if(tmpstatus == FirmOrder)                                                             \
            -- self_make;                                                                           \
        else if(tmpstatus == ApplicationRefundOrder || tmpstatus == ApplicationPartialRefundOrder)  \
            -- self_refund;                                                                         \
} while (0)

typedef enum
{
    //订单原始状态(推了一个订单号时使用)
    DefaultOrder = -100,
    //锁定订单
    LockOrder = -1,
    //新订单
    NewOrder = 1,
    //确认订单
    FirmOrder =2,
    //取消订单
    CancelOrder=3,
    //配送中
    DispatchingOrder = 4,
    //制作完成
    InDevelopment = 5,
    //已送达
    ServiceOrder = 6,
    //申请退款
    ApplicationRefundOrder = 20,
    //申请部分退款
    ApplicationPartialRefundOrder = 22,
    //同意退款
    ApprovalRefundOrder = 30,
    //不同意退款
    RefusingRefundOrder = 40,
    //退款完成
    CompleteRefundOrder = 100,
    //完成订单
    CompleteOrder = 200,

} Order_Status;

typedef enum
{
    //订单原始状态(推了一个订单号时使用)
    DefaultOrderType = -100,
    //1=及时外卖
    TimelyTakeout = 1,
    //2=预约外卖
    AppointmentTakeout = 2,
    //3=及时堂食
    TimelyDining = 3,
    //4=预约堂食
    AppointmentDining = 4,
    //5=及时自提
    TimelyInvite = 5,
    //6=预约自提
    AppointmentInvite = 6
} Order_Type;

typedef struct
{
  //订单编号
  QString order_id;
  //订单修改时间
  uint order_change_time;
  //订单状态
  Order_Status order_status;
  //订单上一次状态
  //Order_Status order_last_status;
  //退单状态
  //Order_Status order_last_refund;
  //退单状态
  Order_Status order_refund;
  //本地写单状态
  int order_write_status;
  //本地退单状态
  int order_refund_status;
  //订单打印状态
  int order_print_status;
  //订单数据
  OrderObject order_data;
  //保留字段1
  QString reserved1;
  //保留字段2
  QString reserved2;
  //保留字段3
  QString reserved3;
  //保留字段4
  QString reserved4;
  //保留字段5
  QString reserved5;

} Order_Info;

class PosOrderPool : public QObject
{
    Q_OBJECT
public:
    static void InitOrderPool();

    static QMap<QString, Order_Info> getS_order_pool();

    static bool GetOrderObject(QString key, OrderObject &order);

    static bool GetOrderStatus(QString key, int &status, int &refund_status, bool &oldorder);

    static bool GetOrderBaseInfo(QString key, QVariantHash &hash);

    static void GetOrderNum(int &tk_new, int &tk_make, int &tk_send, int &tk_refund, int &self_new, int &self_make, int &self_refund);

    static bool GetSearchOrder(QString key, QMap<QString, QString> &map);

    virtual bool event(QEvent *e);

private:
    static void UpdateOrderNum(const OrderObject *order, const OrderObject *orderold = NULL);

    static bool TryInsertOrder(OrderObject order);

    static bool TryChangeOrderStatus(QString key, int order_status, int refundstatus = DefaultOrder);

    static bool TryChangeOrderWriteStatus(QString key, int order_write_status);

    static bool TryChangeOrderRefundStatus(QString key, int order_refund_status);

    static bool TryChangeOrderPrintStatus(QString key, int order_print_status);

    static void removeOrderInfo(QString key);

    static void GetOrderStatus(const OrderObject *order, int &status);

    explicit PosOrderPool(QObject *parent = 0);

    void loadOrders();
private:
    //互斥读写
    static  QMap<QString, Order_Info> s_order_pool;
    //写互斥锁
    static QMutex s_mutex;
    //外卖新单
    static int s_takeout_new;
    //外卖制作单
    static int s_takeout_make;
    //外卖票配送单
    static int s_takeout_send;
    //外卖退单
    static int s_takeout_refund;
    //自提新订单
    static int s_self_new;
    //自提制作单
    static int s_self_make;
    //自提退单
    static int s_self_refund;

    //维护以上订单数量的锁
    static QMutex s_order_num_mutex;
    //定时清理订单池
    QTimer _timer;
    //本地已有订单;
    static QStringList s_order_list;

};

#endif // POSORDERPOOL_H
