module import VidarObject from './object' ; export interface Event { target : VidarObject ; type : string ; } private class TypeId { private _parts : string [ ] ; constructor ( id ) { this . _parts = id . split ( '.' ) ; } contains ( other ) { if ( other . _parts . length > this . _parts . length ) return false ; for ( let i = 0 ; i < other . _parts . length ; i ++ ) if ( other . _parts [ i ] !== this . _parts [ i ] ) return false ; return true ; } toString ( ) { return this . _parts . join ( '.' ) ; } } param target param type param listener export function subscribe ( target , type , listener ) { if ( ! listeners . has ( target ) ) listeners . set ( target , [ ] ) ; listeners . get ( target ) . push ( { type : new TypeId ( type ) , listener } ) ; } param target param type param listener export function unsubscribe ( target , listener ) { if ( ! listeners . has ( target ) || ! listeners . get ( target ) . map ( pair => pair . listener ) . includes ( listener ) ) throw new Error ( 'No matching event listener to remove' ) ; const removed = listeners . get ( target ) . filter ( pair => pair . listener !== listener ) ; listeners . set ( target , removed ) ; } param target param type param event export function publish ( target , type , event ) { ( event as unknown as Event ) . target = target ; ( event as unknown as Event ) . type = type ; const t = new TypeId ( type ) ; if ( ! listeners . has ( target ) ) return null ; const listenersForType = [ ] ; for ( let i = 0 ; i < listeners . get ( target ) . length ; i ++ ) { const item = listeners . get ( target ) [ i ] ; if ( t . contains ( item . type ) ) listenersForType . push ( item . listener ) ; } for ( let i = 0 ; i < listenersForType . length ; i ++ ) { const listener = listenersForType [ i ] ; listener ( event ) ; } return event as unknown as Event ; } const listeners = new WeakMap ( ) ;