
    m
i                         d Z ddlmZ ddlZddlmZmZ ddlZddlm	Z	m
Z
mZmZmZmZ  G d d      Ze G d d	             Zy)
zPeriodic trigger system for actions during navigation.

This module provides a mechanism to execute actions periodically during
long-running operations like navigation, with support for progress-based
and conditional triggering.
    )annotationsN)	dataclassfield)AnyCallableDictListOptionalSetc                  N    e Zd ZdZ	 	 	 d	 	 	 	 	 	 	 d	dZd
dZddZddZddZy)TriggerConditiona  Condition for when a trigger should fire.

    Attributes:
        interval_sec: Time-based trigger interval in seconds
        progress_milestones: Progress-based triggers (0.0-1.0) e.g., [0.25, 0.5, 0.75]
        while_navigating: If True, only trigger during active navigation
    Nc                f    || _         t        |xs g       | _        || _        t               | _        y)a  Initialize TriggerCondition.

        Args:
            interval_sec: Time interval in seconds (e.g., 2.0 for every 2 seconds)
            progress_milestones: List of progress points (0.0-1.0) to trigger at
            while_navigating: Only fire during active navigation state
        N)interval_secsetprogress_milestoneswhile_navigating_fired_milestones)selfr   r   r   s       ?/home/nelsen/Projects/HRI/orchestrator/src/executor/triggers.py__init__zTriggerCondition.__init__   s3     )#&':'@b#A  0 .1U    c                :    | j                   y|| j                   k\  S )zCheck if trigger should fire based on elapsed time.

        Args:
            elapsed_sec: Time elapsed since start

        Returns:
            True if interval_sec is set and enough time has passed
        F)r   )r   elapsed_secs     r   should_fire_timez!TriggerCondition.should_fire_time2   s$     $d////r   c                R    | j                   D ]  }||k\  s	|| j                  vs y y)zCheck if trigger should fire based on progress milestone.

        Args:
            current_progress: Current progress (0.0-1.0)

        Returns:
            True if a new milestone has been reached (not yet fired)
        TF)r   r   )r   current_progress	milestones      r   should_fire_progressz%TriggerCondition.should_fire_progress?   s6     11 	I9,$BXBX1X	 r   c                h    | j                   D ]#  }||k\  s	| j                  j                  |       % y)z_Mark a milestone as fired.

        Args:
            progress: Progress value to mark
        N)r   r   add)r   progressr   s      r   mark_milestone_firedz%TriggerCondition.mark_milestone_firedM   s5     11 	6I9$&&**95	6r   c                8    | j                   j                          y)z-Reset trigger state (clear fired milestones).N)r   clearr   s    r   resetzTriggerCondition.resetW   s    $$&r   )NNT)r   zOptional[float]r   zOptional[List[float]]r   boolreturnNone)r   floatr(   r'   )r   r*   r(   r'   r!   r*   r(   r)   r(   r)   )	__name__
__module____qualname____doc__r   r   r   r"   r&    r   r   r   r      sQ     )-59!%	3%3 33 	3
 
3(06'r   r   c                     e Zd ZU dZded<   ded<   ded<   dZd	ed
<    edd      Zded<    edd      Zded<    edd      Z	ded<    edd      Z
ded<    eej                  d      Zded<   ddZddZddZddZddZddZy) PeriodicTriggeraD  A periodic trigger that executes an action based on conditions.

    Attributes:
        action_id: The action to execute (e.g., "SCAN_AREA", "SPEAK")
        condition: TriggerCondition defining when to fire
        on_fire: Callback function to execute when trigger fires
        logger: Logger instance for debugging
    str	action_idr   	conditionzCallable[[], Any]on_fireNzOptional[logging.Logger]loggerF)defaultinitr'   _runningzOptional[asyncio.Task]_task        r*   _start_time_current_progress)default_factoryr:   zasyncio.Event_stop_eventc                   | j                   r6| j                  r'| j                  j                  d| j                         yd yd| _         | j                  j                          t        j                         j                         | _	        d| _
        | j                  j                          t        j                  | j                               | _        | j                  r'| j                  j!                  d| j                         yy)zStart the periodic trigger.

        Creates a background task that monitors conditions and fires
        the trigger when conditions are met.
        zTrigger '%s' is already runningNTr=   zTrigger '%s' started)r;   r8   warningr5   rA   r$   asyncioget_event_looptimer>   r?   r6   r&   create_task	_run_loopr<   debugr%   s    r   startzPeriodicTrigger.startx   s     ==  KK14>>  #' "11388:!$ (()9:
