import Rx from 'rxjs/Rx';
import difference from 'lodash.difference';

/**
 * Updates widget models based on the redux store state.
 */
export class ModelUpdater {

  /**
   * Public constructor.
   * @param  {Redux.store} store
   * @param  {widgets.WidgetManager} manager
   * @return {ModelUpdater}
   */
  constructor(store, manager) {
    // Listen for changes to the redux store widgets
    Rx.Observable.from(store)
      .pluck('document')
      .map(document => document.get('widgetModels'))
      .distinctUntilChanged((a, b) => !a || a.equals(b))
      .subscribe(this.reduxStateChange.bind(this, manager));
  }

  /**
   * Update the widget models based on the state store change
   * @param  {widgets.WidgetManager} manager
   * @param  {object} newState - state of the widgets key
   */
  reduxStateChange(manager, newState) {
    if (!newState) return;

    // Delete widgets that no longer exist in the state.
    manager.deleteModels(
      difference(Object.keys(manager.modelPromises), newState.keySeq().toJS())
    );

    // Set new states
    newState.entrySeq().forEach(modelState => {
      const [model, state] = modelState;
      manager.setModelState(model, state.toJS());
    });
  }
}

import Rx from 'rxjs/Rx';
import difference from 'lodash.difference';

/**
 * Updates widget models based on the redux store state.
 */
export class ModelUpdater {

  /**
   * Public constructor.
   * @param  {Redux.store} store
   * @param  {widgets.WidgetManager} manager
   * @return {ModelUpdater}
   */
  constructor(store, manager) {
    // Listen for changes to the redux store widgets
    this.widgetSubscriptions = {};
    Rx.Observable.from(store)
      .pluck('document')
      .map(document => document.get('widgetModels'))
      .distinctUntilChanged((a, b) => !a || a.equals(b))
      .subscribe(this.reduxStateChange.bind(this, store, manager));
  }

  /**
   * Update the widget models based on the state store change
   * @param  {widgets.WidgetManager} manager
   * @param  {object} newState - state of the widgets key
   */
  reduxStateChange(store, manager, newState) {
    if (!newState) return;

    // Delete widgets that no longer exist in the state.
    const deleted = difference(
      Object.keys(manager.modelPromises),
      newState.keySeq().toJS()
    );
    manager.deleteModels(deleted);
    deleted.forEach(id => {
      this.widgetSubscriptions[id].unsubscribe();
      delete this.widgetSubscriptions[id];
    });

    // Create missing state subscriptions.
    const created = difference(
      newState.keySeq().toJS(),
      Object.keys(this.widgetSubscriptions)
    );
    created.forEach(id => {
      this.widgetSubscriptions[id] = Rx.Observable.from(store)
        .pluck('document')
        .map(document => document.getIn(['widgetModels', id]))
        .distinctUntilChanged((a, b) => !a || a.equals(b))
        .subscribe(state => {
          manager.setModelState(id, state.toJS());
        });
    });
  }
}

Make the redux -> widgets logic a little bit smarter
Make the redux -> widgets logic a little bit smarter
