from pydevd_constants import *
import pydevd_tracing
import sys
import pydev_log
import pydevd_import_class

_original_excepthook = None
_handle_exceptions = None


import _pydev_threading as threading

threadingCurrentThread = threading.currentThread

from pydevd_comm import GetGlobalDebugger

class ExceptionBreakpoint:

    def __init__(
        self,
        qname,
        notify_always,
        notify_on_terminate,
        notify_on_first_raise_only,
        ):
        exctype = _get_class(qname)
        self.qname = qname
        if exctype is not None:
            self.name = exctype.__name__
        else:
            self.name = None

        self.notify_on_terminate = notify_on_terminate
        self.notify_always = notify_always
        self.notify_on_first_raise_only = notify_on_first_raise_only

        self.type = exctype


    def __str__(self):
        return self.qname

class LineBreakpoint:

    def __init__(self, line, condition, func_name, expression):
        self.line = line
        self.condition = condition
        self.func_name = func_name
        self.expression = expression

def get_exception_full_qname(exctype):
    if not exctype:
        return None
    return str(exctype.__module__) + '.' + exctype.__name__

def get_exception_name(exctype):
    if not exctype:
        return None
    return exctype.__name__


def get_exception_breakpoint(exctype, exceptions):
    exception_full_qname = get_exception_full_qname(exctype)

    exc = None
    if exceptions is not None:
        try:
            return exceptions[exception_full_qname]
        except KeyError:
            for exception_breakpoint in DictIterValues(exceptions):
                if exception_breakpoint.type is not None and issubclass(exctype, exception_breakpoint.type):
                    if exc is None or issubclass(exception_breakpoint.type, exc.type):
                        exc = exception_breakpoint
    return exc

#=======================================================================================================================
# _excepthook
#=======================================================================================================================
def _excepthook(exctype, value, tb):
    global _handle_exceptions
    if _handle_exceptions:
        exception_breakpoint = get_exception_breakpoint(exctype, _handle_exceptions)
    else:
        exception_breakpoint = None

    #Always call the original excepthook before going on to call the debugger post mortem to show it.
    _original_excepthook(exctype, value, tb)

    if not exception_breakpoint:
        return

    if tb is None:  #sometimes it can be None, e.g. with GTK
        return

    frames = []

    while tb:
        frames.append(tb.tb_frame)
        tb = tb.tb_next

    thread = threadingCurrentThread()
    frames_byid = dict([(id(frame),frame) for frame in frames])
    frame = frames[-1]
    thread.additionalInfo.exception = (exctype, value, tb)
    thread.additionalInfo.pydev_force_stop_at_exception = (frame, frames_byid)
    thread.additionalInfo.message = exception_breakpoint.qname
    debugger = GetGlobalDebugger()

    pydevd_tracing.SetTrace(None) #no tracing from here

    pydev_log.debug('Handling post-mortem stop on exception breakpoint %s'% exception_breakpoint.qname)

    debugger.handle_post_mortem_stop(thread.additionalInfo, thread)

#=======================================================================================================================
# _set_pm_excepthook
#=======================================================================================================================
def _set_pm_excepthook(handle_exceptions_dict=None):
    '''
    Should be called to register the excepthook to be used.

    It's only useful for uncaught exceptions. I.e.: exceptions that go up to the excepthook.

    @param handle_exceptions: dict(exception -> ExceptionBreakpoint)
        The exceptions that should be handled.
    '''
    global _handle_exceptions
    global _original_excepthook
    if sys.excepthook != _excepthook:
        #Only keep the original if it's not our own _excepthook (if called many times).
        _original_excepthook = sys.excepthook

    _handle_exceptions = handle_exceptions_dict
    sys.excepthook = _excepthook

def _restore_pm_excepthook():
    global _original_excepthook
    if _original_excepthook:
        sys.excepthook = _original_excepthook
        _original_excepthook = None


def update_exception_hook(dbg):
    if dbg.break_on_uncaught_exceptions:
        _set_pm_excepthook(dbg.break_on_uncaught_exceptions)
    else:
        _restore_pm_excepthook()

def _get_class( kls ):
    if IS_PY24 and "BaseException" == kls:
        kls = "Exception"

    try:
        return eval(kls)
    except:
        return pydevd_import_class.ImportName(kls)
