from datetime import datetime
from plone.restapi.serializer.converters import date_converter
from plone.restapi.serializer.converters import default_converter
from plone.restapi.serializer.converters import python_datetime_converter
from ploneintranet.restapi.serializer.calendarevent import (
    SerializeToJsonSummaryCalendar,
)
from pytz import timezone
from unittest import mock
from zope import component

import unittest
import uuid


class TestingBrain(dict):
    def __getattr__(self, name):
        try:
            return self[name]
        except KeyError:
            return None

    def getURL(self):
        return "http://nohost{}".format(self["path_string"])

    def getObject(self):
        obj = mock.Mock()
        setattr(obj, "start", self.start)
        setattr(obj, "is_maintainer", lambda: False)
        setattr(obj, "whole_day", self.whole_day)
        return obj


class TestEventSerialization(unittest.TestCase):
    def setUp(self):
        component.provideAdapter(default_converter)
        component.provideAdapter(python_datetime_converter)
        component.provideAdapter(date_converter)

    def make_event(self, extra_data={}):
        data = {
            "UID": uuid.uuid4().hex,
            "friendly_type_name": "Event",
            "portal_type": "Event",
            "Title": "Test Event",
            "path_string": "/Plone/workspaces/open-market-committee/test-event",
            "modified": datetime.now(),
            "start": self.make_time(2021, 11, 1, 9),
            "end": self.make_time(2021, 11, 1, 10),
        }
        data.update(extra_data)
        return TestingBrain(data)

    def make_time(self, *args):
        amsterdam = timezone("Europe/Amsterdam")
        return amsterdam.localize(datetime(*args))

    def test_whole_day_one_day(self):
        event_result = self.make_event(
            {
                "start": self.make_time(2021, 11, 6),
                "end": self.make_time(2021, 11, 6),
                "whole_day": True,
            }
        )
        serializer = SerializeToJsonSummaryCalendar(event_result, mock.Mock())
        data = serializer()
        # In our internal representation the end is inclusive, but in fullcalendar it
        # is exclusive
        self.assertEqual(
            data["start"],
            "2021-11-06",
        )
        self.assertEqual(
            data["end"],
            "2021-11-07",
            msg="Event end should be exclusive and date only",
        )

    def test_whole_day_multiple_days(self):
        event_result = self.make_event(
            {
                "start": self.make_time(2021, 11, 4),
                "end": self.make_time(2021, 11, 6),
                "whole_day": True,
            }
        )
        serializer = SerializeToJsonSummaryCalendar(event_result, mock.Mock())
        data = serializer()
        # In our internal representation the end is inclusive, but in fullcalendar it
        # is exclusive
        self.assertEqual(
            data["start"],
            "2021-11-04",
        )
        self.assertEqual(
            data["end"],
            "2021-11-07",
            msg="Event end should be exclusive and date only",
        )

    def test_timed_one_day(self):
        event_result = self.make_event(
            {
                "start": self.make_time(2021, 11, 6, 10),
                "end": self.make_time(2021, 11, 6, 14),
            }
        )
        serializer = SerializeToJsonSummaryCalendar(event_result, mock.Mock())
        data = serializer()
        self.assertEqual(
            data["start"],
            "2021-11-06T09:00:00+00:00",
        )
        self.assertEqual(
            data["end"],
            "2021-11-06T13:00:00+00:00",
        )

    def test_timed_multiple_days(self):
        event_result = self.make_event(
            {
                "start": self.make_time(2021, 11, 6, 8),
                "end": self.make_time(2021, 11, 7, 18),
            }
        )
        serializer = SerializeToJsonSummaryCalendar(event_result, mock.Mock())
        data = serializer()
        self.assertEqual(
            data["start"],
            "2021-11-06T07:00:00+00:00",
        )
        self.assertEqual(
            data["end"],
            "2021-11-07T17:00:00+00:00",
        )
