__all__ = ("initialize_kaa_thread_in_qapp", )

from PyQt4 import QtCore
import kaa

class QtMainThreadCallbackEvent(QtCore.QEvent):
    """Event class used to pass callbacks to the main thread."""
    
    __slots__ = ("_callback")
    
    TYPE = QtCore.QEvent.Type(QtCore.QEvent.User + 9476) # arbitrary unique ID

    def __init__(self, callback):
        QtCore.QEvent.__init__(self, self.TYPE)
        self._callback = callback

    def performCallback(self):
        self._callback()

    def type(self):
        return self.TYPE

class QtMainThreadCallbackListener(QtCore.QObject):
    """Event filtering object that will be attached to a
    Q[Core]Application in order to catch the
    QtMainThreadCallbackEvents, and perform the callbacks."""
    
    def eventFilter(self, app, event):
        if event.type() == QtMainThreadCallbackEvent.TYPE:
            event.performCallback()
            return True
        return QtCore.QObject.eventFilter(self, app, event)

_qapp = None # main QCoreApplication whose mainloop we've hooked into

def call_from_qt_mainloop(callback):
    """Wrapper using the above classes to provide the API expected by
    kaa.notifier for calling a callback function from the main (GUI)
    thread."""
    
    event = QtMainThreadCallbackEvent(callback)
    _qapp.postEvent(_qapp, event)

def initialize_kaa_thread_in_qapp(app):
    """Call this function after initializing a QApplication to
    initialize and start the kaa mainloop and integrate it into Qt's.
    `app` may be any subclass of QCoreApplication."""
    
    global _listener, _qapp
    _listener = QtMainThreadCallbackListener()
    _qapp = app
    _qapp.installEventFilter(_listener)

    loop = kaa.main.select_notifier(
        'thread', handler = call_from_qt_mainloop,
        shutdown = _qapp.quit)

    QtCore.QObject.connect(_qapp, QtCore.SIGNAL("aboutToQuit()"),
                           loop.stop)
