import { Observable , Subject , defer } from 'rxjs' ; import { Emission } from '../shared/emission' ; import { BasePin } from './base' ; import { PinLike } from './pin-like' ; import { PinLockedError } from './errors/locked.error' ; import { UnresolvedPinObservableError } from './errors/unresolved-observable.error' ; /**
 *
 * Represents pins that you can connect other pins to.
 *
 */ export abstract class Connectible extends BasePin { private _inbound : PinLike [ ] ; private _observable : Observable < Emission > | undefined ; private _resolving = false ; private _deferred : Subject < Emission > | undefined ; private _deference_connected = false ; constructor ( ) { super ( ) ; this . _inbound = [ ] ; } note public connect ( pin ) { if ( this . locked ) throw new PinLockedError ( ) ; if ( ! this . _inbound . includes ( pin ) ) this . _inbound . push ( pin ) ; return this ; } note public get observable ( ) : Observable < Emission > { if ( this . shouldResolve ( this . _inbound , this . _observable ) ) { if ( this . _resolving ) { if ( ! this . _deferred ) { this . _deferred = new Subject < any > ( ) ; } return this . _deferred ; } else { this . _resolving = true ; this . _observable = this . resolve ( this . _inbound ) ; if ( this . _deferred ) { let _pristine = this . _observable ; this . _observable = defer ( ( ) => { if ( ! this . _deference_connected ) { this . track ( _pristine . subscribe ( this . _deferred ) ) ; this . _deference_connected = true ; } return _pristine ; } ) ; } this . _resolving = false ; } } if ( ! this . _observable ) throw new UnresolvedPinObservableError ( ) ; return this . _observable ; } note public clear ( ) { this . _inbound . length = 0 ; this . _observable = undefined ; this . _deference_connected = false ; if ( this . _deferred ) { this . _deferred . complete ( ) ; this . _deferred = undefined ; } return super . clear ( ) ; } returns public get locked ( ) : boolean { return this . isLocked ( this . _observable ) ; } returns public get connected ( ) : boolean { return this . isConnected ( ) ; } /**
     *
     * Override this to determine the value of `.connected` through other means.
     *
     */ protected isConnected ( ) { return this . _inbound . length > 0 ; } param observable protected abstract isLocked ( observable ) ; param inbound param observable protected abstract shouldResolve ( inbound , observable ) ; param inbound protected abstract resolve ( inbound ) ; }