"""
Enable wxPython to be used interacive by setting PyOS_InputHook.

Authors:  Robin Dunn and Brian Granger
"""

import sys
from ctypes import *

pyos_inputhook_ptr = c_void_p.in_dll(pythonapi, "PyOS_InputHook")
orig_pyos_inputhook_ptr_value = pyos_inputhook_ptr.value

def inputhook_wx():
    import wx
    app = wx.GetApp()
    if app is not None:
        assert wx.Thread_IsMain()

        # Make a temporary event loop and process system events until
        # there are no more waiting, then allow idle events (which
        # will also deal with pending or posted wx events.)
        evtloop = wx.EventLoop()
        ea = wx.EventLoopActivator(evtloop)
        while evtloop.Pending():
            evtloop.Dispatch()
        app.ProcessIdle()
        del ea
    return 0

callback_wx = CFUNCTYPE(c_int)(inputhook_wx)


def set_inputhook_wx():
    """Set PyOS_InputHook for interactive wx usage.

    This can be called before or after the main wx.App() is created,
    but if this is called, App.MainLoop() should *not* be called ever.

    It is important that when the wx.App() is created that it is passed the
    following options::

        app = wx.App(redirect=False, clearSigInt=False)

    This has been tested on wx 2.8 and 2.9 and works with *both* IPython
    and Python.  So far I have tested it on Mac OS X, Python 2.5.  Needs
    testing on Windows and Linux.
    
    Here is an example of its usage with Matplotlib::
    
        >>> import inputhook
        >>> inputhook.set_inputhook_wx()
        >>> app = wx.App(redirect=False, clearSigInt=False)
        >>> from matplotlib import pyplot as plt
        >>> plt.interactive(True)
        >>> plt.plot(range(10))
    """
    # These must be global or it doesn't work
    global pyos_inputhook_ptr
    global callback_wx
    pyos_inputhook_ptr.value = cast(callback_wx, c_void_p).value

def remove_inputhook():
    """
    Remove the PyOS_InputHook returning it back to its original state.
    """
    pyos_inputhook_ptr.value = orig_pyos_inputhook_ptr_value