""" All views to display or edit events and event-photos. """
from datetime import timedelta

from django.contrib.auth import get_user_model
from django.contrib.auth.mixins import PermissionRequiredMixin
from django.urls import reverse
from django.db.models import Q
from django.http import HttpResponse, Http404
from django.shortcuts import redirect
from django.utils import timezone
from django.utils.translation import ugettext as _
from django.views import generic
from extra_views import InlineFormSetView
from icalendar import Calendar, Event

from . import forms, mixins, models


class DeleteEventPhoto(PermissionRequiredMixin, mixins.EventDetailMixin,
                       generic.DeleteView):
    """Delete a requested photo and redirect to the album view."""
    model = models.Photo
    permission_required = 'events.delete_photo'

    def get_success_url(self):
        """Redirect to the album view of the event from the deleted image."""
        return reverse('event-photo-list', args=[self.object.event_id])


class EventArchiveIndex(mixins.EventArchiveMixin, generic.ArchiveIndexView):
    """Index of the event archive, displays the upcoming events first."""
    allow_empty = True


class EventArchiveMonth(mixins.EventArchiveMixin, generic.MonthArchiveView):
    """List the events from the specific month of the given year."""
    month_format = '%m'


class EventArchiveYear(mixins.EventArchiveMixin, generic.YearArchiveView):
    """List all events from the specified year."""
    year_format = '%Y'


class EventDetail(mixins.EventDetailMixin, generic.DetailView):
    """Detail View to see all details of an event."""
    model = models.Event


class EventForm(PermissionRequiredMixin, mixins.EventDetailMixin,
                generic.UpdateView):
    """Frontend formular to add or edit a Event."""
    form_class = forms.EventForm
    template_name = 'events/event_form.html'
    permission_required = 'events.add_event'

    def get_context_data(self, **kwargs):
        """Dynamicle set the title to Add or Edit Event, depanding if an
        event ID was given, or not."""
        context = super(EventForm, self).get_context_data(**kwargs)
        if self.kwargs.get('pk'):
            context['title'] = _("Edit Event")
        else:
            context['title'] = _("Add Event")
        return context

    def get_object(self, queryset=None):
        """Try return the existing Event for an update if an id has been
        submitted, else create a new one.
        """
        return models.Event.objects.get(pk=self.kwargs['pk']) \
            if self.kwargs.get('pk') else models.Event()


class EventGallery(generic.ListView):
    """Display a overview of all event photo albums."""
    template_name = 'events/photo_gallery.html'
    queryset = models.Event.objects.filter(
        start__lt=timezone.now(),
        event_series__isnull=True,
        photo_count__gt=0
    )
    paginate_by = 12


class EventListIcal(generic.View):
    """Generates an returns an iCal File with all upcoming events."""

    def get(self, request, *args, **kwargs):
        """Add all upcoming events to an .ics file and send it."""
        response = HttpResponse(content_type="text/calendar; charset=UTF-8")
        calendar = Calendar()
        calendar.add('prodid', 'http://www.kasu.at/')
        calendar.add('version', '2.0')
        for event in models.Event.objects.upcoming(limit=None):
            ics_event = Event()
            ics_event.add('DTSTART', timezone.localtime(event.start))
            ics_event.add('SUMMARY', event.name)
            ics_event.add('DESCRIPTION', event.description)
            ics_event.add('LOCATION', event.location.address)
            ics_event.add('URL',
                          'http://www.kasu.at' + event.get_absolute_url())
            ics_event['UID'] = 'event-%d@www.kasu.at' % event.pk
            ics_event.add('PRIORITY', 5)
            if event.end:
                ics_event.add('DTEND', timezone.localtime(event.end))
            calendar.add_component(ics_event)
        response.write(calendar.to_ical())
        return response


class EventPhoto(mixins.EventDetailMixin, generic.UpdateView):
    """Display the requested Photo and allows rotation if the user has change
    permissions."""
    form_class = forms.EditPhotoForm
    model = models.Photo
    template_name = 'events/photo_detail.html'

    def post(self, request, *args, **kwargs):
        if request.POST.get('rotate') and request.user.has_perm(
                'events.change_photo'):
            photo = models.Photo.objects.get(pk=kwargs['pk'])
            photo.rotate(request.POST['rotate'])
            return self.get(request)
        else:
            return generic.UpdateView.post(self, request, *args, **kwargs)


class EventPhotoList(mixins.EventDetailMixin, generic.ListView):
    """List all Photos of the event or event series in an album."""
    context_object_name = 'photo_list'
    event = None
    paginate_by = 36

    def get_context_data(self, **kwargs):
        context = super(EventPhotoList, self).get_context_data(**kwargs)
        context['form'] = forms.PhotoUploadForm(
            initial={'event': self.event, 'photographer': self.request.user})
        return context

    def get_queryset(self):
        try:
            self.event = models.Event.objects.get(id=self.kwargs['event'])
            return models.Photo.objects.filter(
                Q(event=self.event) |
                Q(event__event_series=self.event)
            )
        except models.Event.DoesNotExist:
            raise Http404(_('Event does not exist'))


class EventPhotoUpload(mixins.EventDetailMixin, generic.FormView):
    form_class = forms.PhotoUploadForm
    template_name = 'events/photo_upload.html'
    permission_required = 'events.add_photo'

    def get_context_data(self, **kwargs):
        context = generic.FormView.get_context_data(self, **kwargs)
        context['event_list'] = models.Event.objects.archive()[:12]
        return context

    def get_initial(self):
        """ Set the current user as default value for the photographer."""
        return {'photographer': self.request.user, }

    def post(self, *args, **kwargs):
        event = models.Event.objects.get(id=self.request.POST.get('event'))
        photographer = get_user_model().objects.get(
            id=self.request.POST.get('photographer', self.request.user.id))
        counter = 0
        for image_file in self.request.FILES.getlist('upload'):
            photo = models.Photo(
                event=event,
                photographer=photographer,
                image=image_file,
                name=image_file.name,
                created_date=event.start + timedelta(minutes=counter),
                description=''
            )
            photo.save()
            counter += 1
        return redirect('event-photo-list', event=event.id)


class EventSeriesForm(mixins.EventDetailMixin, PermissionRequiredMixin,
                      InlineFormSetView):
    model = models.Event
    inline_model = models.Event
    fk_name = 'event_series'
    fields = ('start', 'end')
    form_class = forms.EventForm
    extra = 3
    permission_required = 'events.add_event'
    template_name = 'events/eventseries_form.html'

    def get_object(self, queryset=None):
        self.event = models.Event.objects.get(pk=self.kwargs['pk'])
        if self.event.event_series:
            self.event = self.event.event_series
        return self.event


class UpcomingEvents(generic.ListView):
    queryset = models.Event.objects.upcoming(limit=None)
    paginate_by = 16
