from datetime import timedelta
from plone.memoize.view import memoize
from plone.restapi.serializer.converters import json_compatible
from plone.uuid.interfaces import IUUID
from ploneintranet.calendar.utils import escape_id_to_class
from ploneintranet.restapi.interfaces import ISerializeToJsonSummaryCalendar
from ploneintranet.workspace.utils import parent_workspace
from zope.component import adapter
from zope.interface import implementer
from zope.interface import Interface


@implementer(ISerializeToJsonSummaryCalendar)
@adapter(Interface, Interface)
class SerializeToJsonSummaryCalendar:
    def __init__(self, context, request):
        self.context = context
        self.request = request

    @property
    @memoize
    def proto(self):
        return self.context.restrictedTraverse("@@proto")

    def __call__(self, all_groups=[], all_workspace_paths=[], current_workspace=None):
        it = self.context
        ob = it.getObject()
        if it.portal_type != "Event":
            return

        start = it.start
        end = it.end
        if ob.whole_day:
            start = start.date()
            # fullcalendar allDay as well as icalendar spec is end-exclusive.
            end = end.date() + timedelta(days=1)

        if current_workspace:
            url = it.getURL()
        else:
            url = f"{it.getURL()}?in_calendar=true"

        summary = {
            "@id": json_compatible(url),
            "UID": json_compatible(it.UID),
            "title": json_compatible(it.Title),
            "start": json_compatible(start),
            "end": json_compatible(end),
            "whole_day": json_compatible(ob.whole_day),
            "description": json_compatible(it.Description),
            "location": json_compatible(it.location),
            # "text": "",
            # "color": None,
            # "open_end": ob.open_end,
            # "recurrence": ob.recurrence,
            # "attendees": "",
            # "contact_name": "",
            # "contact_phone": "",
            # "contact_email" "",
        }

        # NOTE: The ``calendar-*`` classes match the id of the ``input`` filter
        #       checkboxes in the sidebar and are used to show/hide events in
        #       fullcalendar.

        is_invited = all_groups.intersection(ob.invitees or []) if all_groups else False

        classes = {"cal-event"}
        if ob.whole_day:
            classes.add("all-day")

        shared_calendar = ob.shared_calendar.to_object if ob.shared_calendar else None
        if shared_calendar and it.review_state == "central_calendar":
            cal_uuid = IUUID(shared_calendar)
            cal_id = shared_calendar.id
            classes.add(f"cal-cat-{cal_id}")
            classes.add("cal-cat-central-calendar")
            classes.add("cal-cat-central-calendar-central")
            classes.add(f"cal-cat-{escape_id_to_class(cal_id)}-central")
            classes.add(f"calendar-central-calendars-{cal_uuid}")
            if is_invited:
                classes.add("cal-cat-central-calendar-invited")
                classes.add(f"cal-cat-{escape_id_to_class(cal_id)}-invited")
                classes.add(f"calendar-invited-events-{cal_uuid}")

        workspace = parent_workspace(ob)
        if workspace:

            if current_workspace and workspace != current_workspace:
                classes.add("cal-cat-alien")

            cal_uuid = IUUID(workspace)
            cal_id = workspace.id
            classes.add(f"cal-cat-{cal_id}")
            classes.add(f"cal-cat-{ob.ws_type}")

            if "/".join(workspace.getPhysicalPath()) in all_workspace_paths:
                classes.add(f"cal-cat-{ob.ws_type}-my")
                classes.add(f"cal-cat-{escape_id_to_class(cal_id)}-my")
                classes.add(f"calendar-my-calendars-{cal_uuid}")

            if is_invited:
                classes.add(f"cal-cat-{ob.ws_type}-invited")
                classes.add(f"cal-cat-{escape_id_to_class(cal_id)}-invited")
                classes.add(f"calendar-invited-events-{cal_uuid}")

            # Tag support
            tags = workspace.subject
            if tags:
                classes.add(self.proto.get_tag_classes(tags))

        summary["class"] = " ".join(classes)

        return summary
