from datetime import timedelta
from logging import getLogger
from plone import api
from plone.app.blocks.interfaces import IBlocksTransformEnabled
from plone.app.contenttypes.interfaces import IEvent
from plone.app.event.base import localized_now
from plone.memoize.view import memoize_contextless
from ploneintranet.calendar.content import ICentralCalendar
from ploneintranet.calendar.utils import escape_id_to_class
from ploneintranet.core import _
from ploneintranet.layout.interfaces import IAppView
from ploneintranet.search.interfaces import ISiteSearch
from ploneintranet.workspace.interfaces import IBaseWorkspaceFolder
from Products.Five import BrowserView
from scorched.dates import solr_date
from zope.component import getUtility
from zope.interface import implementer

logger = getLogger(__name__)


@implementer(IBlocksTransformEnabled)
@implementer(IAppView)
class View(BrowserView):
    """The (global) calendar app view"""

    app_name = "calendar"
    title = _("label_title_app_calendar", default="Calendar")
    _group_types = ["ploneintranet.userprofile.workgroup"]

    @memoize_contextless
    def get_authenticated_groupids(self):
        """Look for user groups"""
        user = api.user.get_current()
        if not user:
            return []
        userid = user.getId()
        only_membrane_groups = api.portal.get_registry_record(
            "ploneintranet.userprofile.only_membrane_groups", default=False
        )
        if only_membrane_groups:
            mt = api.portal.get_tool("membrane_tool")
            groups = [
                b.getGroupId
                for b in mt.unrestrictedSearchResults(
                    workspace_members=userid, portal_type=self._group_types
                )
                if b.getGroupId
            ]
        else:
            groups = [
                x.getId() for x in api.group.get_groups(user=user) if x is not None
            ]
        groups.append(userid)
        return groups

    @memoize_contextless
    def get_central_calendars(self):
        """ """
        query = dict(object_provides=ICentralCalendar.__identifier__, is_archived=False)
        sitesearch = getUtility(ISiteSearch)
        data = sitesearch.query(filters=query, step=99999)
        return data

    @memoize_contextless
    def get_workspaces(self):
        """Look for workspaces the user can view"""
        query = dict(
            object_provides=IBaseWorkspaceFolder.__identifier__, is_archived=False
        )
        sitesearch = getUtility(ISiteSearch)
        data = sitesearch.query(filters=query, step=99999)
        return data

    @property
    @memoize_contextless
    def _events_base_query(self):
        fullcalendar_day_span = api.portal.get_registry_record(
            "ploneintranet.calendar.fullcalendar_day_span", default=30
        )
        evt_date = localized_now() - timedelta(fullcalendar_day_span)
        query = {
            "object_provides": IEvent.__identifier__,
            "end__gt": solr_date(evt_date),
        }
        return query

    def _get_events_parent_paths(self, **kw):
        filters = self._events_base_query
        filters.update(kw)
        sitesearch = getUtility(ISiteSearch)
        # TODO allow passing facet_fields to sitesearch.query()
        # sitesearch.query(filters=filters, facet_fields=("path_parents",), step=0)
        query_obj = sitesearch.create_lucene_query(None)
        query_obj = sitesearch._wrap_query_object(query_obj)
        query_obj = query_obj.facet_by(fields=("path_parents",), limit=-1)
        query_obj = query_obj.paginate(rows=0)
        query_obj = sitesearch._apply_filters(query_obj, filters)
        events = sitesearch.execute(query=query_obj)

        paths = [
            facet[0]
            for facet in events.facet_counts.facet_fields["path_parents"]
            if facet[1] > 0
        ]
        return paths

    def get_calendars(self):
        workspaces = self.get_workspaces()

        cal_paths = self._get_events_parent_paths()
        workspace_calendars = [ws for ws in workspaces if ws.getPath() in cal_paths]

        invited_paths = self._get_events_parent_paths(
            invitees=[api.user.get_current().getId()]
        )
        invited_calendars = [ws for ws in workspaces if ws.getPath() in invited_paths]

        calendars = {
            "central": self.get_central_calendars(),
            "my": workspace_calendars,
            "invited": invited_calendars,
        }
        return calendars

    def id2class(self, cal, suffix=None):
        klass = f"cal-cat-{escape_id_to_class(cal)}"
        if suffix:
            klass = "-".join((klass, suffix))
        return klass
