o
    l>jd                     @   s  d Z ddlZddlmZ ddlmZmZmZmZ ddl	m	Z	m
Z
 ddlmZ ddlmZmZmZmZmZmZmZmZ ddlmZ dd	lmZ dd
lmZ ddlmZ ddlmZ ddl m!Z! edZ"G dd dZ#G dd dZ$G dd dZ%G dd dZ&eG dd dZ'eG dd dZ(eG dd dZ)eG dd dZ*eG dd  d Z+eG d!d" d"Z,eG d#d$ d$Z-eG d%d& d&Z.G d'd( d(eZ/dS ))zCalendar service.    N)
monthrange)asdict	dataclassfieldfields)datetime	timedeltarandint)AnyListLiteralOptionalTypeVarUnioncastoverload)uuid4)Response)get_localzone_name)BaseService)PyiCloudSession)camelcase_to_underscoreTc                   @      e Zd ZdZdZdZdS )DateFormatszDate format constants.z%Y-%m-%dz%Y%m%dN)__name__
__module____qualname____doc__API_DATE
APPLE_DATE r"   r"   O/home/thesage/.local/lib/python3.10/site-packages/pyicloud/services/calendar.pyr          r   c                   @   s0   e Zd ZdZdZdZdZdZdZdZ	dZ
dZdS )	CalendarDefaultszDefault values for calendars.Untitled
__custom__Eventpersonal    N)r   r   r   r   TITLESYMBOLIC_COLORSUPPORTED_TYPEOBJECT_TYPEORDERSHARE_TITLE
SHARED_URLCOLORr"   r"   r"   r#   r%      s    r%   c                   @   r   )InviteeDefaultsz"Default values for event invitees.zREQ-PARTICIPANTzNEEDS-ACTIONN)r   r   r   r   ROLESTATUSr"   r"   r"   r#   r4   *   r$   r4   c                   @   r   )AlarmDefaultsz Default values for event alarms.messageFN)r   r   r   r   MESSAGE_TYPEIS_LOCATION_BASEDr"   r"   r"   r#   r7   1   r$   r7   c                   @   sZ   e Zd ZU dZdZeed< dZeed< dZ	eed< dZ
eed< dZeed< dZeed	< d
S )AlarmMeasurementz9
    Represents the timing measurement for an alarm.
    Tbeforer   weeksdayshoursminutessecondsN)r   r   r   r   r<   bool__annotations__r=   intr>   r?   r@   rA   r"   r"   r"   r#   r;   8   s   
 r;   c                   @   sP   e Zd ZU dZeed< eed< ejZeed< ej	Z
eed< eedZeed< dS )	
AppleAlarmzr
    Represents an alarm in Apple's Calendar API format.

    This is used in the main payload's Alarm array.
    guidpGuidmessageTypeisLocationBaseddefault_factorymeasurementN)r   r   r   r   strrC   r7   r9   rH   r:   rI   rB   r   r;   rL   r"   r"   r"   r#   rE   F   s   
 rE   c                   @   sx   e Zd ZU dZeed< eed< eed< eed< eed< eed< eed< edd
ede	dd fddZ
dee fddZdS )AppleDateFormatz
    Apple's 7-element date array format.

    Format: [YYYYMMDD, YYYY, MM, DD, HH, MM, minutes_from_midnight]
    The date_string uses YYYYMMDD format.
    date_stringyearmonthdayhourminuteminutes_from_midnightTdtis_startreturnc              	   C   sV   |r|j d |j }nd|j  d d|j  }| |tj|j|j|j|j |j|dS )z/Convert Python datetime to Apple's date format.<      rO   rP   rQ   rR   rS   rT   rU   )rS   rT   strftimer   r!   rP   rQ   rR   )clsrV   rW   minutes_calcr"   r"   r#   from_datetimeh   s   
zAppleDateFormat.from_datetimec                 C   s    | j | j| j| j| j| j| jgS )z(Convert to Apple's expected list format.r[   selfr"   r"   r#   to_listz   s   zAppleDateFormat.to_listNT)r   r   r   r   rM   rC   rD   classmethodr   rB   r_   listrb   r"   r"   r"   r#   rN   W   s   
 rN   c                   @   s6   e Zd ZU dZeed< ejZeed< ej	Z
eed< dS )AppleEventInviteez
    Represents an invitee within the Event object in Apple's Calendar API.

    This is the simpler invitee structure used inside the Event.invitees array.
    emailroleinviteeStatusN)r   r   r   r   rM   rC   r4   r5   rh   r6   ri   r"   r"   r"   r#   rf      s
   
 rf   c                   @   sn   e Zd ZU dZeed< eed< ejZeed< dZ	e
