from base import BaseCacheMgr
from django.utils.encoding import force_unicode
from pycon.core import safe_utf8_encode
import time, pickle
import datetime

class CacheMgr(BaseCacheMgr):
    """Simple Memory Cache - Single-process in-memory cache backend.
    """
    has_cull = True
    scheme = 'simple'

    def info(self):
        base = super(CacheMgr, self).info()
        num_ent = len(self.cache._cache)
        cfreq = self.cache._cull_frequency
        max_ent = self.cache._max_entries
        info = [
            {'name': 'Cull Frequency', 'value': str(cfreq)},
            {'name': 'Num Entries',    'value': str(num_ent) },
            {'name': 'Max Entries',    'value': str(max_ent)},
            ]
        return base + info

    @staticmethod
    def _cache_info(key, data, exp):
        try:
            data = safe_utf8_encode(pickle.loads(data))[:200]
            if len(data) == 200: data += u'...'
        except pickle.PickleError:
            data = u'Cache Error: bad object.'
        except:
            data = u'Cache Manager Error: could not stringify object.'
        try:
            exd = datetime.datetime.fromtimestamp(exp)
        except:
            data = '(Cache Manager Error: cache time is invalid.) ' + data
            exd = datetime.datetime.now()
        try:
            key = safe_utf8_encode(key)
        except:
            key = safe_utf8_encode(repr(key))
        short_key = key if len(key) <= 25 else key[:25]
        cull = exp < time.time()
        return  {'key': key, 'short_key': short_key,
                 'repr': data, 'expires': exd, 'expired': cull}

    def __iter__(self):
        expire = self.cache._expire_info.items()
        cache = self.cache._cache
        expire.sort(cmp=lambda a, b: cmp(a[1], b[1]))
        for key, exp in expire:
            try:
                raw = cache[key]
            except KeyError:
                continue
            yield self._cache_info(key, raw, exp)

    def clear(self):
        self.cache._cache.clear()
        self.cache._expire_info.clear()

    def cull(self):
        self.cache._cull()
