import os
from django.conf import settings
from django.core.cache import cache
from django.template import TemplateDoesNotExist
from django.core.exceptions import ImproperlyConfigured
from django.utils.encoding import smart_unicode, force_unicode

class BaseCacheBackend(object):
    """
    Base class for custom cache backend of dbtemplates to be used while
    subclassing.

    Set DBTEMPLATES_CACHE_BACKEND setting to the Python path to that subclass.
    """
    def _site(self):
        from django.contrib.sites.models import Site
        return Site.objects.get_current()
    site = property(_site)

    def load(self, name):
        """
        Loads a template from the cache with the given name.
        """
        raise NotImplemented

    def save(self, name, content):
        """
        Saves the given template content with the given name in the cache.
        """
        raise NotImplemented

    def remove(self, name):
        """
        Removes the template with the given name from the cache.
        """
        raise NotImplemented

class DjangoCacheBackend(BaseCacheBackend):
    """
    A cache backend that uses Django's cache mechanism.
    """
    def _cache_key(self, name):
        return 'dbtemplates::%s::%s' % (name, self.site.pk)

    def load(self, name):
        cache_key = self._cache_key(name)
        return cache.get(cache_key)

    def save(self, name, content):
        cache_key = self._cache_key(name)
        cache.set(cache_key, content)

    def remove(self, name):
        cache_key = self._cache_key(name)
        cache.delete(cache_key)

class FileSystemBackend(BaseCacheBackend):
    """
    A cache backend that uses simple files to hold the template cache.
    """
    def __init__(self):
        try:
            self.cache_dir = getattr(settings, 'DBTEMPLATES_CACHE_DIR', None)
            self.cache_dir = os.path.normpath(self.cache_dir)
            if not os.path.isdir(self.cache_dir):
                pass
        except:
            raise ImproperlyConfigured("You're using the dbtemplates file system cache backend without having set the DBTEMPLATES_CACHE_DIR setting to a valid value. Make sure the directory exists and is writeable for the user your Django instance is running with.")
        super(FileSystemBackend, self).__init__()

    def _filepath(self, name):
        return os.path.join(self.cache_dir, self.site.domain, name)

    def load(self, name):
        try:
            filepath = self._filepath(name)
            return open(filepath).read().decode('utf-8')
        except:
            return None

    def save(self, name, content, retry=False):
        try:
            filepath = self._filepath(name)
            dirname = os.path.dirname(filepath)
            if not os.path.exists(dirname):
                os.makedirs(dirname)            
            cache_file = open(filepath, 'w')
            cache_file.write(force_unicode(content).encode('utf-8'))
            cache_file.close()
        except Exception:
            raise

    def remove(self, name):
        try:
            filepath = self._filepath(name)
            os.remove(filepath)
        except:
            pass
