"""This module holds the views for the ``photostories`` app."""

from django.contrib import messages
from django.db.models import Count
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import get_object_or_404, redirect
from django.utils.functional import cached_property
from django.utils.translation import ugettext_lazy as _
from django.views.generic import DetailView, ListView

from mtp.apps.common.views_utils import (
    AjaxResponseMixin,
    ExportFileMixin
)
from mtp.apps.trainings.models import TrainingSession
from mtp.apps.trainings.views.activities import (
    TrainingActivityCreateBase,
    TrainingActivityDetailBase,
    TrainingActivityEditBase,
)

from .exports import StripExportError
from .models import Photostory


class PhotostoryBase(TrainingActivityDetailBase):
    """Base view to use on all views related to the ``Photostory`` model.

    Define the queryset to use for the current user.

    """

    def get_queryset(self):
        """Get all ``Photostory`` instances the current user is allowed to see.

        The user can only see photostory instance he own.
        Also excludes deleted photostory from the result.

        Returns
        -------
        Queryset of ``mtp.apps.photostories.models.Photostory``
            A lazy queryset with the wanted photostories.

        """

        return super().get_queryset().instance_of(Photostory)

    def get_success_url(self):
        """Get the url where to go back when an action is done on a ``Photostory``"""

        return self.object.get_detail_url()


class PhotostoryEditBase(AjaxResponseMixin,
                         PhotostoryBase):
    """Edit base for ``Photostory`` model."""

    model = Photostory
    fields = ['name', 'description']
    pk_url_kwarg = 'photostory_uuid'


class PhotostoryCreateView(PhotostoryEditBase, TrainingActivityCreateBase):
    """Create view for ``Photostory`` instance."""

    success_message = _('Your photostory was successfully created.')


class PhotostoryDetailView(PhotostoryEditBase, DetailView):
    """Detail view for ``Photostory`` instance."""

    success_message = _('Your photostory was successfully created.')


class PhotostoryListViewBySession(PhotostoryEditBase, ListView):
    """List view for ``Photostory`` instance."""

    @cached_property
    def session(self):
        """Get the current session.

        Returns
        -------
        TrainingSession

        """

        return get_object_or_404(TrainingSession, id=self.kwargs['session_uuid'])

    def get_queryset(self):
        """Filter the photostories by session.

        Returns
        -------
        QuerySet of Photostory

        """

        return Photostory.objects.non_deleted().for_session(self.session)

    def get_context_data(self, **kwargs):  # pylint: disable=missing-param-doc
        """Create context data for template render."""

        queryset = self.get_queryset().filter(strips__session=self.session).annotate(
            strips_count=Count('strips', distinct=True),
            photos_count=Count('strips__photos'))

        strips_count = {}
        photos_count = {}

        # Init for photostory with no strip that are filtered in `queryset`
        for photostory in self.get_queryset():
            strips_count[photostory] = 0
            photos_count[photostory] = 0

        for photostory in queryset:
            strips_count[photostory] = photostory.strips_count
            photos_count[photostory] = photostory.photos_count

        return super().get_context_data(
            session=self.session,
            strips_count=strips_count,
            photos_count=photos_count,
            **kwargs
        )


class PhotostoryUpdateView(PhotostoryEditBase, TrainingActivityEditBase):
    """Update view for ``Photostory`` instance."""

    success_message = _('Your photostory was successfully updated.')


class PhotostoryExportView(ExportFileMixin, PhotostoryEditBase, DetailView):
    """Export view for ``Photostory`` instance.

    Attributes
    ----------
    response_class: Response
        The response class to use to export photostory archive.

    """

    response_class = HttpResponse

    @cached_property
    def session(self):
        """Get the current session.

        Returns
        -------
        TrainingSession or None
            Return the wanted session or None if no session is available

        """

        try:
            return get_object_or_404(TrainingSession, id=self.kwargs['session_uuid'])
        except KeyError:
            return None

    def get_filename(self):
        """Get the filename of the photostory archive.

        Returns
        -------
        str

        """

        return self.object.name

    def render_to_response(self, context, **response_kwargs):
        """Render a response to download the photostory archive.

        Parameters
        ----------
        For the parameters, see the ``DetailView`` class.

        Returns
        -------
        HttpResponse

        """

        try:
            archive = self.object.create_archive(self.session)
        except StripExportError as error:
            messages.error(self.request, str(error))
            try:
                return HttpResponseRedirect(self.request.META['HTTP_REFERER'])
            except KeyError:
                return redirect('cms')

        response = self.response_class(content_type=archive.content_type, **response_kwargs)
        response.write(archive.data)
        response['Content-Disposition'] = 'attachment; filename=%s.%s' % (
            self.get_slugified_filename(),
            archive.extension
        )

        return response
