# Based on paste.cgitb_catcher, which is available under the MIT licens.
# http://www.opensource.org/licenses/mit-license.php

import sys, traceback

from bazjunk import email

class EmailErrors(object):
    def __init__(self, app, subject_prefix, **email_args):
        self.app = app
        self.subject_prefix = subject_prefix
        self.email_args = email_args
        
    def __call__(self, environ, start_response):
        try:
            app_iter = self.app(environ, start_response)
            return self.catching_iter(app_iter, environ)
        except:
            exc_info = sys.exc_info()
            self.exception_handler(exc_info, environ)
            raise

    def catching_iter(self, app_iter, environ):
        if not app_iter:
            raise StopIteration
        error_on_close = False
        try:
            for v in app_iter:
                yield v
            if hasattr(app_iter, 'close'):
                error_on_close = True
                app_iter.close()
        except GeneratorExit:
            if not error_on_close and hasattr(app_iter, 'close'):
                app_iter.close()
        except:
            self.exception_handler(sys.exc_info(), environ, ' in iter')
            if not error_on_close and hasattr(app_iter, 'close'):
                try:
                    app_iter.close()
                except:
                    self.exception_handler(sys.exc_info(), environ,
                                           ' in .close()')
            raise

    def exception_handler(self, exc_info, environ, detail=''):
        type, value, tb = exc_info
        msg = ''.join(traceback.format_exception(type, value, tb))
        msg += '\n\n'
        msg += 'Environ:\n'
        for k in sorted(environ):
            msg += '  %s = %s\n' % (k, repr(environ[k]))
        subject = "%s%s: %s" % (self.subject_prefix, detail, value)
        email.send(msg, subject, **self.email_args)
