o
    l>j:                     @  s   d Z ddlmZ ddlZddlZddlZddlmZmZ ddlm	Z	m
Z
mZmZ ddlmZmZmZmZmZ ddlmZ dd	lmZmZ dd
lmZmZmZmZmZ ddlmZm Z m!Z!m"Z" ddl#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z, G dd dZ-dS )z3Write-side orchestration for the Reminders service.    )annotationsN)datetimetimezone)AnyCallableDictOptional)CKModifyOperationCKModifyResponseCKRecordCKWriteParentCKWriteRecord   )_REMINDERS_ZONE_REQ)
AttachmentRemindersRecordMapper)
_as_raw_id_as_record_name_encode_cloudkit_text_field_encode_crdt_document_generate_resolution_token_map)_assert_modify_success_assert_read_success_refresh_record_change_tag_response_record_change_tag)	AlarmHashtagImageAttachmentLocationTrigger	ProximityRecurrenceFrequencyRecurrenceRuleReminderURLAttachmentc                   @  s  e Zd ZdZdd
dZedddZedddZedddddddd)d*Ze	dd+dd5d6Z
edd<d=Zeddd>ddEdFZddNdOZddTdUZddVdWZdd\d]Zdd_d`Z	a	b		c	b	b		dddldmZddndoZddpdqZdadadrdrdsejfddudvZddydzZdd|d}Zdd~dZ	ddddZddddddddddZdddZejddcdcddddZ ddddddddZ!dddZ"dS )RemindersWriteAPIz9Encapsulates mutation behavior for the Reminders service.get_rawCallable[[], Any]mapperr   loggerlogging.LoggerreturnNonec                 C  s   || _ || _|| _d S N)_get_raw_mapper_logger)selfr%   r'   r(    r1   X/home/thesage/.local/lib/python3.10/site-packages/pyicloud/services/reminders/_writes.py__init__2   s   
zRemindersWriteAPI.__init__reminder_idstrc                 C  s
   t | dS )zFNormalize reminder IDs so writes accept shorthand and canonical forms.r"   )r   )r4   r1   r1   r2   _reminder_record_name<   s   
z'RemindersWriteAPI._reminder_record_name
trigger_idalarm_idtitleaddresslatitudefloat	longituderadius	proximityr   location_uidr   c        	   	      C  s   t | ||||||||d	S )z5Validate geofence data before sending a remote write.)	idr8   r9   r:   r;   r=   r>   r?   r@   )r   	r7   r8   r9   r:   r;   r=   r>   r?   r@   r1   r1   r2   _validated_location_triggerA   s   z-RemindersWriteAPI._validated_location_triggerNutifilename	file_sizewidthheight
attachmentr   rE   Optional[str]rF   rG   Optional[int]rH   rI   c                C  st   t | j| j| j|du r| jn||du r| jnt||du r | jnt||du r*| jnt||du r4| j	n|| j
d	S )z>Validate image metadata updates before sending a remote write.N)	rA   r4   file_asset_urlrF   rG   rH   rI   rE   record_change_tag)r   rA   r4   rM   rF   rG   intrH   rI   rE   rN   )rJ   rE   rF   rG   rH   rI   r1   r1   r2   _validated_image_attachment[   s   z-RemindersWriteAPI._validated_image_attachment)rN   recurrence_id	frequencyr    intervalrO   occurrence_countfirst_day_of_weekrN   r!   c             	   C  s"   t t|d| ||||||dS )z8Validate recurrence values before mutating remote state.r!   )rA   r4   rR   rS   rT   rU   rN   )r!   r   r6   )clsrQ   r4   rR   rS   rT   rU   rN   r1   r1   r2   _validated_recurrence_ruler   s   z,RemindersWriteAPI._validated_recurrence_rule	completedboolcompleted_dateOptional[datetime]now_msc                 C  s@   | sdS |du rt j|d tjdS |jdu r|jtjdS |S )zAResolve the completion timestamp to persist for a reminder write.N     @@tztzinfo)r   fromtimestampr   utcra   replacerX   rZ   r\   r1   r1   r2   _completion_datetime   s   
z&RemindersWriteAPI._completion_datetime)rN   parent_record_namerecord_namerecord_typefieldsDict[str, Any]rg   r   c                 C  s$   d}|r	t |d}t| ||||dS )z-Build a typed CloudKit modify-record payload.N)
recordName)rl   
recordTyperecordChangeTagrj   parent)r   r   )rh   ri   rj   rN   rg   ro   r1   r1   r2   _write_record   s   

zRemindersWriteAPI._write_recordreminderr"   
field_nametoken_field_nameraw_ids	list[str]r	   c                C  sb   t t d }t|dg}| |j}td| j|d|j|d|ddd|dd	d
|diddS )z7Build a Reminder update operation for an ID-list field.  lastModifiedDateupdater"   STRING_LISTtypevalueResolutionTokenMapSTRINGLastModifiedDate	TIMESTAMPrh   ri   rN   rj   operationTyperecord)rO   timer   r6   rA   r	   rp   rN   )r0   rq   rr   rs   rt   r\   	token_mapreminder_record_namer1   r1   r2   _build_linked_ids_update_op   s"   	


z-RemindersWriteAPI._build_linked_ids_update_opoperation_name	model_objr   r
   c          	      C  sH   t d| j||||dd}|  j|gtd}t|| t||| |S )zBRun a one-record update and refresh the local object's change tag.rx   r   r   
operationszone_id)r	   rp   r-   modifyr   r   r   )	r0   r   rh   ri   rN   rj   r   opmodify_responser1   r1   r2   _submit_single_record_update   s    	
z.RemindersWriteAPI._submit_single_record_updatec                 C  s^   |   j|gtd}t|jd |jD ]}t|tr'|j|kr'| j	|  S qt
d| )z0Fetch a freshly-created reminder by record name.)record_namesr   zLookup reminderzReminder not found: )r-   lookupr   r   records
isinstancer   rl   r.   record_to_reminderLookupError)r0   rh   resprecr1   r1   r2   _lookup_created_reminder   s   
z*RemindersWriteAPI._lookup_created_reminderreminder_ids_attrprefixchild_fieldstuple[str, CKModifyResponse]c                  s   t t  }	  d|	 }
| |j} fddt||p g D }||	 | j||||d}t	d| j
|
|||dd}|  j||gtdd	}t|| t||| t||| |
|fS )
z=Create a linked child record and update the reminder ID list./c                   s   g | ]}t | qS r1   r   .0xr   r1   r2   
<listcomp>      
z:RemindersWriteAPI._create_linked_child.<locals>.<listcomp>rq   rr   rs   rt   createrh   ri   rj   rg   r   Tr   r   atomic)r5   uuiduuid4upperr6   rA   getattrappendr   r	   rp   r-   r   r   r   setattrr   )r0   rq   r   r   ri   rr   rs   r   r   
child_uuidchild_record_namer   
linked_idsreminder_opchild_opr   r1   r   r2   _create_linked_child   s>   



z&RemindersWriteAPI._create_linked_childchildc             	     s0  t t|d}	t|	 | |j}
t|dd}|r4| ||
kr4t d|	 d| | d|
  fddt||p@g D }| j||||d	}d
dddi}|rbd| |ddd|d< td| j|	|t|dd|dd}| 	 j
||gtdd}t|| t||| t|||
 t|||	 dS )zBSoft-delete a linked child record and update the reminder ID list.rA   r4   Nz child z is linked to z, not c                   s$   g | ]}t | krt |qS r1   r   r   r   r   r1   r2   r   ?  s
    z:RemindersWriteAPI._delete_linked_child.<locals>.<listcomp>r   DeletedINT64r   rz   	REFERENCEVALIDATErl   actionr"   rx   rN   r   r   Tr   )r   r   r   r6   rA   
ValueErrorr   r	   rp   r-   r   r   r   r   r   )r0   rq   r   r   r   ri   rr   rs   r   r   r   child_reminder_idr   r   r   r   r   r1   r   r2   _delete_linked_child%  s`   