ed< dZeed< ejZeed	< dZeed
< dZe
ed< dS )ApplePayloadInviteez
    Represents an invitee in the main payload's Invitee array in Apple's Calendar API.

    This is the more detailed invitee structure used in the top-level Invitee array.
    rF   rG   rh   FisOrganizerr+   rg   ri   
commonNameisMeN)r   r   r   r   rM   rC   r4   r5   rh   rk   rB   rg   r6   ri   rl   rm   r"   r"   r"   r#   rj      s   
 rj   c                   @   sp  e Zd ZU dZeed< eed< eed< eed< eed< eed< eed< ee ed	< ee ed
< ee ed< ee ed< ee ed< ee ed< eed< eed< eed< eed< dZ	eed< dZ
eed< dZeed< dZeed< dZeed< dZeed< dZeed< dZeed< dZeed< eedZee ed< eedZee ed < eedZee ed!< d"Zee ed#< d"S )$AppleCalendarEventz
    Represents an event in Apple's Calendar API format.

    This dataclass exactly mirrors the structure expected by Apple's API,
    using the correct camelCase field names and types.
    titletzicondurationallDayrG   rF   	startDateendDatelocalStartDatelocalEndDatecreatedDatelastModifiedDateextendedDetailsAreIncludedrecurrenceExceptionrecurrenceMasterhasAttachmentsFreadOnlytransparentbirthdayIsYearlessBdaybirthdayShowAsCompanyshouldShowJunkUIWhenAppropriater+   locationurldescriptionetagrJ   alarmsattachmentsinviteesNchangeRecurring)r   r   r   r   rM   rC   rD   rB   r   r~   r   r   r   r   r   r   r   r   r   re   r   r   r   r   r   r   r"   r"   r"   r#   rn      s@   
 	rn   c                   @   s  e Zd ZU dZeed< dZeed< eej	dZ
eed< edd dZeed	< d
Zee ed< d
Zee ed< eddZeed< dZeed< d
Zee ed< dZeed< dZeed< dZeed< dZeed< dZeed< dZeed< dZeed< dZeed< dZeed< d
Zee ed< ededZe e ed < ededZ!e e ed!< ede"dZ#e"ee$f ed"< d<d$d%Z%d#e&fd&d'Z'e(d#e"ee)f fd(d)Z*d=d*ed+ed#efd,d-Z+d>d.ee d#d
fd/d0Z,d#efd1d2Z-	d?d3ed4ed5ed6ed#ef
d7d8Z.d9efd:d;Z/d
S )@EventObjectzC
    An EventObject represents an event in the Apple Calendar.
    pguidz	New Eventro   rJ   
start_datec                   C   s   t  tdd S )NrY   )r@   )r   todayr   r"   r"   r"   r#   <lambda>       zEventObject.<lambda>end_dateNlocal_start_datelocal_end_dateF)initrr   r   rq   change_recurringr+   rp   rF   r   Textended_details_are_includedrecurrence_exceptionrecurrence_masterhas_attachmentsall_dayis_junkr   )r   rK   r   r   _alarm_metadatarX   c                 C   s   | j  s	td| j| jkrtd| j d| j d| js#| j| _| js*| j| _| js5tt	 
 | _| js<t | _t| j | j  d | _d S )Nzpguid cannot be emptyzstart_date (z) must be before end_date ()rY   )r   strip
