_MAX_CACHE_SIZE = 10
_MAX_CACHE_AGE_SECS = 180

import logging
import os
import os.path
import shutil
import tempfile
import time

ui_out = logging.getLogger("av98_logger")

class Cache:

    def __init__(self):

        self.cache = {}
        self.cache_timestamps = {}
        self.tempdir = tempfile.TemporaryDirectory()

    def check(self, url):
        if url not in self.cache:
            return False
        now = time.time()
        cached = self.cache_timestamps[url]
        if now - cached > _MAX_CACHE_AGE_SECS:
            ui_out.debug("Expiring old cached copy of resource.")
            self._remove(url)
            return False
        ui_out.debug("Found cached copy of resource.")
        return True

    def _remove(self, url):
        self.cache_timestamps.pop(url)
        mime, filename = self.cache.pop(url)
        os.unlink(filename)
        self.validatecache()

    def add(self, url, mime, filename):
        # Copy client's buffer file to new cache file
        tmpf = tempfile.NamedTemporaryFile(dir=self.tempdir.name, delete=False)
        tmpf.close()
        shutil.copyfile(filename, tmpf.name)
        # Remember details
        self.cache_timestamps[url] = time.time()
        self.cache[url] = (mime, tmpf.name)
        if len(self.cache) > _MAX_CACHE_SIZE:
            self._trim()
        self.validatecache()

    def _trim(self):
        # Order cache entries by age
        lru = [(t, u) for (u, t) in self.cache_timestamps.items()]
        lru.sort()
        # Drop the oldest entry no matter what
        _, url = lru[0]
        ui_out.debug("Dropping cached copy of {} from full cache.".format(url))
        self._remove(url)
        # Drop other entries if they are older than the limit
        now = time.time()
        for cached, url in lru[1:]:
            if now - cached > _MAX_CACHE_AGE_SECS:
                ui_out.debug("Dropping cached copy of {} from full cache.".format(url))
                self._remove(url)
            else:
                break
        self.validatecache()

    def get(self, url):
        return self.cache[url]

    def validatecache(self):
        assert self.cache.keys() == self.cache_timestamps.keys()
        for _, filename in self.cache.values():
            assert os.path.isfile(filename)

