from datetime import datetime, date, timedelta, timezone
from caldav.objects import Event as CaldavEvent
import dataclasses

from icalendar import Event as IcEvent
from icalendar import Calendar as Icalendar

@dataclasses.dataclass
class  Event():
    summary: str
    dtstart: datetime
    dtend: datetime
    is_all_day: bool

    @classmethod
    def fromCalDavEvents(cls, caldav_events: [CaldavEvent]) -> list['Event']:

        events = []

        for event in caldav_events:
            date_value = event.vobject_instance.vevent.dtstart.value
            if isinstance(date_value, datetime):
                dt_start = date_value
                is_all_day = False
            elif isinstance(date_value, date):
                d_start = date_value
                dt_start = datetime(d_start.year, d_start.month, d_start.day, tzinfo=datetime.now(timezone.utc).astimezone().tzinfo)
                is_all_day = True
            else:
                raise Exception

            date_value = event.vobject_instance.vevent.dtend.value
            if isinstance(date_value, datetime):
                dt_end = date_value
            elif isinstance(date_value, date):
                d_end = date_value
                dt_end = datetime(d_end.year, d_end.month, d_end.day,tzinfo=datetime.now(timezone.utc).astimezone().tzinfo)
                date_value = dt_end
            else:
                raise Exception

            events.append(Event(
                summary=event.vobject_instance.vevent.summary.value,
                dtstart=dt_start,
                dtend=dt_end,
                is_all_day = is_all_day
            ))
        return events

    @classmethod
    def fromIcalendar(cls, icalendar: Icalendar) -> list['Event']:
        events = []
        for event in [e for e in icalendar.subcomponents if isinstance(e, IcEvent)]:
            date_value = event['DTSTART'].dt
            if isinstance(date_value, datetime):
                dt_start = date_value
                is_all_day = False
            elif isinstance(date_value, date):
                d_start = date_value
                dt_start = datetime(d_start.year, d_start.month, d_start.day, tzinfo=datetime.now(timezone.utc).astimezone().tzinfo)
                is_all_day = True
            else:
                raise Exception

            date_value = event['DTEND'].dt if event.get('DTEND') else event['DTSTART'].dt
            if isinstance(date_value, datetime):
                dt_end = date_value
            elif isinstance(date_value, date):
                d_end = date_value
                dt_end = datetime(d_end.year, d_end.month, d_end.day,tzinfo=datetime.now(timezone.utc).astimezone().tzinfo)
            else:
                raise Exception

            events.append(Event(
                summary=event['summary'],
                dtstart=dt_start,
                dtend=dt_end,
                is_all_day = is_all_day
            ))

        return events

    @property
    def range_str(self) -> str:
        start_time_str = self.dtstart.strftime('%-I')
        end_time_str = self.dtend.strftime('%-I')

        if not(self.dtstart.hour and self.dtend.hour):
            return ""

        if self.dtstart.minute: start_time_str += self.dtstart.strftime(':%M')
        if self.dtend.minute: end_time_str += self.dtend.strftime(':%M')

        if not ((self.dtstart.hour < 12 and self.dtend.hour < 12) or (self.dtstart.hour > 12 and self.dtend.hour > 12)):
            start_time_str += self.dtstart.strftime("%p")

        end_time_str += self.dtend.strftime("%p")

        return f"{start_time_str}-{end_time_str}"