ValueErrorr   r   r   r   rF   rM   r   upperrp   r   rD   	timestamprr   r`   r"   r"   r#   __post_init__   s"   

zEventObject.__post_init__c                 C   s^  |  | j}|  | jd}| jr|  | jn|}| jr"|  | jdn|}t }t|}|  |}|  |}g }	| jr?| j}	g }
| j	rG| j	}
t
di d| jd| jd| jd| jd| jd| jd| jd	|d
|d|d|d|d|d| jd| jd| jd| jd| jd| jd| jpdd|
d|	d| jS d|
d|	d| jS )z
        Convert this EventObject to Apple's API format.

        This method handles the conversion from our internal representation
        to the exact structure expected by Apple's Calendar API.
        Fro   rp   rq   rr   rs   rG   rF   rt   ru   rv   rw   rx   ry   rz   r{   r|   r}   r   r   r   r+   r   r   r   Nr"   )
dt_to_listr   r   r   r   timer   fromtimestampr   r   rn   ro   rp   rq   rr   r   r   rF   r   r   r   r   r   r   r   r   )ra   start_date_listend_date_listlocal_start_listlocal_end_listcurrent_timestamp
current_dtcreated_date_listlast_modified_listinvitees_listalarms_listr"   r"   r#   to_apple_event  s   


	

zEventObject.to_apple_eventc                    s      }t|}|g g d jddgid} jr, fdd jD }dd |D |d<  jrB fd	d jD }d
d |D |d< |S )zBReturns the event data in the format required by Apple's calendar.
CollectionN)rF   ctag)r(   InviteeAlarmClientStatec                    s4   g | ]}t | jtjd |dd tjdd dqS )F:r+   )rF   rG   rh   rk   rg   ri   rl   rm   )rj   rF   r4   r5   splitr6   ).0
email_guidr`   r"   r#   
<listcomp>e  s    z,EventObject.request_data.<locals>.<listcomp>c                 S      g | ]}t |qS r"   r   )r   inviteer"   r"   r#   r   r      r   c                    s0   g | ]}t | jtjtj j|t d qS ))rF   rG   rH   rI   rL   )rE   rF   r7   r9   r:   r   getr;   )r   
alarm_guidr`   r"   r#   r   u  s    
c                 S   r   r"   r   )r   alarmr"   r"   r#   r     r   r   )r   r   r   r   r   )ra   apple_event
event_dictdatapayload_inviteespayload_alarmsr"   r`   r#   request_dataU  s&   	


zEventObject.request_datarV   startc                 C   s   t j||d}| S )zf
        Converts python datetime object into a list format used
        by Apple's calendar.
        )rW   )rN   r_   rb   )ra   rV   r   
apple_dater"   r"   r#   r     s   zEventObject.dt_to_list	_inviteesc                    s(   |r  j  fdd|D 7  _ dS dS )zI
        Adds a list of emails to invitees in the correct format
        c                    s   g | ]
} j  d | qS )r   )rF   )r   rg   r`   r"   r#   r     s    z,EventObject.add_invitees.<locals>.<listcomp>N)r   )ra   r   r"   r`   r#   add_invitees  s    zEventObject.add_inviteesc                 C   sD   t t }| j d| }| j| tddddddd| j|< |S )zg
        Adds an alarm at the time of the event.
        Returns the alarm GUID for reference.
        r   Fr   r<   r=   r>   r?   r@   rA   rM   r   rF   r   appendr;   r   )ra   r   alarm_full_guidr"   r"   r#   add_alarm_at_time  s   
zEventObject.add_alarm_at_timer@   r?   r>   r=   c                 C   sD   t t }| j d| }| j| td||||dd| j|< |S )a  
        Adds an alarm before the event.

        Args:
            minutes: Minutes before event
            hours: Hours before event
            days: Days before event
            weeks: Weeks before event

        Returns:
            The alarm GUID for reference.
        r   Tr   r   r   )ra   r@   r?   r>   r=   r   r   r"   r"   r#   add_alarm_before  s   
zEventObject.add_alarm_beforevarc                 C   s   t | |dS )zGet a variableN)getattr)ra   r   r"   r"   r#   r     s   zEventObject.getrX   Nrc   N)r   r   r   r   )0r   r   r   r   rM   rC   ro   r   r   r   r   r   r   r   r   rr   rD   rq   r   rp   rF   r   r   rB   r   r   r   r   r   r   re   r   r   r   dictr   r;   r   rn   r   propertyr   r   r   r   r   r   r   r"   r"   r"   r#   r      s`   
 
</
r   c                   @   s  e Zd ZU dZejZeed< dZ	eed< dZ
ee ed< ejZeed< ejZeed< ejZeed	< ejZeed
< ejZeed< ejZeed< ejZeed< dZeed< dZeed< dZeed< dZee ed< dZ ee ed< dZ!ee ed< dZ"ee ed< dZ#ee ed< dZ$ee ed< dZ%ee ed< dZ&ee ed< dZ'ee ed< dZ(ee ed< dZ)ee ed< dZ*ee ed< dZ+ee ed< dZ,ee ed < dZ-ee ed!< dZ.ee ed"< d*d$d%Z/d#efd&d'Z0e1d#e2ee3f fd(d)Z4dS )+CalendarObjectzG
    A CalendarObject represents a calendar in the Apple Calendar.
    ro   r+   rF   N
