from BTrees.OOBTree import OOBTree
from plone import api
from plone.memoize.view import memoize
from plone.namedfile.file import NamedBlobImage
from plone.rfc822.interfaces import IPrimaryFieldInfo
from ploneintranet.docconv.client.browser.base import CommandView
from ploneintranet.docconv.client.previews import PREVIEW_URL
from zope.annotation import IAnnotations
from zope.datetime import rfc1123_date

import logging
import os

logger = logging.getLogger(__name__)

try:
    from sh import ffmpegthumbnailer
except ImportError:
    # Missing
    logger.error(
        "No `ffmpegthumbnailer` command in your PATH. "
        "Preview generation will not work for video files."
    )
    ffmpegthumbnailer = None


class Poster(CommandView):

    command = ffmpegthumbnailer

    storage_key = "ploneintranet.poster"

    @property
    @memoize
    def _field(self):
        """The field containing the video"""
        pfi = IPrimaryFieldInfo(self.context)
        return pfi.value

    @property
    @memoize
    def arguments(self):
        with self._field._blob.open() as fp:
            return [
                "-s",
                "0",
                "-i",
                fp.name,
                "-o",
                os.path.join(self.get_tempdir().name, "poster.jpg"),
            ]

    def set_headers(self):
        headers = {
            "Last-Modified": rfc1123_date(self.timestamp),
            "content-disposition": 'attachment; filename="poster.jpg"',
            "Accept-Ranges": "bytes",
            "Content-Length": len(self.payload),
            "Content-Type": "image/jpeg",
        }
        for key in headers:
            self.request.response.setHeader(key, headers[key])

    @property
    @memoize
    def timestamp(self):
        return self.context.file._blob._p_mtime

    @property
    def image(self):
        annotations = IAnnotations(self.context)
        return annotations.get(self.storage_key, {}).get(self.timestamp)

    @property
    @memoize
    def payload(self):
        image = self.image
        return image and image.data

    def is_needed(self):
        """This command is we do not have a field containing the video or if
        its content type is not a video one or if we already have a poster
        matching the file we have
        """
        field = self._field
        if not field:
            return False
        if not field.contentType.startswith("video/"):
            return False

        annotations = IAnnotations(self.context)
        if self.timestamp in annotations.get(self.storage_key, {}):
            return False

        return True

    def post_command(self):
        """Get the produced poster jpeg and save it as a lead image"""
        oufile = self.arguments[-1]
        annotations = IAnnotations(self.context)
        with open(oufile, "rb") as fp:
            poster = NamedBlobImage(data=fp.read(), filename="poster.jpg")
            annotations[self.storage_key] = OOBTree({self.timestamp: poster})

    def generate_poster(self, force=False):
        """Generate a poster image for the video using ffmpegthumbnailer"""
        self.run(force=force)
        return "OK"

    def __call__(self):
        data = self.payload
        if not data:
            return self.request.RESPONSE.redirect(
                "/".join((api.portal.get().absolute_url(), PREVIEW_URL)), status=307
            )

        self.set_headers()
        return data
