'use strict'; import ActionDispatcher = require('./action-dispatcher'); import StateTransition = require('./state-transition'); import Callback = require('./callback'); export interface bindFn { (getState: () => State, setState: (s: State) => any): State; } export class LeafNode { private _bind: bindFn; private _state: State; private _callbacks: Callback[] = []; constructor(bind: bindFn) { this._bind = bind; this._state = bind( () => { return this.current; }, (s: State) => { this._setState(s); } ); } get current(): State { return this._state; } watch(callback: Callback): LeafNode { this._callbacks.push(callback); return this; } watchNext(callback: Callback): LeafNode { const wrapped = (s: State) => { this.unwatch(wrapped); callback(s); }; this.watch(wrapped); return this; } unwatch(callback: Callback): LeafNode { for(let i = 0; i < this._callbacks.length; i++) { if(this._callbacks[i] === callback) { this._callbacks.splice(i, 1); break; } } return this; } removeAllWatchers(): LeafNode { this._callbacks = []; return this; } private _setState(state: State): void { const prevState = this._state; this._state = state; if(prevState === state) return; this._notify(); } private _notify() { for(let i = 0; i < this._callbacks.length; i++) { this._callbacks[i](this._state); } } }