"""This module contains the views for the ``media`` app"""

from django.shortcuts import get_object_or_404
from django.utils.functional import cached_property
from django.utils.translation import ugettext_lazy as _
from django.views import generic

from mtp.apps.common.views_utils import (
    AjaxResponseMixin,
    SuccessMessageMixin,
    SyncableDeleteView
)
from mtp.apps.trainings.models import Training
from mtp.apps.trainings.views import TrainingBaseView

from .forms import PresentationForm, VideoForm
from .models import Presentation, Video


class PresentationBase(TrainingBaseView):
    """Base view to use on all views related to the presentation."""

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

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

        Returns
        -------
        Queryset of ``mtp.apps.media.models.Presentation``
            A lazy queryset with the wanted presentations.

        """

        return Presentation.objects.non_deleted().filter(
            training__in=self.get_training_queryset_for_current_user()
        )


class PresentationEditBase(AjaxResponseMixin, SuccessMessageMixin, PresentationBase):
    """Base view to view, create or update a given instance of ``Presentation``"""

    model = Presentation
    form_class = PresentationForm
    pk_url_kwarg = 'presentation_uuid'


class PresentationDetailView(PresentationEditBase, generic.DetailView):
    """View to see a ``Presentation`` instance"""

    pass


class PresentationUpdateView(PresentationEditBase, generic.UpdateView):
    """View to update a ``Presentation`` instance"""

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


class PresentationCreateView(PresentationEditBase, generic.CreateView):
    """View to create a ``Presentation`` instance"""

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

    def get_success_url(self):
        """Return the url to go when the ``Video`` is successfully created

        Returns
        -------
        str

        """

        return self.training.get_activity_list_url()

    def get_context_data(self, **kwargs):
        """Add ``training`` to the context.

        For the parameters, see ``django.forms.generic.base.ContextMixin``
        """

        return super().get_context_data(training=self.training, **kwargs)

    @cached_property
    def training(self):
        """Returns the current training based on the ``training_uuid`` argument in the url.

        Raises
        ------
        ``django.http.Http404``
            If the training doesn't exists.

        """

        return get_object_or_404(
            Training.objects.non_deleted().filter(owner=self.request.user),
            pk=self.kwargs['training_uuid']
        )

    def form_valid(self, form):
        """Set the ``training``, save the presentation contents and redirect the user.

        Parameters
        ----------
        form : instance of ``django.forms.models.ModelForm``
            The validated form to save.

        Returns
        -------
        instance of django.http.HttpResponseRedirect
            A redirect to the edit url of the workshop.

        Notes
        -----
        This method doesn't call ``super`` but implements all the necessary
        stuff (saving and redirecting)

        """

        self.object = form.save(commit=False)
        self.object.training = self.training
        self.object.save()

        return super().form_valid(form)


class PresentationDeleteView(PresentationEditBase, SyncableDeleteView):
    """View to delete a ``Presentation`` instance."""

    success_message = _('Your presentation was successfully deleted.')


class VideoBase(TrainingBaseView):
    """Base view to use on all views related to the video."""

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

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

        Returns
        -------
        Queryset of ``mtp.apps.media.models.Video``
            A lazy queryset with the wanted videos.

        """

        return Video.objects.non_deleted().filter(
            training__in=self.get_training_queryset_for_current_user()
        )


class VideoEditBase(AjaxResponseMixin, SuccessMessageMixin, VideoBase):
    """Base view to view, create or update a given instance of ``Video``"""

    model = Video
    form_class = VideoForm
    pk_url_kwarg = 'video_uuid'


class VideoDetailView(VideoEditBase, generic.DetailView):
    """View to see a ``Video`` instance"""

    pass


class VideoUpdateView(VideoEditBase, generic.UpdateView):
    """View to update a ``Video`` instance"""

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

    def form_valid(self, form):
        """Save the video media, the video and redirect the user.

        Parameters
        ----------
        form : instance of ``django.forms.models.ModelForm``
            The validated form to save.

        Returns
        -------
        instance of django.http.HttpResponseRedirect
            A redirect to the edit url of the workshop.

        Notes
        -----
        This method doesn't call ``super`` but implements all the necessary
        stuff (saving and redirecting)

        """

        self.object = form.save(commit=False)
        self.object.media.save()

        self.object.save()

        return super().form_valid(form)


class VideoCreateView(VideoEditBase, generic.CreateView):
    """View to create a ``Video`` instance"""

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

    def get_success_url(self):
        """Return the url to go when the ``Video`` is successfully created

        Returns
        -------
        str

        """

        return self.training.get_activity_list_url()

    def get_context_data(self, **kwargs):
        """Add ``training`` to the context.

        For the parameters, see ``django.forms.generic.base.ContextMixin``

        """

        return super().get_context_data(training=self.training, **kwargs)

    @cached_property
    def training(self):
        """Returns the current training based on the ``training_uuid`` argument in the url.

        Raises
        ------
        ``django.http.Http404``
            If the training doesn't exists.

        """

        return get_object_or_404(
            Training.objects.non_deleted().filter(owner=self.request.user),
            pk=self.kwargs['training_uuid']
        )

    def form_valid(self, form):
        """Set the ``training``, save the video content and the video and redirect the user.

        Parameters
        ----------
        form : instance of ``django.forms.models.ModelForm``
            The validated form to save.

        Returns
        -------
        instance of django.http.HttpResponseRedirect
            A redirect to the edit url of the workshop.

        Notes
        -----
        This method doesn't call ``super`` but implements all the necessary
        stuff (saving and redirecting)

        """

        self.object = form.save(commit=False)
        self.object.media.save()
        self.object.media_id = self.object.media.id

        self.object.training = self.training
        self.object.save()

        return super().form_valid(form)


class VideoDeleteView(VideoEditBase, SyncableDeleteView):
    """View to delete a ``Video`` instance."""

    success_message = _('Your video was successfully deleted.')
