import * as I from 'immutable'; import {compose} from '@avocado/core'; import {Property} from '@avocado/mixins'; import {nextStep} from './next-step'; const decorate = compose( Property('state'), ); export function Synchronized(Superclass) { return class Synchronized extends decorate(Superclass) { constructor(...args) { super(...args); this.state = I.Map(); } synchronizedChildren() { return []; } patchState(patch) { for (const step of patch) { const {op, path, value} = step; if ('/' === path) { for (const key in value) { this.patchStateStep(key, { op, path, value: value[key], }); } } else { const [key, substep] = nextStep(step); this.patchStateStep(key, { op: substep.op, path: substep.path, value: substep.value, }); } } } patchStateStep(key, step) { if (!(key in this)) { return; } if ( 'undefined' !== typeof this[key] && 'undefined' !== typeof this[key].patchState ) { this[key].patchState([step]); } else { this[key] = step.value; } } tick(elapsed) { const children = this.synchronizedChildren(); for (const key of children) { if ( 'undefined' !== typeof this[key] && 'undefined' !== typeof this[key].tick ) { this[key].tick(elapsed); } } this.state = this.state.withMutations((state) => { for (const key of children) { if ( 'undefined' !== typeof this[key] && 'undefined' !== typeof this[key].state ) { state.set(key, this[key].state); } else { state.set(key, this[key]); } } }); } } }