from itertools import islice
from json import dumps
from plone import api
from plone.base.permissions import AddPortalContent
from plone.memoize.view import memoize_contextless
from ploneintranet.search.interfaces import ISiteSearch
from ploneintranet.workspace.interfaces import IBaseWorkspaceFolder
from ploneintranet.workspace.superspace import ISuperspaceFolder
from Products.Five import BrowserView
from zope.component import getUtility


class CanAddInSharedCalendar(BrowserView):
    @property
    def shared_calendar(self):
        return self.context.shared_calendar and self.context.shared_calendar.to_object

    def auto_accepts(self):
        shared_calendar = self.shared_calendar
        return shared_calendar and (
            shared_calendar.automatically_accept or self.can_add()
        )

    def can_add(self):
        shared_calendar = self.shared_calendar
        return shared_calendar and api.user.has_permission(
            AddPortalContent, obj=shared_calendar
        )


class CalendarPickerJSONView(BrowserView):
    limit = 10

    def get_brains(self, phrase=None, limit=None):
        workspace_container = api.portal.get().get("workspaces")
        filters = {
            "!object_provides": ISuperspaceFolder.__identifier__,
            "object_provides": IBaseWorkspaceFolder.__identifier__,
            "path": "/".join(workspace_container.getPhysicalPath()),
            "is_archived": False,
        }
        sitesearch = getUtility(ISiteSearch)
        if not limit:
            # Get 10 times the limit to have a reasonable change to have enough
            # Good candidate
            limit = self.limit * 10
        return sitesearch.query(
            phrase=phrase, filters=filters, step=limit, sort="sortable_title"
        )

    @memoize_contextless
    def has_writable_workspaces(self):
        pm = api.portal.get_tool("portal_membership")
        for brain in self.get_brains(limit=9999):
            obj = brain.getObject()
            if pm.checkPermission(AddPortalContent, obj):
                return True
        return False

    def get_json(self):
        phrase = self.request.get("q", "")
        limit = None
        if not phrase:
            limit = self.limit * 2
        brains = self.get_brains(phrase, limit)
        objs = (brain.getObject() for brain in brains)
        pm = api.portal.get_tool("portal_membership")
        writable_objs = (
            obj for obj in objs if pm.checkPermission(AddPortalContent, obj)
        )
        return dumps(
            [
                {"id": "/".join(obj.getPhysicalPath()), "text": obj.title}
                for obj in islice(writable_objs, self.limit)
            ]
        )

    def __call__(self):
        self.request.response.setHeader("Content-type", "application/json")
        return self.get_json()
