import parseJSON from '../utils/parseJSON';

function recompute(previousLiftedState, storeState, action, nextActionId) {
  const actionId = nextActionId - 1;
  const liftedState = { ...previousLiftedState };
  liftedState.stagedActionIds = [...liftedState.stagedActionIds, actionId];
  liftedState.actionsById = { ...liftedState.actionsById };
  liftedState.actionsById[actionId] = action;
  liftedState.nextActionId = nextActionId;
  liftedState.computedStates = [...liftedState.computedStates, { state: storeState }];
  liftedState.currentStateIndex++;
  return liftedState;
}

export default function updateState(store, request) {
  const payload = parseJSON(request.payload);
  if (!payload) return null;

  switch (request.type) {
    case 'ACTION':
      const newState = recompute(store.liftedStore.getState(), payload, parseJSON(request.action), request.nextActionId);
      store.liftedStore.setState(newState);
      return newState;
    case 'STATE':
      store.liftedStore.setState(payload);
      return payload;
    default:
      return null;
  }
}

import parseJSON from '../utils/parseJSON';

function recompute(previousLiftedState, storeState, action, nextActionId = 1) {
  const actionId = nextActionId - 1;
  const liftedState = { ...previousLiftedState };
  liftedState.stagedActionIds = [...liftedState.stagedActionIds, actionId];
  liftedState.actionsById = { ...liftedState.actionsById };
  if (action.type === 'PERFORM_ACTION') {
    liftedState.actionsById[actionId] = action;
  } else {
    liftedState.actionsById[actionId] = {
      action: action.action || action,
      timestamp: action.timestamp,
      type: 'PERFORM_ACTION'
    };
  }
  liftedState.nextActionId = nextActionId;
  liftedState.computedStates = [...liftedState.computedStates, { state: storeState }];
  liftedState.currentStateIndex++;
  return liftedState;
}

export default function updateState(store, request) {
  const payload = parseJSON(request.payload);
  if (!payload) return null;

  let newState;
  let action = {};
  if (request.action) action = parseJSON(request.action) || {};

  switch (request.type) {
    case 'INIT':
      newState = recompute(
        store.liftedStore.getInitialState(),
        payload,
        { action: { type: '@@INIT' }, timestamp: action.timestamp }
      );
      break;
    case 'ACTION':
      newState = recompute(
        store.liftedStore.getState(),
        payload,
        action,
        request.nextActionId
      );
      break;
    case 'STATE':
      newState = payload;
      break;
    default:
      return null;
  }
  store.liftedStore.setState(newState);
  return newState;
}

Create `INIT` action