"""This module contains the apiv2-related views of the ``documents`` app"""

import os

from django.conf import settings
from django.http import Http404
from django.shortcuts import get_object_or_404
from django.utils import formats
from django.utils.functional import cached_property

from rest_framework import viewsets
from rest_framework.views import APIView

from mtp.apps.api.permissions import IsAuthenticated
from mtp.apps.api.renderers import TemplatePDFRenderer
from mtp.apps.pdf_reporting.views import PDFReportMixin
from mtp.apps.trainings.models import TrainingSession

from ..models import Document

from .serializers import DocumentSerializer


class DocumentViewSet(viewsets.ReadOnlyModelViewSet):
    """ViewSet for the ``Document`` model"""

    permission_classes = [IsAuthenticated]
    serializer_class = DocumentSerializer
    queryset = Document.objects.non_deleted()


class AnnotatedDocumentPdfDownloadView(APIView, PDFReportMixin):
    """API View to download an annotated document as a pdf file"""

    renderer_classes = [TemplatePDFRenderer]
    permission_classes = [IsAuthenticated]
    template_name = 'rml/document_with_notes.rml'

    @cached_property
    def session(self):
        """Get the session from the url

        Returns
        -------
        TrainingSession

        Raises
        ------
        Http404
            If the session is not found.

        """

        return get_object_or_404(
            TrainingSession.objects.non_deleted(),
            pk=self.kwargs['session_uuid']
        )

    @cached_property
    def document(self):
        """Get the document from the url

        Returns
        -------
        Document

        Raises
        ------
        Http404
            If the document is not found.

        """

        return get_object_or_404(
            Document.objects.non_deleted(),
            pk=self.kwargs['document_uuid']
        )

    def get_filename(self):
        """Get the pdf filename

        Returns
        -------
        str

        """

        return "%(document)s_%(short_date)s_%(user)s" % {
            'document': self.document.name,
            'short_date': formats.date_format(self.session.start_date, "SHORT_DATE_FORMAT"),
            'user': self.request.user
        }

    def get_context_data(self, **kwargs):
        """Add the document, the document images and user's notes to the context

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

        Raises
        ------
        Http404
            If no user notes or no images exists for the current document

        """

        notes = list(self.document.note_set.filter(
            session=self.session,
            user=self.request.user
        ).non_deleted())

        # We don't have any notes for the given session / user / document
        # or the document don't have any generated images.
        if not notes or not self.document.pdf_images_url_list:
            raise Http404

        def get_image_absolute_path(image_relative_path):
            """Shortcut method to get the pdf image absolute path

            - Remove the "/media/" from the file path, as the "pdf_images_url_list"
            - Add the ``MEDIA_ROOT`` to have the absolute path

            Parameters
            ----------
            image_relative_path: str
                The relative path of the image url.

            Returns
            -------
            str

            """

            return os.path.abspath(os.path.join(
                settings.MEDIA_ROOT,
                '/'.join(image_relative_path.split('/')[2:])
            ))

        images_with_notes = [
            {
                # Remove the "/media/" from the file path, as the "pdf_images_url_list"
                # from above return the image paths including the "/media/" part and we
                # are adding the `MEDIA_ROOT` to the path in the template.
                'image': get_image_absolute_path(image_url),
                'notes': [
                    note.text
                    for note in notes
                    if note.page == page_index
                ]
            }
            for page_index, image_url in enumerate(self.document.pdf_images_url_list, start=1)
        ]

        return super().get_context_data(
            images_with_notes=images_with_notes,
            document=self.document,
            session=self.session,
            **kwargs
        )

    def get(self, request, *args, **kwargs):  # pylint: disable=unused-argument
        """Render the response

        For the parameters, see ``rest_framework.views.APIView``

        """

        context = self.get_context_data(**kwargs)

        return self.render_to_response(context)
