from django.contrib.auth import get_user_model
from django.db.models import Q
from django.shortcuts import get_object_or_404
from django.utils.functional import cached_property

from rest_framework.viewsets import ModelViewSet
from rest_framework.filters import OrderingFilter

from event.models import Activity, ActivityTag, ActivityTemplate, Event, Place

from .serializers import (
    ActivitySerializer, ActivityTagSerializer, ActivityTemplateSerializer,
    EventSerializer, PlaceSerializer,
)

User = get_user_model()


# classes utilitaires

class EventUrlViewSetMixin:
    """
    ViewSet mixin to handle the evenk_pk from url.
    """

    @cached_property
    def event(self):
        event_pk = self.kwargs.get('event_pk')
        if event_pk:
            return get_object_or_404(Event, pk=event_pk)
        return None


class EventModelViewSetMixin:

    def perform_create(self, serializer):
        serializer.save(event=self.event)

    def perform_update(self, serializer):
        serializer.save(event=self.event)


class EventModelViewSet(
            EventModelViewSetMixin,
            EventUrlViewSetMixin,
            ModelViewSet,
        ):
    pass


class EventSpecificModelViewSet(EventModelViewSet):
    """
    ViewSet that returns :
    * rootlevel objects if no Event is specified
    * OR objects related to the specified event
         AND root level objects
    if an event is specified it passes the event_pk
    to the save method. Works fine with serializers.EventSpecificSerializer
    Useful for models that extends EventSpecificMixin
    """

    def get_queryset(self):
        """
        Warning : You may want to override this method
        and not call with super
        """
        queryset = super().get_queryset()
        filters = Q(event=None)
        if self.event:
            filters |= Q(event=self.event)
        return queryset.filter(filters)


# ViewSets
class EventViewSet(ModelViewSet):
    queryset = Event.objects.all()
    serializer_class = EventSerializer

    filter_backends = (OrderingFilter,)
    ordering_fields = ('title', 'creation_date', 'beginning_date',
                       'ending_date', )
    ordering = ('beginning_date', )

    def perform_create(self, serializer):
        serializer.save(created_by=self.request.user)


class PlaceViewSet(EventSpecificModelViewSet):
    queryset = Place.objects.all()
    serializer_class = PlaceSerializer

    filter_backends = (OrderingFilter,)
    ordering_fields = ('name', )
    ordering = ('name', )


class ActivityTagViewSet(EventSpecificModelViewSet):
    queryset = ActivityTag.objects.all()
    serializer_class = ActivityTagSerializer

    filter_backends = (OrderingFilter,)
    ordering_fields = ('is_public', 'name', )
    ordering = ('is_public', 'name', )


class ActivityTemplateViewSet(EventModelViewSet):
    queryset = ActivityTemplate.objects.all()
    serializer_class = ActivityTemplateSerializer

    filter_backends = (OrderingFilter,)
    ordering_fields = ('title', )
    ordering = ('title', )


class ActivityViewSet(EventModelViewSet):
    queryset = Activity.objects.all()
    serializer_class = ActivitySerializer

    filter_backends = (OrderingFilter,)
    ordering_fields = ('title', )
    ordering = ('title', )