;;KK4dnnE r   c                F   | j                   syd| _         | j                  j                          | j                  r4| j                  j	                         s| j                  j                          | j                  r'| j                  j                  d| j                         yy)zZStop the periodic trigger.

        Cancels the background task and resets state.
        NFzTrigger '%s' stopped)	r;   rA   r   r<   donecancelr8   rI   r5   r%   s    r   stopzPeriodicTrigger.stop   sp    
 }}::djjoo/JJ;;KK4dnnE r   c                    | j                          d| _        | j                  r'| j                  j                  d| j                         yy)z[Called when navigation completes.

        Stops the trigger and performs cleanup.
              ?z!Trigger '%s': navigation completeN)rN   r?   r8   rI   r5   r%   s    r   on_navigation_completez&PeriodicTrigger.on_navigation_complete   s<    
 			!$;;KK3T^^ r   c                    t        dt        d|            | _        | j                  r2| j                  j	                  d| j
                  | j                         yy)zhUpdate navigation progress.

        Args:
            progress: Progress value from 0.0 to 1.0
        r=   rP   z&Trigger '%s': progress updated to %.2fN)maxminr?   r8   rI   r5   )r   r!   s     r   update_progresszPeriodicTrigger.update_progress   sK     "%S#c8*<!=;;KK8&& r   c                  K   d}	 | j                   r#| j                  j                         st        j                         j                         }|| j                  z
  }| j                  j                  |      r || _        | j                          d{    nb| j                  j                  | j                        r=| j                          d{    | j                  j                  | j                         	 t        j                  | j                  j                         |       d{    yyy7 7 f7 # t        j                  $ r Y Mw xY w# t        j                   $ r7 | j"                  r(| j"                  j%                  d| j&                         Y yY yt(        $ rB}| j"                  r,| j"                  j+                  d| j&                  |       Y d}~yY d}~yd}~ww xY ww)z-Main trigger loop running in background task.g?N)timeoutzTrigger '%s' cancelledzTrigger '%s' error: %s)r;   rA   is_setrD   rE   rF   r>   r6   r   _firer   r?   r"   wait_forwaitTimeoutErrorCancelledErrorr8   rI   r5   	Exceptionerror)r   check_interval	loop_timeelapsedexcs        r   rH   zPeriodicTrigger._run_loop   s     	--(8(8(?(?(A#22499;	#d&6&66 >>227;'0D$**,&& ^^889O9OP**,&&NN778N8NO!**((--/   ) )B- ' '
 ++  %% 	L{{!!":DNNK  	{{!!,dnnc  	s   G-BE D7=E D9)E =2D= /D;0D= 4G-7E 9E ;D= =EE EE AG*G- G*(3G%
G-%G**G-c                  K   	 | j                   r1| j                   j                  d| j                  | j                         | j	                         }t        j                  |      r| d{    yy7 # t        $ rB}| j                   r,| j                   j                  d| j                  |       Y d}~yY d}~yd}~ww xY ww)zExecute the trigger callback.z$Trigger '%s' firing (progress: %.2f)Nz Trigger '%s' callback failed: %s)	r8   infor5   r?   r7   rD   iscoroutiner^   r_   )r   resultrc   s      r   rY   zPeriodicTrigger._fire   s     	{{  :NN** \\^F""6* + 	{{!!6NN  	sA   CA'A4 +A2,A4 0C2A4 4	B?=3B:0
C:B??Cr,   r+   )r-   r.   r/   r0   __annotations__r8   r   r;   r<   r>   r?   rD   EventrA   rJ   rN   rQ   rU   rH   rY   r1   r   r   r3   r3   a   s     N'+F$+ 5u5Hd5$)$U$CE!Cs7K7$Su=u=!&w}}5!QKQF0F"$Lr   r3   )r0   
__future__r   rD   dataclassesr   r   loggingtypingr   r   r   r	   r
   r   r   r3   r1   r   r   <module>rn      sG    #  (  ; ;D' D'X U U Ur   