from collections import defaultdict
from datetime import timedelta
from plone import api
from plone.i18n.normalizer.interfaces import IIDNormalizer
from plone.memoize.view import memoize_contextless
from ploneintranet.search.interfaces import ISiteSearch
from Products.Five import BrowserView
from zope.component import getUtility


class ScheduleView(BrowserView):

    hour_strings = [f"{i:0>2}" for i in range(24)]

    @property
    def view_mode(self):
        if "mode-edit" in self.request:
            return "mode-edit"
        return "mode-view"

    @memoize_contextless
    def results(self):
        query = {"portal_type": "ploneintranet.conference.talk"}
        search_util = getUtility(ISiteSearch)
        ret = search_util.query(filters=query)
        return ret

    def get_talk_style(self, talk):
        """Return CSS rules to display the talks in the proper place"""
        start = 100.0 / 24 * (talk.start.hour + talk.start.minute / 60.0)
        duration = 100.0 / 24 * (talk.end.hour + talk.end.minute / 60.0) - start
        return "top: {start}%; max-height: {duration}%".format(
            start=start, duration=duration
        )

    def normalize(self, string):
        normalizer = getUtility(IIDNormalizer)
        return normalizer.normalize(string)

    @property
    def spaces(self):
        return sorted(
            set(self.context.spaces) | {talk.location for talk in self.results()}
        )

    @property
    def days(self):
        start_date = self.context.start.date()
        duration = (self.context.end.date() - start_date).days + 1
        return sorted(
            {
                (self.context.start.date() + timedelta(days=i)).isoformat()
                for i in range(duration)
            }
            | set(self.schedule_data)
        )

    @property
    @memoize_contextless
    def schedule_data(self):
        """Return talks for the conference in a tree structure:

        {
            day1: {
                location1: [
                    talk1,
                    ....
                ]
            ....
            },
            ...
        }
        """
        results = self.results()
        data = defaultdict(lambda: defaultdict(list))
        for talk in results:
            day = talk.start.date().isoformat()
            data[day][talk.location].append(talk)
        return data

    @property
    @memoize_contextless
    def first_talk_hours(self):
        results = self.results()
        data = dict()
        for talk in results:
            day = talk.start.date().isoformat()
            hour = str(talk.start.hour).zfill(2)
            if day not in data or data[day] > hour:
                data[day] = hour
        return data

    @property
    @memoize_contextless
    def current_user_id(self):
        user = api.user.get_current()
        return user.getId()

    def is_attending(self, talk):
        return self.current_user_id in talk.getObject().attendees

    def __call__(self):
        form = self.request.form
        # If 'title' is in the form then the full form has been submitted
        # We only want to handle a form submission from a scheduler modal
        # which only contains a few fields
        if self.request.method == "POST" and "title" not in form:
            talk_to_attend = form.get("attend")
            talk_to_not_attend = form.get("dont-attend")
            if talk_to_attend:
                talk = api.content.get(UID=talk_to_attend)
                api.content.get_view(
                    name="maybe_attend", context=talk, request=self.request
                )()
            elif talk_to_not_attend:
                talk = api.content.get(UID=talk_to_not_attend)
                if self.current_user_id in talk.attendees:
                    attendees_list = list(talk.attendees)
                    attendees_list.remove(self.current_user_id)
                    talk.attendees = tuple(attendees_list)
        return self.index()
