import sys

# Some cruft to deal with the Pythonwin GUI booting up from a non GUI app.
def _MakeDebuggerGUI():
	app.InitInstance()

isInprocApp = -1
def _CheckNeedGUI():
	global isInprocApp
	if isInprocApp==-1:
		import win32ui
		isInprocApp = win32ui.GetApp().IsInproc()
	if isInprocApp:
		# MAY Need it - may already have one
		need = "pywin.debugger.dbgpyapp" not in sys.modules
	else:
		need = 0
	if need:
		import pywin.framework.app
		from . import dbgpyapp
		pywin.framework.app.CreateDefaultGUI(dbgpyapp.DebuggerPythonApp)

	else:
		# Check we have the appropriate editor
		# No longer necessary!
		pass
	return need

# Inject some methods in the top level name-space.
currentDebugger = None # Wipe out any old one on reload.

def _GetCurrentDebugger():
	global currentDebugger
	if currentDebugger is None:
		_CheckNeedGUI()
		from . import debugger
		currentDebugger = debugger.Debugger()
	return currentDebugger

def GetDebugger():
	# An error here is not nice - as we are probably trying to
	# break into the debugger on a Python error, any
	# error raised by this is usually silent, and causes
	# big problems later!
	try:
		rc = _GetCurrentDebugger()
		rc.GUICheckInit()
		return rc
	except:
		print("Could not create the debugger!")
		import traceback
		traceback.print_exc()
		return None

def close():
	if currentDebugger is not None:
		currentDebugger.close()

def run(cmd,globals=None, locals=None, start_stepping = 1):
	_GetCurrentDebugger().run(cmd, globals,locals, start_stepping)

def runeval(expression, globals=None, locals=None):
	return _GetCurrentDebugger().runeval(expression, globals, locals)

def runcall(*args):
	return _GetCurrentDebugger().runcall(*args)

def set_trace():
	import sys
	d = _GetCurrentDebugger()

	if d.frameShutdown: return # App closing

	if d.stopframe != d.botframe:
		# If im not "running"
		return

	sys.settrace(None) # May be hooked
	d.reset()
	d.set_trace()

# "brk" is an alias for "set_trace" ("break" is a reserved word :-(
brk = set_trace

# Post-Mortem interface

def post_mortem(t=None):
	if t is None:
		t = sys.exc_info()[2] # Will be valid if we are called from an except handler.
	if t is None:
		try:
			t = sys.last_traceback
		except AttributeError:
			print("No traceback can be found from which to perform post-mortem debugging!")
			print("No debugging can continue")
			return
	p = _GetCurrentDebugger()
	if p.frameShutdown: return # App closing
	# No idea why I need to settrace to None - it should have been reset by now?
	sys.settrace(None)
	p.reset()
	while t.tb_next != None: t = t.tb_next
	p.bAtPostMortem = 1
	p.prep_run(None)
	try:
		p.interaction(t.tb_frame, t)
	finally:
		t = None
		p.bAtPostMortem = 0
		p.done_run()

def pm(t=None):
	post_mortem(t)