from django.db.models import sql, Manager
from django.contrib.auth.models import AnonymousUser

from intranet.femida.src.permissions.context import context


class EmptyQException(Exception):
    pass


class PermQueryBuilder:

    def __init__(self, prefix=''):
        self.prefix = prefix or ''
        self.user = context.user

    def add_perm_filter(self, query):
        if isinstance(self.user, AnonymousUser):
            query.set_empty()
            return query

        if self.user.is_superuser:
            return query

        try:
            perm_q = self.get_perm_q()
        except EmptyQException:
            query.set_empty()
        else:
            if perm_q:
                query.add_q(perm_q)

        return query

    def get_perm_q(self):
        return None


class PermQuery(sql.Query):

    _perm_query_builder_cls = PermQueryBuilder

    def get_compiler(self, *args, **kwargs):
        if self.can_filter():
            query = self.chain(sql.Query)
            self.add_perm_filter(query)
            compiler = query.get_compiler(*args, **kwargs)
        else:
            compiler = super().get_compiler(*args, **kwargs)

        return compiler

    def set_limits(self, *args, **kwargs):
        if self.can_filter():
            self.add_perm_filter(self)
        return super().set_limits(*args, **kwargs)

    def add_perm_filter(self, query):
        qb = self._perm_query_builder_cls(self.model._perm_prefix)
        query = qb.add_perm_filter(query)
        return query


class PermManager(Manager):

    _perm_query_cls = PermQuery

    def __init__(self, perm_prefix=''):
        super().__init__()
        self._perm_prefix = perm_prefix

    def contribute_to_class(self, *args, **kwargs):
        super().contribute_to_class(*args, **kwargs)
        self.model._perm_prefix = self._perm_prefix

    def get_queryset(self):
        qs = super().get_queryset()
        qs.query = self._perm_query_cls(self.model)
        return qs