z&RemindersWriteAPI._delete_linked_child Fr   list_iddescdue_datepriorityflaggedall_day	time_zoneparent_reminder_idc                 C  s  t t  }d| }t|}t|}g d}t|}tt d }d|r*dnddd|r2dnddd|r:|nd	dd|ddddd|rJdndddddd|dd
|dddd|dd|dd|dd|dd}|d	ur|jd	u r|j	t
jd}dt| d d|d< |	rd|	d|d< |
rd
t|
dddd|d< td| j|d||dd}|  j|gtd}t|d | |S )zDCreate a new Reminder inside a List, optionally as a child reminder.z	Reminder/)allDaytitleDocumentnotesDocumentparentReminderr   icsDisplayOrdercreationDatelistr   rX   completionDaterw   recurrenceRuleIDsdueDatetimeZonerv   r   r   r   rz   r   Nr   r   r   r~   )AllDay	CompletedCompletionDateCreationDater   FlaggedImportedr   ListNotesDocumentPriorityr}   TitleDocumentr`   DueDateTimeZoner"   ParentReminderr   r   r   r   zCreate reminder)r5   r   r   r   r   r   rO   r   ra   rd   r   rc   	timestampr   r	   rp   r-   r   r   r   r   )r0   r   r9   r   rX   r   r   r   r   r   r   reminder_uuidrh   	title_doc	notes_doc
fields_modr   r\   record_fieldsr   r   r1   r1   r2   r   l  sl   







zRemindersWriteAPI.createc              
   C  s  |  |j}t|j}t|jpd}tt d }g d}| j|j|j	|d}|dur4t|
 d nd}d|dd|dd|jrDd	nd
dd|dd|jdd|jrVd	nd
dd|jr_d	nd
dd|dd}	|jdur|j}
|
jdu r|
jtjd}
|
|_dt|

 d d|	d< nddd|	d< |d |jrd|jd|	d< nddd|	d< |d |jrdt|jdddd|	d< nddd|	d< |d dt|d|	d< | jd|d|j|	|d ||_	tj|d tjd|_dS )zUpdate an existing reminder.r   rv   )r   r   rX   r   r   r   r   rw   re   Nr~   rz   r   r   r   r   )r   r   r   r   r   r   r   r   r`   r   r   r   r   r   r"   r   r   r   r   r}   zUpdate reminderr   rh   ri   rN   rj   r   r]   r^   )r6   rA   r   r9   r   rO   r   rf   rX   rZ   r   r   r   r   r   ra   rd   r   rc   r   r   r   r   r   r   rN   r   rb   modified)r0   rq   r   r   r   r\   r   completion_datecompletion_date_msrj   r   r1   r1   r2   rx     s~   








