from django.core.cache import cache


class CachedSingleton:
    def __init__(self, cache_key):
        self._cache_key = cache_key

    def __call__(self, cls):
        def save(_self, *args, **kwargs):
            # Store only one instance of model
            _self.id = 1
            cls.objects.exclude(id=_self.id).delete()

            # Model's default save
            _self._model_save(*args, **kwargs)

            # Store model instance in cache
            cache.set(self._cache_key, _self)

        def load(_self) -> cls:
            """Load instance from cache or create new one in DB"""
            obj = cache.get(self._cache_key)

            if not obj:
                obj, _ = cls.objects.get_or_create(id=1)
                cache.set(self._cache_key, obj)
            return obj

        # Save old Model.save() method first
        setattr(cls, '_model_save', cls.save)

        # Then, override it with decorator's one
        setattr(cls, 'save', save)

        # Set the singleton loading method
        setattr(cls, 'load', classmethod(load))
        return cls
