import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
import _defineProperty from "@babel/runtime/helpers/defineProperty";
import _objectSpread from "@babel/runtime/helpers/objectSpread";
import { FOLDER_OPEN_STATE } from '../constants';
import { ACTIONS } from './constants';
import { getFileNodesMap, getCodecrumbNodesMap } from './utils/treeLayout';
import { calculateLayoutProps } from './utils/geometry';
var DefaultState = {};
var DefaultNamespaceState = {
  sourceTree: null,
  filesMap: null,
  foldersMap: null,
  sourceLayoutTree: null,
  layoutSize: null,
  filesLayoutMap: {},
  codecrumbsLayoutMap: {},
  openedFolders: {},
  activeItemsMap: {},
  selectedNode: null,
  dependenciesEntryName: undefined,
  selectedDependencyEdgeNodes: null,
  selectedCodeCrumb: null,
  codeCrumbedFlowsMap: {},
  selectedCrumbedFlowKey: undefined
};
export var getMergeState = function getMergeState(state, namespace) {
  return function (namespaceStateUpdate) {
    return _objectSpread({}, state, _defineProperty({}, namespace, _objectSpread({}, state[namespace], namespaceStateUpdate)));
  };
};
var FULL_FEATURES_LANG_LIST = ['javascript', 'typescript'];
export default (function () {
  var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : DefaultState;
  var action = arguments.length > 1 ? arguments[1] : undefined;
  var namespace = action.namespace;
  var namespaceState = state[namespace];
  var mergeState = getMergeState(state, namespace);

  switch (action.type) {
    case ACTIONS.SET_INITIAL_SOURCE_DATA:
      {
        var _action$payload = action.payload,
            dependenciesEntryName = _action$payload.dependenciesEntryName,
            filesMap = _action$payload.filesMap,
            foldersMap = _action$payload.foldersMap;
        return mergeState(_objectSpread({}, DefaultNamespaceState, action.payload, {
          fullFeaturesSupport: FULL_FEATURES_LANG_LIST.includes(action.payload.language),
          selectedNode: filesMap[dependenciesEntryName],
          openedFolders: _objectSpread({}, Object.keys(foldersMap).reduce(function (res, item) {
            res[item] = FOLDER_OPEN_STATE.CLOSED;
            return res;
          }, {}))
        }));
      }

    case ACTIONS.SET_CHANGED_SOURCE_DATA:
      return mergeState(action.payload);

    case ACTIONS.UPDATE_FILES_TREE_LAYOUT_NODES:
      {
        var sourceLayoutTree = action.payload;

        var _calculateLayoutProps = calculateLayoutProps(sourceLayoutTree),
            ccAlightPoint = _calculateLayoutProps.ccAlightPoint,
            layoutSize = _objectWithoutProperties(_calculateLayoutProps, ["ccAlightPoint"]);

        var filesLayoutMap = getFileNodesMap(sourceLayoutTree);
        var codecrumbsLayoutMap = getCodecrumbNodesMap(filesLayoutMap);
        return mergeState({
          sourceLayoutTree: sourceLayoutTree,
          layoutSize: layoutSize,
          filesLayoutMap: filesLayoutMap,
          codecrumbsLayoutMap: codecrumbsLayoutMap,
          ccAlightPoint: ccAlightPoint
        });
      }

    case ACTIONS.SELECT_NODE:
      {
        var payload = action.payload;
        return mergeState({
          selectedCodeCrumb: null,
          selectedNode: payload,
          dependenciesEntryName: payload.path,
          filesMap: _objectSpread({}, namespaceState.filesMap, _defineProperty({}, payload.path, payload))
        });
      }

    case ACTIONS.TOGGLE_FOLDER:
      {
        var openedFolders = namespaceState.openedFolders,
            activeItemsMap = namespaceState.activeItemsMap;
        var folderPath = action.payload.path;
        var openedStateValue = activeItemsMap[folderPath] !== undefined ? openedFolders[folderPath] === FOLDER_OPEN_STATE.OPEN ? FOLDER_OPEN_STATE.CLOSED : openedFolders[folderPath] + 1 : openedFolders[folderPath] === FOLDER_OPEN_STATE.OPEN ? FOLDER_OPEN_STATE.CLOSED : FOLDER_OPEN_STATE.OPEN;
        return mergeState({
          openedFolders: _objectSpread({}, openedFolders, _defineProperty({}, folderPath, openedStateValue))
        });
      }

    case ACTIONS.SET_ACTIVE_ITEMS:
      return mergeState({
        activeItemsMap: action.payload
      });

    case ACTIONS.SET_FOLDERS_STATE:
      return mergeState({
        openedFolders: _objectSpread({}, namespaceState.openedFolders, action.payload)
      });

    case ACTIONS.OPEN_ALL_FOLDERS:
      return mergeState({
        openedFolders: _objectSpread({}, Object.keys(namespaceState.foldersMap).reduce(function (res, item) {
          res[item] = FOLDER_OPEN_STATE.OPEN;
          return res;
        }, {}))
      });

    case ACTIONS.CLOSE_ALL_FOLDERS:
      return mergeState({
        openedFolders: _objectSpread({}, Object.keys(namespaceState.foldersMap).reduce(function (res, item) {
          res[item] = FOLDER_OPEN_STATE.CLOSED;
          return res;
        }, {}))
      });

    case ACTIONS.SELECT_CODE_CRUMB:
      var _action$payload2 = action.payload,
          fileNode = _action$payload2.fileNode,
          codeCrumb = _action$payload2.codeCrumb; //TODO: fileNode also can be folder, maybe don't use SELECT_CODE_CRUMB at all and use selected node as well

      return mergeState({
        selectedNode: fileNode,
        selectedCodeCrumb: codeCrumb
      });

    case ACTIONS.SELECT_CODE_CRUMBED_FLOW:
      return mergeState({
        selectedCrumbedFlowKey: action.payload,
        selectedCcFlowEdgeNodes: undefined
      });

    case ACTIONS.SET_DEPENDENCIES_ENTRY_POINT:
      {
        var _fileNode = action.payload.fileNode;

        var _dependenciesEntryName = _fileNode ? _fileNode.path : namespaceState.dependenciesEntryName; // do some reducerr


        return mergeState({
          dependenciesEntryName: _dependenciesEntryName,
          selectedDependencyEdgeNodes: null
        });
      }

    case ACTIONS.SELECT_DEPENDENCY_EDGE:
      return mergeState({
        selectedDependencyEdgeNodes: action.payload
      });

    case ACTIONS.SELECT_CC_FLOW_EDGE:
      return mergeState({
        selectedCcFlowEdgeNodes: action.payload
      });

    case ACTIONS.UPDATE_FILES:
      var selectedNode = namespaceState.selectedNode;
      var fileForSelectedNode = action.payload.find(function (item) {
        return item.path === selectedNode.path;
      });
      return mergeState({
        selectedNode: fileForSelectedNode ? _objectSpread({}, selectedNode, fileForSelectedNode) : selectedNode,
        filesMap: _objectSpread({}, namespaceState.filesMap, action.payload.reduce(function (acc, item) {
          acc[item.path] = _objectSpread({}, namespaceState.filesMap[item.path], item);
          return acc;
        }, {}))
      });

    case ACTIONS.SET_FULL_STATE:
      return _objectSpread({}, state, action.payload);

    case ACTIONS.SET_NAMESPACE_STATE:
      return mergeState(_objectSpread({}, action.payload));

    case ACTIONS.RESET_ALL:
      return DefaultState;

    default:
      return state;
  }
});