zRemindersWriteAPI.updatec                 C  s   |  |j}ddg}t|}tt d }dddd|dd|dd	}| jd
|d|j||d d|_tj	|d t
jd|_dS )z1Delete a reminder using soft-update (Deleted: 1).deletedrw   rv   r   r   rz   r~   r   )r   r}   r   zDelete reminderr"   r   Tr]   r^   N)r6   rA   r   rO   r   r   rN   r   r   rb   r   rc   r   )r0   rq   r   r   r   r\   rj   r1   r1   r2   delete(  s$   zRemindersWriteAPI.deleteg        g      Y@tuple[Alarm, LocationTrigger]c                 C  s:  t t  }t t  }	t t  }
d| }d|	 }| |j}tt d }t d }d| }| j|||||||||
d	}dd t	|j
pPg D }|| td	d
g}td| j|d|jd|dd|dd|dddd}td| j|d|ddddddddd|ddd|	dd|ddd|dd}td| j|d|d dd!d|dddddd|jd dd!|
dd|jd dd!t|jdd|jddd"d dd!|jd dd!d#ddd$|dd}|  j|||gtd d%}t|d& ||_
t||| t||||	t||d'}t|||_||fS )(z>Attach a location-based alarm trigger to an existing Reminder.zAlarm/zAlarmTrigger/rv   g   @'Al    h] rB   c                 S  s   g | ]}t |d qS )r   r   r   r1   r1   r2   r   a  r   z:RemindersWriteAPI.add_location_trigger.<locals>.<listcomp>alarmIDsrw   rx   r"   ry   rz   r~   r   )AlarmIDsr}   r   r   r   r   r   )r|   r{   r   r   r   r   r   DOUBLE)AlarmUIDr   r   r"   	TriggerIDDueDateResolutionTokenAsNoncer   AlarmTriggerT)r|   isEncryptedr{   1Location)Addressr   r   LatitudeLocationUID	Longituder   RadiusReferenceFrameStringTitleTyper   zAdd location trigger)rA   	alarm_uidr4   r7   rN   )r5   r   r   r   r6   rA   rO   r   rC   r   	alarm_idsr   r   r	   rp   rN   r;   r=   r?   r>   r9   r-   r   r   r   r   r   r   )r0   rq   r9   r:   r;   r=   r>   r?   
alarm_uuidtrigger_uuidr@   alarm_record_nametrigger_record_namer   r\   apple_epoch_secsdue_date_noncetriggerexisting_alarm_idsr   r   alarm_op
trigger_opr   alarmr1   r1   r2   add_location_trigger@  s   



