'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

exports.default = createDevStore;

var _jsan = require('jsan');

var _monitorActions = require('./monitorActions');

function createDevStore(onDispatch) {
  var initialState = {
    actionsById: {},
    computedStates: [],
    currentStateIndex: -1,
    monitorState: {},
    nextActionId: 0,
    skippedActionIds: [],
    stagedActionIds: []
  };
  var currentState = [];
  var listeners = [];
  var isReduxStore = [];
  var actionCreators = [];
  var instance = void 0;

  function getState(id, strict) {
    if (id) return currentState[id] || !strict && initialState;
    if (instance) return currentState[instance] || initialState;
    return initialState;
  }

  function getInitialState() {
    return initialState;
  }

  function getInstance() {
    return instance;
  }

  function update() {
    listeners.forEach(function (listener) {
      return listener();
    });
  }

  function setState(state, id, onChanged) {
    var isNew = !currentState[id];
    if (isNew && onChanged) onChanged();
    currentState[id] = state;
    update();
  }

  function setInstance(id, toUpdate) {
    instance = id;
    if (toUpdate && instance) update();
  }

  function deleteInstance(id) {
    delete currentState[id];
    delete isReduxStore[id];
    instance = Object.keys(currentState)[0];
    update();
  }

  function clear() {
    currentState = [];
    isReduxStore = [];
    update();
  }

  function dispatch(action) {
    var id = arguments.length <= 1 || arguments[1] === undefined ? instance : arguments[1];

    var state = void 0;
    if (action.type === 'JUMP_TO_STATE') {
      var liftedState = getState(id);
      if (!isReduxStore[id]) state = (0, _jsan.stringify)(liftedState.computedStates[action.index].state);
      onDispatch('DISPATCH', action, id, state);
      setState(_extends({}, liftedState, { currentStateIndex: action.index }), id);
    } else if (action.type[0] !== '@') {
      if (!isReduxStore[id]) {
        if (action.type === 'ROLLBACK') {
          state = (0, _jsan.stringify)(getState(id).computedStates[0].state);
        } else if (action.type === 'TOGGLE_ACTION') {
          state = (0, _jsan.stringify)(getState(id));
        } else if (action.type === 'SWEEP') {
          setState((0, _monitorActions.sweep)(getState(id)), id);
          return null;
        }
      }
      onDispatch('DISPATCH', action, id, state);
    }
    return action;
  }

  function dispatchAction(action, id) {
    onDispatch('ACTION', action, id || instance);
    return action;
  }

  function importState(state, id) {
    onDispatch('IMPORT', undefined, id || instance, state);
  }

  function subscribe(listener) {
    listeners.push(listener);

    return function unsubscribe() {
      var index = listeners.indexOf(listener);
      listeners.splice(index, 1);
    };
  }

  function init(_ref) {
    var id = _ref.id;
    var type = _ref.type;
    var action = _ref.action;

    if (type === 'STATE') isReduxStore[id] = true;
    var creators = action;
    if (typeof creators === 'string') creators = JSON.parse(creators);
    if (Array.isArray(creators)) actionCreators[id] = creators;
  }

  function getActionCreators(id) {
    return actionCreators[id || instance];
  }

  function isRedux(id) {
    return isReduxStore[id || instance];
  }

  return {
    dispatch: dispatchAction,
    getState: getState,
    subscribe: subscribe,
    init: init,
    getActionCreators: getActionCreators,
    isRedux: isRedux,
    clear: clear,
    liftedStore: {
      dispatch: dispatch,
      getInstance: getInstance,
      getInitialState: getInitialState,
      getState: getState,
      setState: setState,
      setInstance: setInstance,
      deleteInstance: deleteInstance,
      subscribe: subscribe,
      importState: importState
    }
  };
}
module.exports = exports['default'];