import sys
import traceback
import logging
import warnings

from django.core.signals import got_request_exception
from django.db import  transaction
from django.http import Http404

from sentry import settings
from sentry.client.base import SentryClient
from sentry.helpers import get_installed_apps

logger = logging.getLogger('sentry')

_client = (None, None)
def get_client():
    global _client
    if _client[0] != settings.CLIENT:
        module, class_name = settings.CLIENT.rsplit('.', 1)
        _client = (settings.CLIENT, getattr(__import__(module, {}, {}, class_name), class_name)())
    return _client[1]
client = get_client()

@transaction.commit_on_success
def sentry_exception_handler(sender, request=None, **kwargs):
    try:
        exc_type, exc_value, exc_traceback = sys.exc_info()

        if not settings.CATCH_404_ERRORS \
                and issubclass(exc_type, Http404):
            return

        if settings.DEBUG or getattr(exc_type, 'skip_sentry', False):
            return

        if transaction.is_dirty():
            transaction.rollback()

        # kudos to Tapz for this idea
        modules = get_installed_apps()

        # only retrive last 10 lines
        tb = traceback.extract_tb(exc_traceback)

        # retrive final file and line number where the exception occured
        file, line_number = tb[-1][:2]

        # tiny hack to get the python path from filename
        for (filename, line, function, text) in reversed(tb):
            for path in sys.path:
                if filename.startswith(path):
                    view = '%s.%s' % (filename[len(path)+1:].replace('/', '.').replace('.py', ''), function)
                    break
            if view.split('.')[0] in modules:
                break
            else:
                view = '%s.%s' % (exc_traceback.tb_frame.f_globals['__name__'], tb[-1][2]) 

        if request:
            data = dict(
                META=request.META,
                POST=request.POST,
                GET=request.GET,
                COOKIES=request.COOKIES,
            )
        else:
            data = dict()

        extra = dict(
            url=request and request.build_absolute_uri() or None,
            data=data,
            view=view,
        )
        
        client = get_client()
        client.create_from_exception(**extra)
    except Exception, exc:
        try:
            logger.exception(u'Unable to process log entry: %s' % (exc,))
        except Exception, exc:
            warnings.warn(u'Unable to process log entry: %s' % (exc,))

got_request_exception.connect(sentry_exception_handler)

