import * as d3FlexTree from 'd3-flextree';
import { FILE_NODE_TYPE, DIR_NODE_TYPE, FOLDER_OPEN_STATE } from '../../constants';
import { LAYOUT_CONFIG } from '../../../components/treeDiagram/component/constants';
export var getTreeLayout = function getTreeLayout(treeData, _ref) {
  var includeFileChildren = _ref.includeFileChildren,
      extraSpaceForDetails = _ref.extraSpaceForDetails,
      extraSpaceForCodePreview = _ref.extraSpaceForCodePreview,
      _ref$config = _ref.config,
      config = _ref$config === void 0 ? LAYOUT_CONFIG : _ref$config,
      openedFolders = _ref.openedFolders,
      activeItemsMap = _ref.activeItemsMap,
      activeCodeCrumbs = _ref.activeCodeCrumbs;
  var activeCodecrumbsFiles = activeCodeCrumbs && Object.values(activeCodeCrumbs).reduce(function (acc, item) {
    if (typeof acc[item.filePath] === 'undefined') {
      acc[item.filePath] = item.flowStep;
    } else if (item.flowStep < acc[item.filePath]) {
      acc[item.filePath] = item.flowStep;
    }

    return acc;
  }, {}) || {};
  var layoutStructure = d3FlexTree.flextree({
    children: function children(data) {
      if (data.type === DIR_NODE_TYPE) {
        if (openedFolders[data.path] === FOLDER_OPEN_STATE.CLOSED) {
          return [];
        }

        var children = openedFolders[data.path] === FOLDER_OPEN_STATE.OPEN_ACTIVE_CHILDREN_ONLY ? data.children.filter(function (child) {
          return activeItemsMap[child.path];
        }) : data.children;
        return activeCodeCrumbs ? children.map(function (i) {
          return i;
        }).sort(sortNodesForCc(activeCodecrumbsFiles)) : children;
      }

      if (!includeFileChildren) {
        return [];
      }

      return !activeCodeCrumbs ? data.children : (data.children || []).filter(function (_ref2) {
        var params = _ref2.params;
        return !!activeCodeCrumbs[params.original];
      }).sort(function (a, b) {
        return stepsSorter(a.params.flowStep, b.params.flowStep);
      });
    },
    nodeSize: function nodeSize(node) {
      var nameLength = node.data.name.length;

      if (node.parent && node.data.type === DIR_NODE_TYPE) {
        var children = node.parent.children;
        nameLength = children.reduce(function (max, item) {
          if (item.data.type === DIR_NODE_TYPE && item.data.name.length > max) {
            return item.data.name.length;
          }

          return max;
        }, 0);
      } // TODO: calc properly, not 5000
      // impossible to do in one loop


      var LARGE_WIDTH_CC = 5000;
      var widthSpace = node.data.type !== DIR_NODE_TYPE && node.data.type !== FILE_NODE_TYPE ? LARGE_WIDTH_CC : nameLength * config.symbolWidth + config.nodeSizeY;

      if (extraSpaceForDetails && node.data.type !== DIR_NODE_TYPE && node.data.type !== FILE_NODE_TYPE && node.data.params && node.data.params.details) {
        return [calcHeightForDetails(node), widthSpace];
      }

      if (extraSpaceForCodePreview && node.data.type !== DIR_NODE_TYPE && node.data.type !== FILE_NODE_TYPE) {
        return [calcHeightForCodePreview(node), widthSpace];
      }

      return [config.nodeSizeX, widthSpace];
    },
    spacing: function spacing() {
      return config.spacing;
    }
  });
  var tree = layoutStructure.hierarchy(treeData);
  return layoutStructure(tree);
};
export var sortNodesForCc = function sortNodesForCc(activeCodecrumbsFiles) {
  return function (aNode, bNode) {
    var aNodeStepOrder = getNodeFlowStepOrder(activeCodecrumbsFiles, aNode);
    var bNodeStepOrder = getNodeFlowStepOrder(activeCodecrumbsFiles, bNode);
    return stepsSorter(aNodeStepOrder, bNodeStepOrder);
  };
};
export var stepsSorter = function stepsSorter(stepA, stepB) {
  return stepA > stepB ? 1 : -1;
};

