var compose = require('lodash.flowright');
var {findIndex, isObject} = require('./helpers/cursor_helper');
var reactUpdate = require('react/lib/update');

var async = true;
var privates = new WeakMap();

class Cursor {
  static get async() { return async; }

  static set async(bool) { async = bool; }

  constructor(data, callback, {path = [], state = {updates: [], data}} = {}) {
    privates.set(this, {data, callback, path, state});
  }

  refine(...query) {
    var {callback, data, path, state} = privates.get(this);
    if (!query.some(isObject)) return new Cursor(data, callback, {path: path.concat(query), state});
    query = query.map(findIndex.bind(this, query));
    return new Cursor(data, callback, {path: path.concat(query), state});
  }

  get(...morePath) {
    var {data, path} = privates.get(this);
    return path.concat(morePath).reduce((memo, step) => memo[step], data);
  }

  isEqual(otherCursor) {
    return this.get() === otherCursor.get();
  }

  apply(options) {
    return this.update({$apply: options});
  }

  merge(options) {
    return this.update({$merge: options});
  }

  set(options) {
    return this.update({$set: options});
  }

  push(...options) {
    return this.update({$push: options});
  }

  remove(object) {
    return this.splice([this.get().indexOf(object), 1]);
  }

  splice(...options) {
    return this.update({$splice: options});
  }

  unshift(...options) {
    return this.update({$unshift: options});
  }

  nextTick(fn) {
    setImmediate(fn);
  }

  flush() {
    var {callback, state} = privates.get(this);
    if (!state.updates.length) return this;
    var fn = compose(...state.updates);
    state.updates = [];
    state.data = fn.call(this, state.data);
    callback(state.data);
    return this;
  }

  update(options) {
    var {path, state} = privates.get(this);
    var query = path.reduceRight((memo, step) => ({[step]: {...memo}}), options);
    state.updates.unshift(data => reactUpdate(data, query));
    if (Cursor.async) {
      if (state.updates.length === 1) this.nextTick(this.flush.bind(this));
      return this;
    }
    return this.flush();
  }
}

module.exports = Cursor;
@@ -1795,32 +1795,43 @@
 var %7Bpath, state
+: %7Bupdates%7D
 %7D = privates.get
@@ -1920,30 +1920,24 @@
 tions);%0A    
-state.
 updates.unsh
@@ -2009,22 +2009,16 @@
     if (
-state.
 updates.

use destructured updates instead of calling through the state