import { CurrentEvents , EventCallback , NumericCalculator , TimeEventLike , TimeHandlrSettings , } from "./types" ; import { TimeEvent } from "./TimeEvent" ; /**
 * Scheduling for dynamically repeating or synchronized events.
 */ export class TimeHandlr { /**
     * Default time separation between repeated events.
     */ private readonly timingDefault : number ; /**
     * The current (most recently reached) time.
     */ private time : number ; /**
     * Events yet to be triggered, keyed by their time.
     */ private events : CurrentEvents ; param settings public constructor ( settings = { } ) { this . time = 0 ; this . events = { } ; this . timingDefault = settings . timingDefault === undefined ? 1 : settings . timingDefault ; } param callback param timeDelay param args returns public addEvent ( callback , timeDelay ? , ... args ) { const event = new TimeEvent ( callback , 1 , this . time , timeDelay || 1 , args ) ; this . insertEvent ( event ) ; return event ; } param callback param timeDelay param numRepeats param args returns public addEventInterval ( callback , timeDelay ? , numRepeats ? , ... args ) { const event = new TimeEvent ( callback , numRepeats || 1 , this . time , timeDelay || 1 , args ) ; this . insertEvent ( event ) ; return event ; } param callback param timeDelay param numRepeats param args returns public addEventIntervalSynched ( callback , timeDelay ? , numRepeats ? , ... args ) { timeDelay = timeDelay || 1 ; numRepeats = numRepeats || 1 ; const calcTime = TimeEvent . runCalculator ( timeDelay || this . timingDefault ) ; const entryTime = Math . ceil ( this . time / calcTime ) * calcTime ; return entryTime === this . time ? this . addEventInterval ( callback , timeDelay , numRepeats , ... args ) : this . addEvent ( this . addEventInterval , entryTime - this . time , callback , timeDelay , numRepeats , ... args ) ; } /**
     * Increments time and handles all now-current events.
     */ public advance ( ) { this . time += 1 ; const currentEvents = this . events [ this . time ] ; if ( ! currentEvents ) { return ; } for ( const currentEvent of currentEvents ) { this . handleEvent ( currentEvent ) ; } delete this . events [ this . time ] ; } param event returns public handleEvent ( event ) { if ( event . repeat ! <= 0 || event . callback . apply ( this , event . args || [ ] ) ) { return undefined ; } if ( typeof event . repeat === "function" ) { if ( ! event . repeat . apply ( this , event . args || [ ] ) ) { return undefined ; } } else { if ( ! event . repeat ) { return undefined ; } event . repeat = event . repeat - 1 ; if ( event . repeat <= 0 ) { return undefined ; } } event . scheduleNextRepeat ( ) ; this . insertEvent ( event ) ; return event . time ; } param event public cancelEvent ( event ) { event . repeat = 0 ; } /**
     * Cancels all events.
     */ public cancelAllEvents ( ) { this . events = { } ; } /**
     * Quick handler to add an event to events at a particular time. If the time
     * doesn't have any events listed, a new Array is made to hold this event.
     */ private insertEvent ( event ) { if ( ! this . events [ event . time ] ) { this . events [ event . time ] = [ event ] ; } else { this . events [ event . time ] . push ( event ) ; } } }