import { defineComponent, provide, createVNode } from 'vue';
import _defineProperty from '@babel/runtime/helpers/esm/defineProperty';
import { isFunction, isString } from 'lodash-es';
import getPrefixCls from '../_util/getPrefixCls';
import { useTheme } from '../_theme/useTheme';
import VirtualList from '../virtual-list';
import TreeNode from './treeNode';
import { COMPONENT_NAME } from './const';
import useData from './useData';
import useState from './useState';
import useDrag from './useDrag';
import useFilter from './useFilter';
import useExpand from './useExpand';
import useSelect from './useSelect';
import useCheck from './useCheck';
import useCurrentData from './useCurrentData';
import { TREE_PROVIDE_KEY, treeProps } from './props';

function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
const prefixCls = getPrefixCls('tree');
var tree = defineComponent({
  name: COMPONENT_NAME.TREE,
  props: _objectSpread({}, treeProps),
  emits: ['update:expandedKeys', 'update:checkedKeys', 'update:selectedKeys', 'update:nodeList', 'check', 'expand', 'load', 'select', 'dragstart', 'dragenter', 'dragover', 'dragleave', 'dragend', 'drop'],
  setup(props, _ref) {
    let {
      emit,
      expose,
      slots
    } = _ref;
    useTheme();
    const {
      nodeList,
      allKeys
    } = useData({
      props,
      emit
    });
    const {
      currentExpandedKeys,
      updateExpandedKeys,
      currentCheckedKeys,
      updateCheckedKeys,
      currentSelectedKeys,
      updateSelectedKeys,
      hasSelected,
      hasNoExpandableNode
    } = useState({
      props,
      emit
    });
    const {
      filter,
      filteredExpandedKeys,
      filteredKeys,
      isSearchingRef
    } = useFilter(props, allKeys, nodeList);
    const {
      expandNode,
      expandingNode
    } = useExpand({
      allKeys,
      isSearchingRef,
      filteredExpandedKeys,
      nodeList,
      currentExpandedKeys,
      updateExpandedKeys,
      props,
      emit
    });
    const {
      selectNode
    } = useSelect({
      nodeList,
      currentSelectedKeys,
      updateSelectedKeys,
      props,
      emit
    });
    const {
      checkNode
    } = useCheck({
      allKeys,
      nodeList,
      currentCheckedKeys,
      updateCheckedKeys,
      props,
      emit
    });
    const {
      currentData
    } = useCurrentData({
      props,
      isSearchingRef,
      filteredExpandedKeys,
      currentExpandedKeys,
      filteredKeys,
      allKeys,
      expandingNode,
      nodeList
    });
    const {
      handleDragstart,
      handleDragenter,
      handleDragover,
      handleDragleave,
      handleDragend,
      handleDrop,
      dragOverInfo,
      dragHighlightNode
    } = useDrag({
      nodeList,
      emit,
      expandNode
    });
    if (expose) {
      expose({
        selectNode,
        expandNode,
        checkNode,
        filter
      });
    }
    provide(TREE_PROVIDE_KEY, {
      props,
      slots,
      selectNode,
      expandNode,
      checkNode,
      hasSelected,
      nodeList,
      handleDragstart,
      handleDragenter,
      handleDragover,
      handleDragleave,
      handleDragend,
      handleDrop,
      dragOverInfo,
      dragHighlightNode
    });
    const renderNode = value => {
      const node = nodeList.get(value);
      const itemSlots = {};
      if (isFunction(node.prefix)) {
        itemSlots.prefix = node.prefix;
      }
      if (isString(node.prefix)) {
        itemSlots.prefix = () => node.prefix;
      }
      if (isFunction(node.suffix)) {
        itemSlots.suffix = node.suffix;
      }
      if (isString(node.suffix)) {
        itemSlots.suffix = () => node.suffix;
      }

      // 当前 node 在最顶层，且顶层所有 node 都没有 children
      const noExpand = node.level === 1 && hasNoExpandableNode.value;
      return createVNode(TreeNode, {
        "key": node.uid,
        "level": node.level,
        "value": node.value,
        "label": node.label,
        "disabled": node.disabled,
        "selectable": node.selectable,
        "checkable": node.checkable,
        "isLeaf": node.isLeaf,
        "draggable": props.draggable && !props.inline && !node.disabled,
        "noExpand": noExpand
      }, itemSlots);
    };
    const renderChildren = arr => arr.map(value => renderNode(value));
    const renderDefault = _ref2 => {
      let {
        source
      } = _ref2;
      return renderNode(source);
    };
    return () => props.virtualList && !props.inline ? createVNode(VirtualList, {
      "dataSources": currentData.value,
      "dataKey": source => {
        return source;
      },
      "estimateSize": 32,
      "keeps": 14,
      "observeResize": false,
      "class": prefixCls
    }, {
      default: renderDefault
    }) : createVNode("div", {
      "class": prefixCls,
      "role": "tree"
    }, [renderChildren(currentData.value)]);
  }
});

export { tree as default };
