import sys
import traceback

from django.conf import settings
from django.urls import resolve
from lxml import etree
from six.moves.urllib.request import urlopen, Request

class Client(object):
    API_URL = '%s://airbrake.io/notifier_api/v2/notices'
    ERRORS = {
        403: "Cannot use SSL",
        422: "Invalid XML sent to Airbrake",
        500: "Airbrake has braked too hard",
    }

    DEFAULTS = {
        'TIMEOUT': 5,
        'USE_SSL': False,
    }

    @property
    def url(self):
        scheme = 'http'
        if self.settings['USE_SSL']:
            scheme = 'https'

        return Client.API_URL % scheme

    @property
    def settings(self):
        if getattr(self, '_settings', None):
            return self._settings

        self._settings = Client.DEFAULTS
        self._settings.update(getattr(settings, 'AIRBRAKE', {}))
        return self._settings

    def notify(self, exception=None, request=None):
        headers = {
            'Content-Type': 'text/xml'
        }

        payload = self._generate_xml(exception=exception, request=request)
        req = Request(self.url, payload, headers)
        resp = urlopen(req, timeout=self.settings['TIMEOUT'])
        status = resp.getcode()

        if status == 200:
            return True
        elif status in Client.ERRORS:
            raise Exception(Client.ERRORS[status])

    def _generate_xml(self, exception=None, request=None):
        _, _, trace = sys.exc_info()
        notice_em = etree.Element('notice', version='2.0')

        tb = traceback.extract_tb(trace)

        api_key = etree.SubElement(notice_em, 'api-key').text = self.settings['API_KEY']

        notifier_em = etree.SubElement(notice_em, 'notifier')

        etree.SubElement(notifier_em, 'name').text = 'django-airbrake'
        etree.SubElement(notifier_em, 'version').text = '0.0.4'
        url_el = etree.SubElement(notifier_em, 'url')
        url_el.text = 'http://example.com'

        if request:
            request_em = etree.SubElement(notice_em, 'request')

            if request.is_secure():
                scheme = 'https'
            else:
                scheme = 'http'
            url = '%s://%s%s' % (scheme, request.get_host(),
                request.get_full_path())
            etree.SubElement(request_em, 'url').text = str(url)
            url_el.text = url

            cb, _, _ = resolve(request.path)
            etree.SubElement(request_em, 'component').text = str(cb.__module__)
            etree.SubElement(request_em, 'action').text = str(cb.__name__)
            if 'context' in self.settings:
                cgi_em = etree.SubElement(request_em, 'cgi-data')
                for key, val in list(self.settings['context'].items()):
                    var = etree.SubElement(cgi_em, 'var')
                    var.set('key', str(key))
                    var.text = str(val)

            session = list(request.session.items())
            if len(session):
                session_em = etree.SubElement(request_em, 'session')
                for key, val in session:
                    var = etree.SubElement(session_em, 'var')
                    var.set('key', str(key))
                    var.text = str(val)

            if exception:
                error_em = etree.SubElement(notice_em, 'error')

                etree.SubElement(error_em, 'class').text = str(exception.__class__.__name__)
                etree.SubElement(error_em, 'message').text = str(exception)

                backtrace_em = etree.SubElement(error_em, 'backtrace')

                for line in tb:
                    etree.SubElement(backtrace_em, 'line',
                        file=str(line[0]),
                        number=str(line[1]),
                        method=str(line[2]))

        env_em = etree.SubElement(notice_em, 'server-environment')

        etree.SubElement(env_em, 'environment-name').text = self.settings.get('ENVIRONMENT', 'development')

        return '<?xml version="1.0" encoding="UTF-8"?>%s' % etree.tostring(notice_em)

