from calendar import timegm

from django.db.models import Max
from django.http import HttpResponse
from django.utils.http import http_date, parse_http_date_safe
from rest_framework.filters import OrderingFilter


class RichOrderingFilter(OrderingFilter):

    def filter_queryset(self, request, queryset, view):
        ordering = self.get_ordering(request, queryset, view)

        if ordering:
            if hasattr(view, 'ordering_custom'):
                newo = []
                for ordering_part in ordering:
                    ob = view.ordering_custom.get(ordering_part)
                    if ob:
                        ob = dict(ob)
                        newo.append(ob.pop('_order'))
                        queryset = queryset.annotate(**ob)
                    else:
                        newo.append(ordering_part)
                ordering = newo
            return queryset.order_by(*ordering)

        return queryset


class ConditionalListView:

    def list(self, request, **kwargs):
        if_modified_since = request.headers.get('If-Modified-Since')
        if if_modified_since:
            if_modified_since = parse_http_date_safe(if_modified_since)
        if_unmodified_since = request.headers.get('If-Unmodified-Since')
        if if_unmodified_since:
            if_unmodified_since = parse_http_date_safe(if_unmodified_since)
        if not hasattr(request, 'event'):
            return super().list(request, **kwargs)

        lmd = request.event.logentry_set.filter(
            content_type__model=self.get_queryset().model._meta.model_name,
            content_type__app_label=self.get_queryset().model._meta.app_label,
        ).aggregate(
            m=Max('datetime')
        )['m']
        if lmd:
            lmd_ts = timegm(lmd.utctimetuple())

        if if_unmodified_since and lmd and lmd_ts > if_unmodified_since:
            return HttpResponse(status=412)

        if if_modified_since and lmd and lmd_ts <= if_modified_since:
            return HttpResponse(status=304)

        resp = super().list(request, **kwargs)
        if lmd:
            resp['Last-Modified'] = http_date(lmd_ts)
        return resp