'0

z&RemindersWriteAPI.add_location_triggernamer   c                 C  sv   t t d }| |j}| j|dddddt|dddd	|d
ddd|dddd\}}t|||t||dS )zECreate a hashtag linked to a reminder and update Reminder.HashtagIDs.rv   hashtag_idsr   
HashtagIDs
hashtagIDsr   r   rz   r   r   r   r   )Namer   r"   r   zCreate hashtagrq   r   r   ri   rr   rs   r   r   )rA   r  r4   rN   )rO   r   r6   rA   r   r   r   r   )r0   rq   r  r\   r   hashtag_record_namer   r1   r1   r2   create_hashtag  s:   
z RemindersWriteAPI.create_hashtaghashtagc                 C  s\   dt |i}|jrd| |jddd|d< t|jd}| jd|d|j||d	 ||_d
S )z Update an existing hashtag name.r  r   r   r   rz   r"   r   zUpdate hashtagr   N)r   r4   r6   r   rA   r   rN   r  )r0   r  r  rj   r  r1   r1   r2   update_hashtag  s$   


z RemindersWriteAPI.update_hashtagc              
   C     | j |d|dddddd dS )z=Soft-delete a hashtag and remove it from Reminder.HashtagIDs.r  r   r  r  zDelete hashtagrq   r   r   r   ri   rr   rs   r   Nr   )r0   rq   r  r1   r1   r2   delete_hashtag     
z RemindersWriteAPI.delete_hashtag
public.urlurlr#   c                 C  s|   |  |j}| j|ddddddddd|d	d
dd|ddd|dddddddddd\}}t||||t||dS )z@Create a URL attachment and link it from Reminder.AttachmentIDs.attachment_idsr   AttachmentIDsattachmentIDsr~   URLrz   r   r   r   Tr{   r|   r   r   r   )r  r"   r%  UTIr   r   zCreate attachmentr  )rA   r4   r!  rE   rN   )r6   rA   r   r#   r   )r0   rq   r!  rE   r   attachment_record_namer   r1   r1   r2   create_url_attachment!  sD   
z'RemindersWriteAPI.create_url_attachment)r!  rE   rF   rG   rH   rI   r   c                C  s  i }t |tr4|dup|du}	|	std|dur!d|dd|d< |dur,d|d|d< ddd|d	< nctd
d |||||fD }	|	sHtd| j||||||d}
|dur^d|d|d< |durid|d|d< |durvdt|d|d< |durdt|d|d< |durdt|d|d< ddd|d	< |jrd| |jddd|d< t|j	d}| j
d|d|j||d t |tr|dur||_|dur||_dS dS |
j|_|
j|_|
j|_|
j|_|
j|_dS )zBUpdate an attachment record (URL fields or image metadata fields).Nz(No attachment fields provided for updater~   Tr&  r%  rz   r'  r  c                 s      | ]}|d uV  qd S r,   r1   r   r|   r1   r1   r2   	<genexpr>k  s    
z6RemindersWriteAPI.update_attachment.<locals>.<genexpr>rD   FileNamer   FileSizeWidthHeightImager   r   r   r"   r   zUpdate attachmentr   )r   r#   r   anyrP   rO   r4   r6   r   rA   r   rN   r!  rE   rF   rG   rH   rI   )r0   rJ   r!  rE   rF   rG   rH   rI   rj   has_mutationvalidated_attachmentr(  r1   r1   r2   update_attachmentO  s~   




	
z#RemindersWriteAPI.update_attachmentc              
   C  r  )zDSoft-delete an attachment and unlink it from Reminder.AttachmentIDs.r"  r   r#  r$  zDelete attachmentr  Nr  )r0   rq   rJ   r1   r1   r2   delete_attachment  r  z#RemindersWriteAPI.delete_attachmentr   )rR   rS   rT   rU   c          
      C  s   | j d|j||||d}| |j}| j|dddddd|dd	d
dt|jd
dt|jd
dt|jd
dt|jd
ddd
ddd
ddd\}}	||_||_	t
|	||_|S )zECreate a recurrence rule and link it from Reminder.RecurrenceRuleIDs.zRecurrenceRule/NEW)rQ   r4   rR   rS   rT   rU   recurrence_rule_idsr!   RecurrenceRuleIDsr   r   r   r   rz   r   r   )r"   	FrequencyIntervalOccurrenceCountFirstDayOfTheWeekr   r   zCreate recurrence ruler  )rW   rA   r6   r   rO   rR   rS   rT   rU   r4   r   rN   )
r0   rq   rR   rS   rT   rU   validated_ruler   recurrence_record_namer   r1   r1   r2   create_recurrence_rule  sV   

