from django.db import models
from django.contrib.auth.models import Permission, AbstractUser
from knox.models import AuthToken

from inventory.models import Event


class ExtendedUser(AbstractUser):
    permissions = models.ManyToManyField(Permission, through='EventPermission', through_fields=('user', 'permission'))

    class Meta:
        verbose_name = 'Extended user'
        verbose_name_plural = 'Extended users'

    def get_permissions(self):
        if self.is_superuser:
            for permission in Permission.objects.all():
                yield "*:" + permission.codename
        for permission in self.user_permissions.all():
            yield "*:" + permission.codename
        for group in self.groups.all():
            for permission in group.permissions.all():
                yield "*:" + permission.codename
        for permission in self.event_permissions.all():
            yield permission.event.slug + ":" + permission.permission.codename

    def has_event_perm(self, event, permission):
        if self.is_superuser:
            return True
        permissions = set(self.get_permissions())
        if "*:" + permission in permissions:
            return True
        if event.slug + ":" + permission in permissions:
            return True
        return False


class ExtendedAuthToken(AuthToken):
    permissions = models.ManyToManyField('EventPermission', through='AuthTokenEventPermissions',
                                         through_fields=('token', 'permission'))

    class Meta:
        verbose_name = 'Extended auth token'
        verbose_name_plural = 'Extended auth tokens'


class EventPermission(models.Model):
    user = models.ForeignKey(ExtendedUser, on_delete=models.CASCADE, related_name='event_permissions')
    permission = models.ForeignKey(Permission, on_delete=models.CASCADE)
    event = models.ForeignKey(Event, on_delete=models.CASCADE, null=True, blank=True)

    class Meta:
        unique_together = ('user', 'permission', 'event')


class AuthTokenEventPermissions(models.Model):
    token = models.ForeignKey(ExtendedAuthToken, on_delete=models.CASCADE)
    permission = models.ForeignKey(EventPermission, on_delete=models.CASCADE)
    event = models.ForeignKey(Event, on_delete=models.CASCADE)

    class Meta:
        unique_together = ('token', 'permission', 'event')