'use strict';

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

var _rollupPluginBabelHelpers = require('../../../_virtual/_rollupPluginBabelHelpers.js');
var deepCopy = require('../../../utils/deepCopy.js');

// Утилита для поиска ключа в объекте по пути.
var keyExists = function keyExists(obj, path) {
  if (_rollupPluginBabelHelpers.typeof(obj) !== 'object' || obj === null || !Array.isArray(path)) {
    return false;
  }
  var current = obj;
  for (var i = 0; i < path.length; i++) {
    var _key = path[i];
    if (current === null || _rollupPluginBabelHelpers.typeof(current) !== 'object' || !(_key in current)) {
      return false;
    }
    current = current[_key];
  }
  return true;
};
function createObjectAtPath(obj, path) {
  if (_rollupPluginBabelHelpers.typeof(obj) !== 'object' || obj === null) {
    return;
  }
  var current = obj;
  for (var i = 0; i < path.length; i++) {
    var _key2 = path[i];
    if (i === path.length - 1) {
      current[_key2] = {};
      break;
    }
    if (current[_key2] === undefined || current[_key2] === null) {
      current[_key2] = {};
    }
    current = current[_key2];
  }
  return obj;
}
function removeObjectAtPath(obj, path) {
  if (path.length === 0) {
    return obj;
  }
  var current = obj;
  for (var i = 0; i < path.length; i++) {
    var _key3 = path[i];
    if (current === null || _rollupPluginBabelHelpers.typeof(current) !== 'object' || !(_key3 in current)) {
      return obj;
    }
    if (i === path.length - 1) {
      delete current[_key3];
      break;
    }
    current = current[_key3];
  }
  return obj;
}

/**
 * Утилита, которая получает на вход список отфильтрованных элементов и
 * callback, с помощью которого эти элементы были отфильтрованы.
 * Возвращает TreePathState, т.е. список раскрытых групп.
 * По умолчанию группа не раскрывается, если в ней не было найдено ни одного элемента.
 * Но т.к. поиск может осуществляться как по элементам, так и по группам,
 * то может возникнуть ситуация, когда будет найдена как группа с определенным названием,
 * так и элемент с таким же названием внутри нее, и в таком случае мы должны частично раскрыть группу,
 * вплоть то найденного элемента.
 * Если найдена только группа, без элементов внутри нее, то саму эту группу
 * раскрывать не нужно. Нужно раскрыть только родителя этой группы.
 */
function generateNestedTreePathFromFilteredItems(filteredItems, filterCb, textValue) {
  var result = {};
  function traverse(items, currentPath) {
    var hasFoundItems = false;
    var _iterator = _rollupPluginBabelHelpers.createForOfIteratorHelper(items),
      _step;
    try {
      for (_iterator.s(); !(_step = _iterator.n()).done;) {
        var item = _step.value;
        var isFound = filterCb(item, textValue);
        if (item.items && item.items.length > 0) {
          // Обрабатываем детей
          var childPath = {};
          var foundInChildren = traverse(item.items, childPath);
          if (foundInChildren) {
            // Если в детях найдены элементы - добавляем путь
            currentPath[item.value] = childPath;
            hasFoundItems = true;
          }

          // Если сама группа найдена, но в детях ничего нет - НЕ добавляем путь
          // Просто отмечаем что что-то найдено на этом уровне
          if (isFound && !foundInChildren) {
            hasFoundItems = true;
          }
        } else if (isFound) {
          // Для конечного элемента не добавляем путь в currentPath,
          // но отмечаем что на этом уровне есть найденные элементы
          hasFoundItems = true;
        }
      }
    } catch (err) {
      _iterator.e(err);
    } finally {
      _iterator.f();
    }
    return hasFoundItems;
  }
  traverse(filteredItems, result);
  return result;
}
function treePathReducer(state, action) {
  switch (action.type) {
    case 'reset':
      {
        return {};
      }
    case 'toggled_level':
      {
        var stateCopy = deepCopy.deepCopy(state);
        var isTargetLevelOpened = keyExists(stateCopy, action.value);
        if (isTargetLevelOpened) {
          // нужно закрыть текущий уровень
          removeObjectAtPath(stateCopy, action.value);
        } else {
          // нужно открыть требуемый уровень
          createObjectAtPath(stateCopy, action.value);
        }
        return stateCopy;
      }
    case 'expand_by_key':
      {
        var _action$value = action.value,
          filteredItems = _action$value.filteredItems,
          filterCb = _action$value.filterCb,
          textValue = _action$value.textValue;
        return generateNestedTreePathFromFilteredItems(filteredItems, filterCb, textValue);
      }
    case 'open_level':
      {
        var _stateCopy = deepCopy.deepCopy(state);
        createObjectAtPath(_stateCopy, action.value);
        return _stateCopy;
      }
    case 'close_level':
      {
        var _stateCopy2 = deepCopy.deepCopy(state);
        removeObjectAtPath(_stateCopy2, action.value);
        return _stateCopy2;
      }
    default:
      {
        return state;
      }
  }
}

exports.keyExists = keyExists;
exports.treePathReducer = treePathReducer;
