const { createStore } = require('redux');

function change(collection, index, properties) {
  return collection.map((item, i) =>
    i === index ? Object.assign({ ...item }, properties(item)) : item);
}

// Modifies state by creating copy of all data except laying on the path.
// Callback is called when copying is complete, with all the new path nodes.
function modify(state, path, callback) {
  const copies = [];
  function copy(current, idx) {
    const item = Array.isArray(current) ? [...current] : { ...current };
    copies.push(item);
    copies.push(path[idx]);
    if (idx === path.length - 1) {
      copies.push(item[path[idx]]);
      copies.reverse();
      callback.apply(null, copies);
    } else {
      item[path[idx]] = copy(item[path[idx]], idx + 1, copies);
    }
    return item;
  }
  return copy(state, 0);
}

function model(state = {}, action) {
  switch (action.type) {
    case 'file':
      return JSON.parse(require('fs').readFileSync(action.path, { encoding: 'utf8' }));
    case 'set':
      return modify(state, action.path,
        (_, property, object) => object[property] = action.value);
    case 'add':
      return modify(state, action.path,
        collection => collection.push(action.item));
    case 'remove':
      return modify(state, action.path,
        (_, index, collection) => collection.splice(index, 1));
    default:
      return state
  }
}

exports.store = createStore(model);
