#include "fmapplication.h"

#include <QMutexLocker>

#include "event/posevent.h"

QMap< int, QSet<QObject *> > FMApplication::s_user_event_pool;
QMutex FMApplication::s_mutex;
bool FMApplication::s_stop_flag = false;

FMApplication::FMApplication(int &argc, char **argv):QApplication(argc, argv)
{

}

void FMApplication::postEvent(QObject *receiver, QEvent *event, int priority)
{
    //参数检测过滤无效的事件
    if(event == NULL || event->type() > QEvent::MaxUser)
        return ;

    int type = event->type();

    //处理自定义事件
    if((!s_stop_flag) && type >= QEvent::User && type <= QEvent::MaxUser)
    {
        QMutexLocker loker(&s_mutex);

        if(s_user_event_pool.contains(type))
        {
             QSet<QObject *> tmpset = s_user_event_pool[type];

             QSetIterator<QObject *> i(tmpset);

             while(i.hasNext())
             {
                PosEvent *tmpevent = new PosEvent(event->type());

                *tmpevent = *((PosEvent*)event);

                QApplication::postEvent(i.next(), tmpevent, priority);
             }

        }
        //while循环中调用的QApplication::postEvent都是副本,PosEvent的设计(重载了=运算符)可以防止事件携带的信息一致
        //这样就导致调用FMApplication::postEvent发送的event没有被推送到qt事件循环中,在这里手动释放
        delete event;
        return;
    }

    //非自定义事件应当指定接收者
    if(receiver == NULL)
        return;

    QApplication::postEvent(receiver, event, priority);
}

bool FMApplication::subscibeEvent(QObject *listener, QEvent::Type type)
{
    if(type < QEvent::User || type > QEvent::MaxUser)
        return false;

    QMutexLocker loker(&s_mutex);

    if(s_user_event_pool.contains(type))
    {
        QSet<QObject *> tmpset = s_user_event_pool[type];

        tmpset.insert(listener);

        s_user_event_pool.insert(type, tmpset);

        return true;
    }

    QSet<QObject *> tmpset;
    tmpset.insert(listener);
    s_user_event_pool.insert(type, tmpset);

    return true;
}

void FMApplication::logoutEvent(QObject *listener, QEvent::Type type)
{
    if(type < QEvent::User || type > QEvent::MaxUser)
        return ;

    QMutexLocker loker(&s_mutex);

    if(s_user_event_pool.contains(type))
    {
        QSet<QObject *> tmpset = s_user_event_pool[type];

        tmpset.remove(listener);

        s_user_event_pool.insert(type, tmpset);
    }

}

void FMApplication::exit(int rlt)
{
    s_stop_flag = true;
    qApp->exit(rlt);
}