!z(RemindersWriteAPI.create_recurrence_rulerecurrence_ruleOptional[RecurrenceFrequency]c          
   	   C  sJ  i }t dd ||||fD }|std| j|j|j|p|j|du r&|jn||du r.|jn||du r6|jn||j	d}|durIdt
|d|d< |durVdt
|d|d	< |durcdt
|d|d
< |durpdt
|d|d< |jrd| |jddd|d< t|jd}	| jd|	d|j	||d |j|_|j|_|j|_|j|_dS )z#Update an existing recurrence rule.c                 s  r*  r,   r1   r+  r1   r1   r2   r,    s
    
z;RemindersWriteAPI.update_recurrence_rule.<locals>.<genexpr>z-No recurrence rule fields provided for updateN)rQ   r4   rR   rS   rT   rU   rN   r   rz   r9  r:  r;  r<  r   r   r   r"   r!   zUpdate recurrence ruler   )r2  r   rW   rA   r4   rR   rS   rT   rU   rN   rO   r6   r   r   )
r0   r@  rR   rS   rT   rU   rj   r3  r=  r>  r1   r1   r2   update_recurrence_rule  sh   





	z(RemindersWriteAPI.update_recurrence_rulec              
   C  r  )z>Soft-delete a recurrence rule and unlink it from the reminder.r7  r!   r8  r   zDelete recurrence ruler  Nr  )r0   rq   r@  r1   r1   r2   delete_recurrence_rule7  s   
z(RemindersWriteAPI.delete_recurrence_rule)r%   r&   r'   r   r(   r)   r*   r+   )r4   r5   r*   r5   )r7   r5   r8   r5   r9   r5   r:   r5   r;   r<   r=   r<   r>   r<   r?   r   r@   r5   r*   r   )rJ   r   rE   rK   rF   rK   rG   rL   rH   rL   rI   rL   r*   r   )rQ   r5   r4   r5   rR   r    rS   rO   rT   rO   rU   rO   rN   rK   r*   r!   )rX   rY   rZ   r[   r\   rO   r*   r[   )rh   r5   ri   r5   rj   rk   rN   rK   rg   rK   r*   r   )
rq   r"   rr   r5   rs   r5   rt   ru   r*   r	   )r   r5   rh   r5   ri   r5   rN   rK   rj   rk   r   r   r*   r
   )rh   r5   r*   r"   )rq   r"   r   r5   r   r5   ri   r5   rr   r5   rs   r5   r   rk   r   r5   r*   r   )rq   r"   r   r5   r   r   r   r5   ri   r5   rr   r5   rs   r5   r   r5   r*   r+   )r   FNr   FFNN)r   r5   r9   r5   r   r5   rX   rY   r   r[   r   rO   r   rY   r   rY   r   rK   r   rK   r*   r"   )rq   r"   r*   r+   )rq   r"   r9   r5   r:   r5   r;   r<   r=   r<   r>   r<   r?   r   r*   r   )rq   r"   r  r5   r*   r   )r  r   r  r5   r*   r+   )rq   r"   r  r   r*   r+   )r   )rq   r"   r!  r5   rE   r5   r*   r#   )rJ   r   r!  rK   rE   rK   rF   rK   rG   rL   rH   rL   rI   rL   r*   r+   )rq   r"   rJ   r   r*   r+   )rq   r"   rR   r    rS   rO   rT   rO   rU   rO   r*   r!   )r@  r!   rR   rA  rS   rL   rT   rL   rU   rL   r*   r+   )rq   r"   r@  r!   r*   r+   )#__name__
__module____qualname____doc__r3   staticmethodr6   rC   rP   classmethodrW   rf   rp   r   r   r   r   r   r   rx   r   r   ARRIVINGr  r  r  r  r)  r5  r6  r    DAILYr?  rB  rC  r1   r1   r1   r2   r$   /   s    







0K
d
X 

#
2
T@Kr$   ).rG  
__future__r   loggingr   r   r   r   typingr   r   r   r   pyicloud.common.cloudkitr	   r
   r   r   r   
_constantsr   _mappersr   r   	_protocolr   r   r   r   r   _supportr   r   r   r   modelsr   r   r   r   r   r    r!   r"   r#   r$   r1   r1   r1   r2   <module>   s    ,