import { EventEmitter } from 'events' ; import { Event } from './Event' ; import { SelfDestructingCallbackInterface } from './EventManagerTypes' ; import { createDebugLogger } from '../../debug' ; const debug = createDebugLogger ( 'eventManager' ) ; export class EventManager extends EventEmitter { protected sharedEventManager : EventManager ; private hooks : { [ eventName ] : Array < Function > ; } = { } ; public constructor ( sharedEventManager = null ) { super ( ) ; this . sharedEventManager = sharedEventManager ; } async trigger ( eventName , target , payload ? ) { debug ( `Triggering event: ${ eventName }.` ) ; if ( ! this . hooks [ eventName ] ) { debug ( 'No listeners attached.' ) ; return false ; } const callbacks = this . hooks [ eventName ] ; let triggered = 0 ; let detached = 0 ; let remaining = callbacks . length ; for ( let i = 0 ; i < remaining ; i ++ ) { const callback = callbacks [ i ] as SelfDestructingCallbackInterface ; await callback ( new Event < typeof target > ( eventName , target , payload ) ) ; if ( callback . _isSelfDestructingCallback ) { callbacks . splice ( i , 1 ) ; detached ++ ; remaining -- ; i -- ; } triggered ++ ; } if ( ! remaining ) { delete this . hooks [ eventName ] ; } debug ( `Called ${ triggered } listeners for: ${ eventName } (detached ${ detached } one-time listeners).` ) ; return true ; } has ( event , callback ) { return this . hooks [ event ] && this . hooks [ event ] . indexOf ( callback ) > - 1 ; } attachOnce ( eventName , callback , index ? ) { ( callback as SelfDestructingCallbackInterface ) . _isSelfDestructingCallback = true ; this . attach ( eventName , callback , index ) ; } attach ( event , callback , index ? ) { this . hooks [ event ] = this . hooks [ event ] || [ ] ; if ( index ) { this . hooks [ event ] . splice ( index , 0 , callback ) ; } else { this . hooks [ event ] . push ( callback ) ; } return this ; } attachAt ( index , event , callback ) { return this . attach ( event , callback , index ) ; } detach ( event , callback ) { if ( ! this . hooks [ event ] ) { return this ; } const hookIndex = this . hooks [ event ] . indexOf ( callback ) ; if ( hookIndex === - 1 ) { return this ; } this . hooks [ event ] . splice ( hookIndex , 1 ) ; if ( this . hooks [ event ] . length === 0 ) { delete this . hooks [ event ] ; } return this ; } getSharedEventManager ( ) { return this . sharedEventManager ; } }