var getNodeFlowStepOrder = function getNodeFlowStepOrder(activeCodecrumbsFiles, _ref3) {
  var path = _ref3.path;

  if (activeCodecrumbsFiles[path]) {
    return activeCodecrumbsFiles[path];
  }

  var children = Object.keys(activeCodecrumbsFiles).filter(function (p) {
    return !!p.startsWith(path);
  });
  return children.reduce(function (acc, child) {
    if (activeCodecrumbsFiles[child] < acc) {
      return activeCodecrumbsFiles[child];
    }

    return acc;
  }, Infinity);
};

export var getFileNodesMap = function getFileNodesMap(layoutNodes) {
  var map = {};
  layoutNodes.each(function (node) {
    if (node.data && node.data.type === FILE_NODE_TYPE) {
      map[node.data.path] = node;
    }
  });
  return map;
};
export var getCodecrumbNodesMap = function getCodecrumbNodesMap(fileNodesMap) {
  return Object.keys(fileNodesMap).reduce(function (map, key) {
    var node = fileNodesMap[key];

    if (node.data && node.data.type === FILE_NODE_TYPE && node.children) {
      map[node.data.path] = node;
    }

    return map;
  }, {});
};
export var getFilesForCurrentCcFlow = function getFilesForCurrentCcFlow(_ref4) {
  var codeCrumbedFlowsMap = _ref4.codeCrumbedFlowsMap,
      selectedCrumbedFlowKey = _ref4.selectedCrumbedFlowKey,
      filesMap = _ref4.filesMap;
  return Object.keys(codeCrumbedFlowsMap[selectedCrumbedFlowKey]).filter(function (filePath) {
    var steps = (filesMap[filePath] && filesMap[filePath].children || []).filter(function (_ref5) {
      var params = _ref5.params;
      return params.flow === selectedCrumbedFlowKey;
    });
    return steps && steps.length;
  });
};
export var getCodeCrumbsMapForCurrentCcFlow = function getCodeCrumbsMapForCurrentCcFlow(_ref6) {
  var codeCrumbedFlowsMap = _ref6.codeCrumbedFlowsMap,
      selectedCrumbedFlowKey = _ref6.selectedCrumbedFlowKey,
      filesMap = _ref6.filesMap;
  var ccMap = {};
  Object.keys(codeCrumbedFlowsMap[selectedCrumbedFlowKey]).map(function (filePath) {
    return {
      filePath: filePath,
      steps: (filesMap[filePath] && filesMap[filePath].children || []).filter(function (_ref7) {
        var params = _ref7.params;
        return params.flow === selectedCrumbedFlowKey;
      })
    };
  }).filter(function (_ref8) {
    var steps = _ref8.steps;
    return steps.length;
  }).forEach(function (_ref9) {
    var filePath = _ref9.filePath,
        steps = _ref9.steps;
    steps.forEach(function (_ref10) {
      var params = _ref10.params;
      ccMap[params.original] = {
        filePath: filePath,
        flowStep: params.flowStep
      };
    });
  });
  return ccMap;
}; //TODO: numbers based on styles, better to do something with that..

var calcHeightForDetails = function calcHeightForDetails(_ref11) {
  var data = _ref11.data;

  var _ref12 = data.params || {},
      details = _ref12.details;

  var nameWidth = data.name ? data.name.length * 7.5 : 100;
  if (nameWidth < 250) nameWidth = 250;
  var n = Math.ceil(details.length * 7 / nameWidth);
  return (n + 1) * 20 + 50;
};

var calcHeightForCodePreview = function calcHeightForCodePreview() {
  var n = 5;
  return n * 15 + 40;
};