from threading import currentThread

from django.core.cache.backends.dummy import DummyCache
from django.core.cache.backends.locmem import LocMemCache
from django.utils.deprecation import MiddlewareMixin

_request_cache = {}


class RequestCache(LocMemCache):
    """ LocMemCache is a threadsafe local memory cache """
    def __init__(self):
        name = 'locmemcache@%i' % hash(currentThread())
        super(RequestCache, self).__init__(name, {})


def get_request_cache():
    """
    Returns per-request cache when running RequestCacheMiddleware otherwise a
    DummyCache instance (when running periodic tasks, tests or shell)
    """
    try:
        return _request_cache[currentThread()]
    except KeyError:
        return DummyCache('dummy', {})


class RequestCacheMiddleware(MiddlewareMixin):
    def process_request(self, request):
        current_thread = currentThread()
        cache = _request_cache.get(current_thread, RequestCache())
        _request_cache[current_thread] = cache
        cache.clear()

    def clear_cache(self):
        current_thread = currentThread()
        if currentThread() in _request_cache:
            _request_cache[current_thread].clear()

    def process_exception(self, request, exception):
        self.clear_cache()

    def process_response(self, request, response):
        self.clear_cache()
        return response