share_typesymbolic_colorsupported_typeobject_typeshare_title
shared_urlcolororderTr   F	read_onlyenabledignore_event_updatesemail_notificationlast_modified_dateme_as_participantpre_published_urlparticipantsdefer_loadingpublished_urlremove_alarmsignore_alarmsr   remove_todos
is_default	is_familyr   r   rX   c                 C   s.   | j stt  | _ | js|  | _d S d S r   )rF   rM   r   r   r   gen_random_colorr`   r"   r"   r#   r     s
   zCalendarObject.__post_init__c                 C   s*   dt dddt dddt dddS )z0
        Creates a random rgbhex color.
        #r      02xr	   r`   r"   r"   r#   r     s   *zCalendarObject.gen_random_colorc                 C   s   t | g ddd}|S )zEReturns the calendar data in the format required by Apple's calendar.F)r   	fullState)r   r   r   )ra   r   r"   r"   r#   r     s   zCalendarObject.request_datar   )5r   r   r   r   r%   r,   ro   rM   rC   rF   r   r   r-   r   r.   r   r/   r   r1   r   r2   r   r3   r   r0   r   rD   r   rB   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r"   r"   r"   r#   r     sF   
 
r   c                       s  e Zd ZdZdededeeef ddf fddZe	deeef fd	d
Z
dedefddZdedefddZd2deeef fddZedeeeef  fddZeded deeeef  fddZeded dee fddZ	d3deed ed f deeeeef  ee f fddZdedeeef fddZdedeeef fdd Ze			!d4d"ee d#ee d$edeeeef  fd%d&Ze			!	d5d"ee d#ee d$eded deeeef  f
d'd&Ze			!	d6d"ee d#ee d$eded dee f
d(d&Z			!	d5d"ee d#ee d$ededeeeeef  ee f f
d)d&Zd3d*edefd+d,Zd-edeeef fd.d/Zd-edeeef fd0d1Z  ZS )7CalendarServicezO
    The 'Calendar' iCloud service, connects to iCloud and returns events.
    service_rootsessionparamsrX   Nc                    sZ   t  ||| | j d| _| j d| _| j d| _| j d| _| j d| _d S )Nz/caz/eventsz/eventdetailz/collectionsz/allcollections)super__init__r   _calendar_endpoint_calendar_refresh_url_calendar_event_detail_url_calendar_collections_url_calendars_url)ra   r   r   r   	__class__r"   r#   r     s   zCalendarService.__init__c                 C   sn   t  }t|j|j\}}t |j|jd}t |j|j|}t| j}|dt |	t
j|	t
jd |S )z8Returns the default parameters for the calendar service.   en-us)langusertzrt   ru   )r   r   r   rP   rQ   r   r   updater   r\   r   r    )ra   r   _days_in_monthfrom_dtto_dtr   r"   r"   r#   default_params  s   



	zCalendarService.default_paramsobjc           	      C   s   t |dr0dd t|D }ddd}| D ]\}}||t|}||v r-t||| q|S | D ]
\}}t||| q4|S )zACreates an object from a dictionary with proper field validation.__dataclass_fields__c                 S   s   h | ]}|j qS r"   )name)r   fr"   r"   r#   	<setcomp>&  r   z0CalendarService.obj_from_dict.<locals>.<setcomp>r   r   )rG   r   )hasattrr   itemsr   r   setattr)	ra   r  _dictvalid_fieldsspecial_mappingsapi_keyvalue
field_namekeyr"   r"   r#   obj_from_dict#  s    
zCalendarService.obj_from_dictrF   c                 C   sh   d}| j ddD ]'}t|tr|j|kr|j}nt|tr)|d|kr)|d}|r/|  S qtd)z*Returns the ctag for a given calendar guidNF)as_objsrF   r   zctag not found.)get_calendars
isinstancer   rF   r   r   r   r   )ra   rF   r   calr"   r"   r#   get_ctag:  s   
zCalendarService.get_ctagc                 C   s   t  }|p	|p	|}|j|j}}t||\}}|du s |du r,|jdd}|j|d}t| j}	|	dt	 |
tj|
tj| jjjd d d | jj| j|	d}
|
 S )	a  
        Refresh the Calendar service and return a fresh event payload.

        Date range semantics:
        - If both 'from_dt' and 'to_dt' are provided, they are respected as-is.
        - If exactly one bound is provided, the missing bound is anchored to the
          same month as the provided bound and expanded to the full month
          (1st..last day of that month).
        - If neither is provided, defaults to the current month.

        Notes:
        - Apple's Calendar API treats 'endDate' as inclusive; events occurring on
          the last day of the month (including all-day and 23:00->00:00 boundary
          events) are returned. See tests in tests/test_calendar.py.
        Nr  )rR   r  dsInfodsid)r  r  rt   ru   r#  r   )r   r   rP   rQ   r   replacer   r   r  r   r\   r   r    r   servicer   r   r   json)ra   r
  r  r   anchorrP   rQ   r  r	  r   reqr"   r"   r#   refresh_clientG  s(   


	zCalendarService.refresh_clientc                 C      d S r   r"   r`   r"   r"   r#   r  p     zCalendarService.get_calendarsr  Fc                 C   r+  r   r"   ra   r  r"   r"   r#   r  s  r,  Tc                 C   r+  r   r"   r-  r"   r"   r#   r  v  r,  c                    sF    j } jj j|d}| }|d }|s|r|S  fdd|D S )z4
        Retrieves calendars of this month.
        r$  r   c                    s   g | ]	}  t |qS r"   )r  r   )r   r   r`   r"   r#   r     s    z1CalendarService.get_calendars.<locals>.<listcomp>)r  r   r   r   r'  )ra   r  r   r)  response	calendarsr"   r`   r#   r  y  s   calendarc                 C   s4   |j }| j}| jj| j d|j ||d}| S )z8
        Adds a Calendar to the apple calendar.
        /r   r'  )r   r  r   postr   rF   r'  )ra   r0  r   r   r)  r"   r"   r#   add_calendar  s   zCalendarService.add_calendarcal_guidc                 C   s4   | j }d|d< | jj| j d| |i d}| S )z=
        Removes a Calendar from the apple calendar.
        DELETEmethodOverrider1  r2  )r  r   r3  r   r'  )ra   r5  r   r)  r"   r"   r#   remove_calendar  s   zCalendarService.remove_calendarrQ   r
  r  periodc                 C   r+  r   r"   )ra   r
  r  r9  r"   r"   r#   
