from datetime import timedelta
from django.core.cache import cache
from django.utils import timezone
from misago.thread import local

_thread_local = local()

def load_monitor():
    from misago.models import MonitorItem
    monitor = cache.get('monitor', {})
    if not monitor:
        for i in MonitorItem.objects.all():
            monitor[i.id] = [i.value, i.updated, i.type]
        cache.set('monitor', monitor)
    return monitor


def refresh_monitor():
    _thread_local.monitor = load_monitor()


class Monitor(object):
    def monitor(self):
        try:
            return _thread_local.monitor
        except AttributeError:
            _thread_local.monitor = load_monitor()
            return _thread_local.monitor

    def entry(self, key):
        try:
            return self.monitor()[key]
        except KeyError:
            raise Exception(u"Monitor entry \"%s\" could not be found." % key)

    def __contains__(self, key):
        return key in self.monitor()

    def __getitem__(self, key):
        return self.entry(key)[0]

    def __getattr__(self, key):
        return self.entry(key)[0]

    def __setitem__(self, key, value):
        _thread_local.monitor_update.append((key, value))
        return value

    def increase(self, key, i=1):
        _thread_local.monitor_update.append((key, self[key] + i))

    def decrease(self, key, i=1):
        _thread_local.monitor_update.append((key, self[key] - i))

    def get(self, key, default=None):
        if not key in self.monitor():
            return default
        return self.entry(key)[0]

    def updated(self, key):
        if key in self.monitor():
            return self.entry(key)[1]
        return None

    def expired(self, key, seconds=5):
        return self.entry(key)[1] < (timezone.now() - timedelta(seconds=seconds))

    def has_key(self, key):
        return key in self.entry()

    def keys(self):
        return self.entry().keys()

    def values(self):
        return self.entry().values()

    def items(self):
        return self.entry().items()

    def iterkeys(self):
        return self.entry().iterkeys()

    def itervalues(self):
        return self.entry().itervalues()

    def iteritems(self):
        return self.entry().iteritems()


class UpdatingMonitor(object):
    def __enter__(self):
        _thread_local.monitor_update = []

    def __exit__(self, type, value, traceback):
        if _thread_local.monitor_update:
            from misago.models import MonitorItem
            for key, value in _thread_local.monitor_update:
                MonitorItem.objects.filter(pk=key).update(_value=value, updated=timezone.now())
            cache.delete('monitor')
            _thread_local.monitor_update = None


monitor = Monitor()