[((45, 14, 45, 49), 'six.moves.urllib.request.Request', 'Request', ({(45, 22, 45, 30): 'self.url', (45, 32, 45, 39): 'payload', (45, 41, 45, 48): 'headers'}, {}), '(self.url, payload, headers)', False, 'from six.moves.urllib.request import urlopen, Request\n'), ((46, 15, 46, 61), 'six.moves.urllib.request.urlopen', 'urlopen', (), '', False, 'from six.moves.urllib.request import urlopen, Request\n'), ((55, 22, 55, 36), 'sys.exc_info', 'sys.exc_info', ({}, {}), '()', False, 'import sys\n'), ((56, 20, 56, 58), 'lxml.etree.Element', 'etree.Element', (), '', False, 'from lxml import etree\n'), ((58, 13, 58, 40), 'traceback.extract_tb', 'traceback.extract_tb', ({(58, 34, 58, 39): 'trace'}, {}), '(trace)', False, 'import traceback\n'), ((62, 22, 62, 61), 'lxml.etree.SubElement', 'etree.SubElement', ({(62, 39, 62, 48): 'notice_em', (62, 50, 62, 60): '"""notifier"""'}, {}), "(notice_em, 'notifier')", False, 'from lxml import etree\n'), ((66, 17, 66, 53), 'lxml.etree.SubElement', 'etree.SubElement', ({(66, 34, 66, 45): 'notifier_em', (66, 47, 66, 52): '"""url"""'}, {}), "(notifier_em, 'url')", False, 'from lxml import etree\n'), ((113, 17, 113, 66), 'lxml.etree.SubElement', 'etree.SubElement', ({(113, 34, 113, 43): 'notice_em', (113, 45, 113, 65): '"""server-environment"""'}, {}), "(notice_em, 'server-environment')", False, 'from lxml import etree\n'), ((60, 18, 60, 56), 'lxml.etree.SubElement', 'etree.SubElement', ({(60, 35, 60, 44): 'notice_em', (60, 46, 60, 55): '"""api-key"""'}, {}), "(notice_em, 'api-key')", False, 'from lxml import etree\n'), ((64, 8, 64, 45), 'lxml.etree.SubElement', 'etree.SubElement', ({(64, 25, 64, 36): 'notifier_em', (64, 38, 64, 44): '"""name"""'}, {}), "(notifier_em, 'name')", False, 'from lxml import etree\n'), ((65, 8, 65, 48), 'lxml.etree.SubElement', 'etree.SubElement', ({(65, 25, 65, 36): 'notifier_em', (65, 38, 65, 47): '"""version"""'}, {}), "(notifier_em, 'version')", False, 'from lxml import etree\n'), ((70, 25, 70, 63), 'lxml.etree.SubElement', 'etree.SubElement', ({(70, 42, 70, 51): 'notice_em', (70, 53, 70, 62): '"""request"""'}, {}), "(notice_em, 'request')", False, 'from lxml import etree\n'), ((81, 23, 81, 44), 'django.urls.resolve', 'resolve', ({(81, 31, 81, 43): 'request.path'}, {}), '(request.path)', False, 'from django.urls import resolve\n'), ((115, 8, 115, 52), 'lxml.etree.SubElement', 'etree.SubElement', ({(115, 25, 115, 31): 'env_em', (115, 33, 115, 51): '"""environment-name"""'}, {}), "(env_em, 'environment-name')", False, 'from lxml import etree\n'), ((117, 60, 117, 85), 'lxml.etree.tostring', 'etree.tostring', ({(117, 75, 117, 84): 'notice_em'}, {}), '(notice_em)', False, 'from lxml import etree\n'), ((78, 12, 78, 47), 'lxml.etree.SubElement', 'etree.SubElement', ({(78, 29, 78, 39): 'request_em', (78, 41, 78, 46): '"""url"""'}, {}), "(request_em, 'url')", False, 'from lxml import etree\n'), ((82, 12, 82, 53), 'lxml.etree.SubElement', 'etree.SubElement', ({(82, 29, 82, 39): 'request_em', (82, 41, 82, 52): '"""component"""'}, {}), "(request_em, 'component')", False, 'from lxml import etree\n'), ((83, 12, 83, 50), 'lxml.etree.SubElement', 'etree.SubElement', ({(83, 29, 83, 39): 'request_em', (83, 41, 83, 49): '"""action"""'}, {}), "(request_em, 'action')", False, 'from lxml import etree\n'), ((85, 25, 85, 65), 'lxml.etree.SubElement', 'etree.SubElement', ({(85, 42, 85, 52): 'request_em', (85, 54, 85, 64): '"""cgi-data"""'}, {}), "(request_em, 'cgi-data')", False, 'from lxml import etree\n'), ((93, 29, 93, 68), 'lxml.etree.SubElement', 'etree.SubElement', ({(93, 46, 93, 56): 'request_em', (93, 58, 93, 67): '"""session"""'}, {}), "(request_em, 'session')", False, 'from lxml import etree\n'), ((100, 27, 100, 63), 'lxml.etree.SubElement', 'etree.SubElement', ({(100, 44, 100, 53): 'notice_em', (100, 55, 100, 62): '"""error"""'}, {}), "(notice_em, 'error')", False, 'from lxml import etree\n'), ((105, 31, 105, 70), 'lxml.etree.SubElement', 'etree.SubElement', ({(105, 48, 105, 56): 'error_em', (105, 58, 105, 69): '"""backtrace"""'}, {}), "(error_em, 'backtrace')", False, 'from lxml import etree\n'), ((87, 26, 87, 57), 'lxml.etree.SubElement', 'etree.SubElement', ({(87, 43, 87, 49): 'cgi_em', (87, 51, 87, 56): '"""var"""'}, {}), "(cgi_em, 'var')", False, 'from lxml import etree\n'), ((95, 26, 95, 61), 'lxml.etree.SubElement', 'etree.SubElement', ({(95, 43, 95, 53): 'session_em', (95, 55, 95, 60): '"""var"""'}, {}), "(session_em, 'var')", False, 'from lxml import etree\n'), ((102, 16, 102, 51), 'lxml.etree.SubElement', 'etree.SubElement', ({(102, 33, 102, 41): 'error_em', (102, 43, 102, 50): '"""class"""'}, {}), "(error_em, 'class')", False, 'from lxml import etree\n'), ((103, 16, 103, 53), 'lxml.etree.SubElement', 'etree.SubElement', ({(103, 33, 103, 41): 'error_em', (103, 43, 103, 52): '"""message"""'}, {}), "(error_em, 'message')", False, 'from lxml import etree\n')]