#!/usr/bin/env python

# This file is part of Window-Switch.
# Copyright (c) 2009-2013 Antoine Martin <antoine@nagafix.co.uk>
# Window-Switch is released under the terms of the GNU GPL v3

import sys

from winswitch.util.simple_logger import Logger
logger=Logger("main_loop", log_colour=Logger.CYAN)


REACTOR = None
def loop_init(useGtk=True):
	global REACTOR
	if REACTOR:
		logger.slog("already initialized: reactor=%s" % REACTOR, useGtk)
		return	REACTOR
	logger.sdebug(None, useGtk)
	try:
		import glib
		try:
			glib.threads_init()
		except AttributeError:
			#old versions of glib may not have this method
			pass
	except ImportError:
		#glib bindings not installed
		pass
	import gobject
	gobject.threads_init()
	from twisted.python import threadable
	threadable.init(1)
	if not sys.platform.startswith("win"):
		if useGtk:
			import gtk.gdk
			gtk.gdk.threads_init()
	from twisted.internet import gtk2reactor
	gtk2reactor.install(useGtk=useGtk)
	import twisted.internet.reactor as just_load_it		#we need this or py2exe screws it up?
	assert just_load_it
	import twisted.internet
	logger.slog("twisted version %s" % str(twisted.__version__), useGtk)
	REACTOR = twisted.internet.reactor
	return REACTOR


LOOP_STARTED = False
def loop_run():
	global LOOP_STARTED, REACTOR
	if not REACTOR:
		logger.serror("not initialized! call loop_init() first")
		return
	if LOOP_STARTED:
		logger.serror("already started!")
		return
	from winswitch.util.process_util import start_dump_threads, dump_threads
	start_dump_threads()
	try:
		logger.sdebug("reactor uses gtk/glib main loop")
		logger.slog("calling reactor.run()")
		try:
			REACTOR.run(installSignalHandlers=1)
		except Exception, e:
			logger.exc(e)
			raise e
		logger.slog("reactor.run() terminated")
	except KeyboardInterrupt, e:
		logger.serr("stopping on %s: %s" % (type(e), e), None)
	dump_threads()

def is_loop_started():
	global LOOP_STARTED
	return LOOP_STARTED

def loop_exit():
	logger.slog(None)
	from twisted.internet import error
	try:
		REACTOR.callFromThread(REACTOR.stop)
	except error.ReactorNotRunning, e:
		logger.serror("%s" % e)
	except Exception, e:
		logger.serr(None, e)
	logger.slog("done")

def get_reactor():
	global REACTOR
	return	REACTOR

def with_loop(callback, useGtk=True, exit_after=None):
	loop_init(useGtk)
	if exit_after is not None:
		callLater(exit_after, loop_exit)
	callWhenRunning(callback)
	loop_run()

def with_gtk_loop(callback):
	with_loop(callback, True)

def test_loop(callback):
	with_loop(callback, False, 20)

def test_gtk_loop(callback):
	with_loop(callback, True, 20)


# below are the reactor methods we wrap
# so pydev quits moaning about undefined imports
def reactor():
	global REACTOR
	if REACTOR is None:
		raise Exception("BUG: reactor not initialized! You must call loop_init()")
	return	REACTOR
def callLater(*args, **kwargs):
	return	reactor().callLater(*args, **kwargs)
def callWhenRunning(*args, **kwargs):
	return	reactor().callWhenRunning(*args, **kwargs)
def callFromThread(*args, **kwargs):
	return	reactor().callFromThread(*args, **kwargs)
def listenTCP(*args, **kwargs):
	return	reactor().listenTCP(*args, **kwargs)
def listenUNIX(*args, **kwargs):
	return	reactor().listenUNIX(*args, **kwargs)
def connectTCP(*args, **kwargs):
	return	reactor().connectTCP(*args, **kwargs)
def connectUNIX(*args, **kwargs):
	return	reactor().connectUNIX(*args, **kwargs)
def addSystemEventTrigger(*args, **kwargs):
	return	reactor().addSystemEventTrigger(*args, **kwargs)
