/**
 * A wrapper around <code>setTimeout()</code> and <code>clearTimeout()</code>
 * that allows the timer to be edited to complete earlier or later,
 * relative to its original start time.
 */ export class EditableTimeout { public readonly callback : ( ) => void ; public readonly startTime : number ; public runTime : number ; public runningTimeout : NodeJS . Timeout | undefined ; public completed = false ; public constructor ( callback , runTime ) { this . callback = callback ; this . startTime = Date . now ( ) ; /**
         * Time in milliseconds of when <code>callback</code> should be invoked,
         * relative to  startTime .
          this . runTime = runTime ; this . updateTimer ( ) ; } public stop ( ) { if ( this . runningTimeout == null ) { return false ; } else { clearTimeout ( this . runningTimeout ) ; return true ; } } public update ( newRunTime ) { if ( this . completed ) { return ; } this . runTime = newRunTime ; this . updateTimer ( ) ; } private updateTimer ( ) { this . stop ( ) ; let timeRemaining ; if ( this . runningTimeout == null ) { timeRemaining = this . runTime ; } else { const currentTime = Date . now ( ) ; const alreadyPassed = currentTime - this . startTime ; timeRemaining = this . runTime - alreadyPassed ; } this . runningTimeout = setTimeout ( this . invokeCallback . bind ( this ) , timeRemaining ) ; } private invokeCallback ( ) { this . completed = true ; this . callback ( ) ; } }