from IPython.genutils import Term,warn,error,flag_calls, ask_yes_no

import thread,inspect

try:
    import ctypes
    HAS_CTYPES = True
except ImportError:
    HAS_CTYPES = False


# Globals
# global flag to pass around information about Ctrl-C without exceptions
KBINT = False

# global flag to turn on/off Tk support.
USE_TK = False

# ID for the main thread, used for cross-thread exceptions
MAIN_THREAD_ID = thread.get_ident()

# Tag when runcode() is active, for exception handling
CODE_RUN = None


#-----------------------------------------------------------------------------
# This class is trivial now, but I want to have it in to publish a clean
# interface. Later when the internals are reorganized, code that uses this
# shouldn't have to change.


if HAS_CTYPES:
    #  Add async exception support.  Trick taken from:
    # http://sebulba.wikispaces.com/recipe+thread2
    def _async_raise(tid, exctype):
        """raises the exception, performs cleanup if needed"""
        if not inspect.isclass(exctype):
            raise TypeError("Only types can be raised (not instances)")
        res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid,
                                                         ctypes.py_object(exctype))
        if res == 0:
            raise ValueError("invalid thread id")
        elif res != 1:
            # """if it returns a number greater than one, you're in trouble, 
            # and you should call it again with exc=NULL to revert the effect"""
            ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, 0)
            raise SystemError("PyThreadState_SetAsyncExc failed")

    def sigint_handler (signum,stack_frame):
        """Sigint handler for threaded apps.

        This is a horrible hack to pass information about SIGINT _without_
        using exceptions, since I haven't been able to properly manage
        cross-thread exceptions in GTK/WX.  In fact, I don't think it can be
        done (or at least that's my understanding from a c.l.py thread where
        this was discussed)."""

        global KBINT

        if CODE_RUN:
            _async_raise(MAIN_THREAD_ID,KeyboardInterrupt)
        else:
            KBINT = True
            print '\nKeyboardInterrupt - Press <Enter> to continue.',
            Term.cout.flush()

else:
    def sigint_handler (signum,stack_frame):
        """Sigint handler for threaded apps.

        This is a horrible hack to pass information about SIGINT _without_
        using exceptions, since I haven't been able to properly manage
        cross-thread exceptions in GTK/WX.  In fact, I don't think it can be
        done (or at least that's my understanding from a c.l.py thread where
        this was discussed)."""

        global KBINT

        print '\nKeyboardInterrupt - Press <Enter> to continue.',
        Term.cout.flush()
        # Set global flag so that runsource can know that Ctrl-C was hit
        KBINT = True

def run_in_frontend(src):
    """ Check if source snippet can be run in the REPL thread, as opposed to GUI mainloop
    
    (to prevent unnecessary hanging of mainloop).  
    
    """
    
    if src.startswith('_ip.system(') and not '\n' in src:
        return True
    return False