#ifndef POSEVENT_H
#define POSEVENT_H

#include <QEvent>
#include <QString>
#include <QMutex>
#include <functional>

#define DEFAULTPOSTEVENT(eventtype, info) do {                              \
    PosEvent *event = new PosEvent(eventtype);                              \
    QString *tmpkey = new QString(info);                                    \
    event->setInfo((void *)tmpkey);                                         \
    event->setInfo_call_bk([](void *key) {                                  \
        QString *tmp = (QString *)key;                                      \
        delete tmp;                                                         \
    });                                                                     \
    event->setCopy_info_call_bk([](void *&tmpkeys,void *keys){              \
            tmpkeys = (void *)new QString;                                  \
            *((QString *)tmpkeys) = *((QString *)keys);                     \
    });                                                                     \
    FMApplication::postEvent(NULL, event);                                  \
} while (0)
//发送携带任意类型数据的事件;eventtype事件类型,info事件携带类型(确保深复制);Type为info的类型
#define POSTEVENTTYPE(eventtype, info, Type) do {                           \
    PosEvent *event = new PosEvent(eventtype);                              \
    Type *tmpkey = new Type;                                                \
    *tmpkey = info;                                                         \
    event->setInfo((void *)tmpkey);                                         \
    event->setInfo_call_bk([](void *key) {                                  \
        Type *tmp = (Type *)key;                                            \
        delete tmp;                                                         \
    });                                                                     \
    event->setCopy_info_call_bk([](void *&tmpkeys, void *keys){             \
            tmpkeys = (void *)new Type;                                     \
            *((Type *)tmpkeys) = *((Type *)keys);                           \
    });                                                                     \
    FMApplication::postEvent(NULL, event);                                  \
} while (0)
//获取事件携带的信息
#define GETEVENTINFO(value, ev, Type) do {                                  \
    PosEvent *tmp = (PosEvent*)(ev);                                        \
    value = *((Type *)(tmp->info()));                                       \
}while(0)

//发送携带信息的事件;获取事件携带的信息应当使用以上的宏,这可以保证夸线程跨对象传递event时,event中的info总是有效和info堆内存的及时释放;
class PosEvent : public QEvent
{
public:
    PosEvent(Type e);

    virtual ~PosEvent();

    void *info() const;
    void setInfo(void *info);
    //重载等号
    PosEvent &operator =(const PosEvent &e);
    //删除info函数
    void setInfo_call_bk(const std::function<void (void *)> &info_call_bk);
    //info信息的深复制
    void setCopy_info_call_bk(const std::function<void (void *&, void *)> &copy_info_call_bk);

public:
    //订单状态改变事件
    static Type s_change_order;
    //删除订单
    static Type s_delete_order;
    //操作订单,送出,接单,退单,拒绝接单等
    static Type s_opt_order;
    //订单操作状态改变,写销售单,写db
    static Type s_opt_change_order;
    //需要拉单
    static Type s_need_get_order;
    //登陆状态,用于登陆相关通知
    static Type s_login_status;
    //操作状状态,用于操作相关通知
    static Type s_opt_status;
    //获取拉单状态
    static Type s_get_order_status;
    //本地化状态改变
    static Type s_order_location;
    //token变化
    static Type s_token_change;
    //插入新订单
    static Type s_inset_orderpool;
    //改变订单状态
    static Type s_change_orderpool;
    //改变本地订单状态
    static Type s_location_orderpool;
    //登陆并设置门店信息
    static Type s_login_storeinfo;

private:
    //事件携带的信息,该内存你应当在堆中分配
    void *_info;
    //用于处理info资源的回收,当事件被删除时调用
    std::function< void (void *) > _info_call_bk;
    //用于处理info资源的复制
    std::function< void (void *&, void *) > _copy_info_call_bk;
};

#endif // POSEVENT_H
