import threading
import logging
import sys

__ALL__ = ('KeepUserAroundMiddleware', 'get_extra')

NO_USER = '-'
NO_IP = NO_USER

logger = logging.getLogger('docbow')

def get_extra():
    '''Extract current remote ip and current user from the thread local storage
       from the KeepUserAroundMiddleware middleware class.
    '''
    k = KeepUserAroundMiddleware
    return { 'ip': k.get_global_ip(), 'user': k.get_global_user() }

class KeepUserAroundMiddleware(object):
    '''
       Store the request.user and the REMOTE_ADDR in a global thread local
       variable, so that logging calls inside signals handler can know about
       them.
    '''
    __middleware_ctx = threading.local()
    __middleware_ctx.user = NO_USER
    __middleware_ctx.ip = NO_USER

    def process_request(self, request):
        self.__middleware_ctx.user = getattr(request, 'user', NO_USER)
        self.__middleware_ctx.ip = request.META.get('REMOTE_ADDR', NO_IP)
        return None

    def process_response(self, request, response):
        self.__middleware_ctx.user = NO_USER
        self.__middleware_ctx.ip = NO_IP
        return response

    def process_exception(self, request, exception):
        logger.error('Internal Server Error: %s' % request.path,
            exc_info=sys.exc_info,
            extra={
                'status_code': 500,
                'request': request,
                'ip': self.get_global_ip(),
                'user': self.get_global_user(),
            })
        self.__middleware_ctx.user = NO_USER
        self.__middleware_ctx.ip = NO_IP
        return None

    @classmethod
    def get_global_user(cls):
        return cls.__middleware_ctx.user

    @classmethod
    def get_global_ip(cls):
        return cls.__middleware_ctx.ip
