from plone import api
from plone.memoize.view import memoize
from plone.namedfile.file import NamedBlobImage
from ploneintranet.core import _
from ploneintranet.layout.browser.base import BasePanel
from Products.Five import BrowserView

import json
import requests


class Carousel(BrowserView):
    @memoize
    def should_show_carousel(self):
        """
        Return True if the carousel should be shown
        """
        if self.context.carousel_show_as == "hidden":
            return False
        if not self.carousel_slides:
            return False
        return True

    def should_show_carousel_above(self):
        if self.context.carousel_position != "above":
            return False
        return self.should_show_carousel()

    def should_show_carousel_below(self):
        if self.should_show_carousel_above():
            return False
        return self.should_show_carousel()

    @property
    def carousel_height(self):
        return self.context.carousel_height or "adaptive"

    @property
    @memoize
    def carousel_slides(self):
        """
        Return a list of slides for the carousel
        """
        slides = []
        for relation in self.context.carousel_slides:
            obj = relation.to_object
            if obj:
                slides.append(obj)
        return slides


class BrowseGalleryPanel(BasePanel):

    title = _("label_image_gallery", "Image gallery")
    panel_size = "large"
    _form_data_pat_inject_parts = (
        "#global-statusmessage; loading-class: ''",
        "#image-gallery-fieldset",
    )

    @property
    @memoize
    def sections(self):
        """Return a list of sections"""
        return api.content.get_view(
            "view", self.context.aq_parent, self.request
        ).app.sections()

    def get_section_images(self, section):
        extra_query = {}
        if self.selected_uids:
            extra_query["UID"] = {"not": self.selected_uids}
        return api.content.find(
            context=section,
            portal_type="Image",
            **extra_query,
        )

    @property
    @memoize
    def selected_uids(self):
        """The list of thew currently selected carousel slides"""
        objs = filter(None, [obj.to_object for obj in self.context.carousel_slides])
        return [obj.UID() for obj in objs]

    @property
    def available_images(self):
        uid = self.request.form.get("uid")
        if not uid:
            return []
        obj = api.content.get(UID=uid)
        if not obj:
            return []
        return self.get_section_images(obj)

    def execute_on_post(self):
        uids = self.request.form.get("carousel_image")
        if not uids:
            return
        new_uids = set(uids) - set(self.selected_uids)
        for uid in new_uids:
            obj = api.content.get(UID=uid)
            if obj:
                api.relation.create(self.context, obj, "carousel_slides")

        return self.redirect(f"{self.context.absolute_url()}/@@edit.html")


class BrowsePixxioPanel(BasePanel):
    title = _("label_image_gallery", "Pixx.io")
    panel_size = "large"
    _form_data_pat_inject_parts = (
        "#global-statusmessage; loading-class: ''",
        "#image-panel-content",
        "#canvas-toolbar-section",
        "#image-gallery-fieldset",
    )

    @property
    @memoize
    def form_action(self):
        """The handler for this form"""
        return "{url}/@@{action}".format(
            url=self.context.absolute_url(),
            action="panel-select-image-pixxio-collection",
        )

    @property
    @memoize
    def collections(self):
        resp = self.pixxio_session.get(
            f"{self.base_url}/gobackend/collections?pageSize=20&page=1", timeout=10
        )
        return json.loads(resp.text)["collections"]

    @memoize
    def images(self, collection_id=None):
        form = self.request.form
        search_term = form.get("search_term")
        collection_id = collection_id or form.get("collection_id")
        if not (search_term or collection_id):
            return []

        # If you filter by "fileType": "image" this also includes PDFs, and possibly
        # other formats that we don't handle. So we can filter by extension instead
        jpeg_filter = {"filterType": "fileExtension", "fileExtension": "jpeg"}
        # This also includes the ".jpg" extension
        png_filter = {"filterType": "fileExtension", "fileExtension": "png"}
        gif_filter = {"filterType": "fileExtension", "fileExtension": "gif"}
        image_filter = {
            "filterType": "connectorOr",
            "filters": [jpeg_filter, png_filter, gif_filter],
        }
        filter = {
            "filterType": "connectorAnd",
            "filters": [image_filter],
        }
        search_term_filter = {"filterType": "searchTerm", "term": search_term}
        if search_term:
            filter["filters"].append(search_term_filter)
        if collection_id:
            collection_filter = {
                "filterType": "collection",
                "collectionID": collection_id,
            }
            filter["filters"].append(collection_filter)
        resp = self.pixxio_session.get(
            f"{self.base_url}/gobackend/files",
            params={
                "page": 1,
                "pageSize": 200,
                "filter": json.dumps(filter),
                "responseFields": json.dumps(
                    [
                        "previewFileURL",
                        "originalFileURL",
                        "id",
                        "fileName",
                        "md5sum",
                        "description",
                    ]
                ),
            },
            timeout=10,
        )
        return json.loads(resp.text).get("files", [])

    @property
    @memoize
    def base_url(self):
        return api.portal.get_registry_record("ploneintranet.news.pixxio_url")

    @property
    @memoize
    def pixxio_session(self):
        application_key = api.portal.get_registry_record(
            "ploneintranet.news.pixxio_application_key"
        )
        refresh_token = api.portal.get_registry_record(
            "ploneintranet.news.pixxio_refresh_token"
        )
        resp = requests.post(
            f"{self.base_url}/gobackend/accessToken",
            data={
                "applicationKey": application_key,
                "refreshToken": refresh_token,
            },
            timeout=10,
        )
        token = json.loads(resp.text)["accessToken"]
        s = requests.Session()
        s.headers["Authorization"] = f"Key {token}"
        return s

    def execute_on_post(self):
        md5sums = self.request.form.get("md5sums")
        if not md5sums:
            # No images have been selected, show the search results
            return
        session = self.pixxio_session
        for md5sum in md5sums:
            image = [i for i in self.images() if i["md5sum"] == md5sum][0]
            file_name = image.get("fileName")
            obj = api.content.create(
                container=self.context.aq_parent,
                type="Image",
                title=file_name,
                description=image.get("description"),
                image=NamedBlobImage(
                    data=session.get(image.get("originalFileURL"), timeout=10).content,
                    filename=file_name,
                ),
            )
            api.relation.create(self.context, obj, "carousel_slides")

        return self.redirect(f"{self.context.absolute_url()}/@@edit.html")