get_events  s   zCalendarService.get_eventsc                 C   r+  r   r"   ra   r
  r  r9  r  r"   r"   r#   r:       c                 C   r+  r   r"   r;  r"   r"   r#   r:    r<  c                 C   s   t  }|dkr|rt |j|j|j}|dkr*|s"t |j|j|j}|tdd }n|dkrI|sBt |j|j|jt| d d }|tdd }| ||}|dg }|r{|r{t	|D ]\}}	|	dd	}
|
spt
d
|	 | t|
|	||< q]|S )zR
        Retrieves events for a given date range, by default, this month.
        rQ   rR   r  )r>   week   r(   rG   r+   z$Event missing required pGuid field: )r   r   rP   rQ   rR   r   weekdayr*  r   	enumerater   r  r   )ra   r
  r  r9  r  r   r.  eventsidxeventr   r"   r"   r#   r:    s,   

as_objc           	      C   s   t | j}|dt | jjjd d d | j d| d| }| jj||d}|	 }|d d }|rC|rCt
t| t|d	|}|S )
zy
        Fetches a single event's details by specifying a pguid
        (a calendar) and a guid (an event's ID).
        r  r"  r#  )r  r  r#  r1  r$  r(   r   )r   )r   r   r  r   r   r&  r   r   r   r'  r   r   r  )	ra   r   rF   rD  r   r   r)  r.  rC  r"   r"   r#   get_event_detail  s"   
z CalendarService.get_event_detailrC  c                 C   sX   |j }| |j|d d d d< | j}| jj| j d|j d|j ||d}| S )z.
        Adds an Event to a calendar.
        r   r   r   r   r1  r2  )	r   r!  r   r  r   r3  r   rF   r'  ra   rC  r   r   r)  r"   r"   r#   	add_event  s   zCalendarService.add_eventc                 C   s   |j }| |j|d d d d< i |d< | j}d|d< t|dd	s0| j|j|jd
dd|_|j|d< | j	j
| j d|j d|j ||d}| S )zn
        Removes an Event from a calendar. The calendar's guid corresponds to the EventObject's pGuid
        r   r   r   r   r(   r6  r7  r   NF)rD  ifMatchr1  r2  )r   r!  r   r  r   rE  rF   r   r   r   r3  r   r'  rF  r"   r"   r#   remove_event  s$   

zCalendarService.remove_event)NN)F)NNrQ   )NNrQ   F)NNrQ   T) r   r   r   r   rM   r   r   r   r   r   r  r   r  r!  r*  r   re   r  r   r   r   r4  r8  r   r   r:  r   rB   rE  rG  rI  __classcell__r"   r"   r  r#   r     s    

)$


%"r   )0r   r   r0  r   dataclassesr   r   r   r   r   r   randomr
   typingr   r   r   r   r   r   r   r   uuidr   requestsr   tzlocalr   pyicloud.services.baser   pyicloud.sessionr   pyicloud.utilsr   r   r   r%   r4   r7   r;   rE   rN   rf   rj   rn   r   r   r   r"   r"   r"   r#   <module>   sH    (// e=