'use strict';

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

var _slicedToArray2 = require('babel-runtime/helpers/slicedToArray');

var _slicedToArray3 = _interopRequireDefault(_slicedToArray2);

var _defineProperty2 = require('babel-runtime/helpers/defineProperty');

var _defineProperty3 = _interopRequireDefault(_defineProperty2);

var _immutable = require('immutable');

var _keyBy = require('lodash/keyBy');

var _keyBy2 = _interopRequireDefault(_keyBy);

var _sortBy3 = require('lodash/sortBy');

var _sortBy4 = _interopRequireDefault(_sortBy3);

var _isArrayLike = require('lodash/isArrayLike');

var _isArrayLike2 = _interopRequireDefault(_isArrayLike);

var _constants = require('../../constants');

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var addQuizEntries = function addQuizEntries(state, quizEntries) {
  var quizEntriesHash = (0, _keyBy2.default)(quizEntries, 'id');
  return (0, _immutable.fromJS)(quizEntriesHash);
};

var addQuizEntry = function addQuizEntry(state, quizEntry) {
  // This is sad, but because of how we handle our data in the
  // getPersistenceActions/CallHandlers all of our data will be
  // arrays coming in to the store from fetcher, even if it
  // _should_ be a single object.
  var qe = (0, _isArrayLike2.default)(quizEntry) ? (0, _keyBy2.default)(quizEntry, 'id') : (0, _defineProperty3.default)({}, quizEntry.id, quizEntry);
  return state.mergeDeep((0, _immutable.fromJS)(qe));
};

var deleteQuizEntry = function deleteQuizEntry(state, _ref2) {
  var id = _ref2.id;

  var deletedEntry = state.get(id);
  var stateWithoutDeletedEntry = state.delete(id);

  // Adjust the positions of subsequent quiz entries, to fill in the gap left
  // by the one we're deleting.
  var moved = stateWithoutDeletedEntry.filter(function (entry) {
    return entry.get('position') > deletedEntry.get('position');
  }).map(function (entry) {
    return entry.set('position', entry.get('position') - 1);
  });

  return stateWithoutDeletedEntry.merge(moved);
};

var deleteStimulusEntry = function deleteStimulusEntry(state, _ref3) {
  var id = _ref3.id,
      _ref3$childQuizEntryI = _ref3.childQuizEntryIds,
      childQuizEntryIds = _ref3$childQuizEntryI === undefined ? [] : _ref3$childQuizEntryI;

  var stimulusEntry = state.get(id);
  // TODO: use deleteAll here after upgrading to immutable 4:
  // http://facebook.github.io/immutable-js/docs/#/Map/deleteAll
  var stateWithoutDeletedEntries = childQuizEntryIds.reduce(function (reduced, childQuizEntryId) {
    return reduced.delete(childQuizEntryId);
  }, state.delete(id));

  // Disassociate any quiz entries that were associated with the stimulus, but
  // not deleted along with it.
  var disassociated = stateWithoutDeletedEntries.map(function (entry) {
    return entry.get('stimulusQuizEntryId') === id ? entry.set('stimulusQuizEntryId', '') : entry;
  });

  // Adjust the positions of all the quiz entries that were associated with the
  // removed stimulus and were not deleted along with it, as well as all
  // subsequent entries, to fill in the gap left by the removed stimulus.
  var moved = disassociated.valueSeq().filter(function (entry) {
    return entry.get('position') > stimulusEntry.get('position');
  }).sortBy(function (entry) {
    return entry.get('position');
  }).map(function (entry, index) {
    return entry.set('position', stimulusEntry.get('position') + index);
  }).reduce(function (entries, entry) {
    return entries.set(entry.get('id'), entry);
  }, (0, _immutable.Map)());

  return disassociated.merge(moved);
};

var moveQuizEntry = function moveQuizEntry(state, _ref4) {
  var id = _ref4.id,
      position = _ref4.position,
      stimulusQuizEntryId = _ref4.stimulusQuizEntryId;

  var originalQuizEntry = state.get(id);
  var originalPosition = originalQuizEntry.get('position');
  var movedQuizEntry = originalQuizEntry.merge({ position: position, stimulusQuizEntryId: stimulusQuizEntryId });

  // If the position hasn't changed, we might still be moving the entry into or
  // out of a stimulus.
  if (position === originalPosition) {
    return state.set(id, movedQuizEntry);
  }

  // If the position has changed, move the quiz entries between the original
  // position and the new posision, to make space for it.
  // NOTE: this allows for gaps between position numbers, but not duplicates

  var _sortBy = (0, _sortBy4.default)([position, originalPosition]),
      _sortBy2 = (0, _slicedToArray3.default)(_sortBy, 2),
      start = _sortBy2[0],
      end = _sortBy2[1];

  var direction = position > originalPosition ? -1 : 1;
  var moved = state.delete(id).valueSeq().filter(function (entry) {
    return entry.get('position') >= start && entry.get('position') <= end;
  }).sortBy(function (entry) {
    return entry.get('position') * direction;
  }).map(function (entry, index) {
    return entry.set('position', position + (index + 1) * direction);
  }).reduce(function (entries, entry) {
    return entries.set(entry.get('id'), entry);
  }, (0, _immutable.Map)((0, _defineProperty3.default)({}, id, movedQuizEntry)));

  return state.merge(moved);
};

exports.default = function () {
  var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : (0, _immutable.Map)();
  var action = arguments[1];

  switch (action.type) {
    case _constants.ADD_QUIZ_ENTRIES:
      return addQuizEntries(state, action.payload);
    case _constants.ADD_QUIZ_ENTRY:
      return addQuizEntry(state, action.payload);
    case _constants.DELETE_QUIZ_ENTRY:
      return deleteQuizEntry(state, action.payload);
    case _constants.DELETE_STIMULUS_ENTRY:
      return deleteStimulusEntry(state, action.payload);
    case _constants.MOVE_QUIZ_ENTRY:
      return moveQuizEntry(state, action.payload);
    default:
      return state;
  }
};