import _extends from "@babel/runtime/helpers/esm/extends";
import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
import React, { forwardRef, useCallback } from 'react';
import PropTypes from 'prop-types';
import { hasClass } from 'dom-lib';
import ArrowDown from '@rsuite/icons/legacy/ArrowDown';
import Spinner from '@rsuite/icons/legacy/Spinner';
import reactToString from '../utils/reactToString';
import { useClassNames, TREE_NODE_PADDING, TREE_NODE_ROOT_PADDING } from '../utils';
var TreeNode = /*#__PURE__*/forwardRef(function (_ref, ref) {
  var _extends2;

  var _ref$as = _ref.as,
      Component = _ref$as === void 0 ? 'div' : _ref$as,
      rtl = _ref.rtl,
      label = _ref.label,
      layer = _ref.layer,
      style = _ref.style,
      active = _ref.active,
      loading = _ref.loading,
      nodeData = _ref.nodeData,
      className = _ref.className,
      classPrefix = _ref.classPrefix,
      disabled = _ref.disabled,
      visible = _ref.visible,
      draggable = _ref.draggable,
      expand = _ref.expand,
      focus = _ref.focus,
      hasChildren = _ref.hasChildren,
      dragging = _ref.dragging,
      dragOver = _ref.dragOver,
      dragOverTop = _ref.dragOverTop,
      dragOverBottom = _ref.dragOverBottom,
      onSelect = _ref.onSelect,
      onDragStart = _ref.onDragStart,
      onDragOver = _ref.onDragOver,
      onDragEnter = _ref.onDragEnter,
      onDragLeave = _ref.onDragLeave,
      onDragEnd = _ref.onDragEnd,
      onDrop = _ref.onDrop,
      onExpand = _ref.onExpand,
      onRenderTreeIcon = _ref.onRenderTreeIcon,
      onRenderTreeNode = _ref.onRenderTreeNode,
      rest = _objectWithoutPropertiesLoose(_ref, ["as", "rtl", "label", "layer", "style", "active", "loading", "nodeData", "className", "classPrefix", "disabled", "visible", "draggable", "expand", "focus", "hasChildren", "dragging", "dragOver", "dragOverTop", "dragOverBottom", "onSelect", "onDragStart", "onDragOver", "onDragEnter", "onDragLeave", "onDragEnd", "onDrop", "onExpand", "onRenderTreeIcon", "onRenderTreeNode"]);

  var _useClassNames = useClassNames(classPrefix),
      prefix = _useClassNames.prefix,
      merge = _useClassNames.merge,
      withClassPrefix = _useClassNames.withClassPrefix;

  var getTitle = useCallback(function () {
    if (typeof label === 'string') {
      return label;
    } else if ( /*#__PURE__*/React.isValidElement(label)) {
      var nodes = reactToString(label);
      return nodes.join('');
    }
  }, [label]);
  var handleExpand = useCallback(function (event) {
    var _event$nativeEvent, _event$nativeEvent$st;

    // stop propagation when using custom loading icon
    event === null || event === void 0 ? void 0 : (_event$nativeEvent = event.nativeEvent) === null || _event$nativeEvent === void 0 ? void 0 : (_event$nativeEvent$st = _event$nativeEvent.stopImmediatePropagation) === null || _event$nativeEvent$st === void 0 ? void 0 : _event$nativeEvent$st.call(_event$nativeEvent);
    onExpand === null || onExpand === void 0 ? void 0 : onExpand(nodeData);
  }, [nodeData, onExpand]);
  var handleSelect = useCallback(function (event) {
    if (disabled) {
      return;
    }

    if (event.target instanceof HTMLElement) {
      if (hasClass(event.target.parentNode, prefix('expand-icon-wrapper'))) {
        return;
      }
    }

    onSelect === null || onSelect === void 0 ? void 0 : onSelect(nodeData, event);
  }, [nodeData, disabled, prefix, onSelect]);
  var handleDragStart = useCallback(function (event) {
    var dragNode = document.getElementById('drag-node');

    if (dragNode) {
      event.dataTransfer.setDragImage(dragNode, 0, 0);
    }

    onDragStart === null || onDragStart === void 0 ? void 0 : onDragStart(nodeData, event);
  }, [nodeData, onDragStart]);
  var handleDragEnter = useCallback(function (event) {
    event.preventDefault();
    event.stopPropagation();
    onDragEnter === null || onDragEnter === void 0 ? void 0 : onDragEnter(nodeData, event);
  }, [nodeData, onDragEnter]);
  var handleDragOver = useCallback(function (event) {
    event.preventDefault();
    event.stopPropagation();
    onDragOver === null || onDragOver === void 0 ? void 0 : onDragOver(nodeData, event);
  }, [nodeData, onDragOver]);
  var handleDragLeave = useCallback(function (event) {
    event.stopPropagation();
    onDragLeave === null || onDragLeave === void 0 ? void 0 : onDragLeave(nodeData, event);
  }, [nodeData, onDragLeave]);
  var handleDragEnd = useCallback(function (event) {
    event.stopPropagation();
    onDragEnd === null || onDragEnd === void 0 ? void 0 : onDragEnd(nodeData, event);
  }, [nodeData, onDragEnd]);
  var handleDrop = useCallback(function (event) {
    event.preventDefault();
    event.stopPropagation();
    onDrop === null || onDrop === void 0 ? void 0 : onDrop(nodeData, event);
  }, [nodeData, onDrop]);

  var renderIcon = function renderIcon() {
    var classes = prefix('expand-icon', 'icon', {
      expanded: expand
    });
    var expandIcon = /*#__PURE__*/React.createElement(ArrowDown, {
      className: classes
    });

    if (loading) {
      expandIcon = /*#__PURE__*/React.createElement("div", {
        className: prefix('loading-icon')
      }, /*#__PURE__*/React.createElement(Spinner, {
        spin: true
      }));
    }

    if (nodeData !== undefined && typeof onRenderTreeIcon === 'function') {
      var customIcon = onRenderTreeIcon(nodeData);
      expandIcon = customIcon !== null ? /*#__PURE__*/React.createElement("div", {
        className: prefix('custom-icon')
      }, customIcon) : expandIcon;
    }

    return hasChildren ? /*#__PURE__*/React.createElement("div", {
      role: "button",
      tabIndex: -1,
      "data-ref": nodeData.refKey,
      className: prefix('expand-icon-wrapper'),
      onClick: handleExpand
    }, expandIcon) : null;
  };

  var renderLabel = function renderLabel() {
    var contentClasses = prefix('label-content', {
      dragging: dragging,
      'drag-over': dragOver,
      'drag-over-top': dragOverTop,
      'drag-over-bottom': dragOverBottom
    });
    return /*#__PURE__*/React.createElement("span", {
      className: prefix('label'),
      title: getTitle(),
      "data-layer": layer,
      "data-key": (nodeData === null || nodeData === void 0 ? void 0 : nodeData.refKey) || '',
      role: "button",
      tabIndex: -1,
      onClick: handleSelect
    }, /*#__PURE__*/React.createElement("span", {
      className: contentClasses
    }, onRenderTreeNode ? onRenderTreeNode(nodeData) : label));
  };

  var classes = merge(className, withClassPrefix({
    disabled: disabled,
    active: active,
    'text-muted': disabled,
    focus: focus
  })); // layer start from 1

  var padding = (layer - 1) * TREE_NODE_PADDING + TREE_NODE_ROOT_PADDING;

  var styles = _extends({}, style, (_extends2 = {}, _extends2[rtl ? 'paddingRight' : 'paddingLeft'] = padding, _extends2));

  return visible ? /*#__PURE__*/React.createElement(Component, _extends({
    role: "treeitem"
  }, rest, {
    "aria-expanded": expand,
    "aria-label": label,
    "aria-level": layer,
    "aria-disabled": disabled,
    "aria-selected": active,
    style: styles,
    className: classes,
    ref: ref,
    draggable: draggable,
    onDragStart: handleDragStart,
    onDragEnter: handleDragEnter,
    onDragOver: handleDragOver,
    onDragLeave: handleDragLeave,
    onDragEnd: handleDragEnd,
    onDrop: handleDrop
  }), renderIcon(), renderLabel()) : null;
});
TreeNode.displayName = 'TreePickerNode';
TreeNode.defaultProps = {
  visible: true,
  classPrefix: 'tree-node'
};
TreeNode.propTypes = {
  as: PropTypes.elementType,
  rtl: PropTypes.bool,
  focus: PropTypes.bool,
  layer: PropTypes.number,
  value: PropTypes.any,
  label: PropTypes.any,
  expand: PropTypes.bool,
  active: PropTypes.bool,
  loading: PropTypes.bool,
  visible: PropTypes.bool,
  nodeData: PropTypes.any,
  disabled: PropTypes.bool,
  draggable: PropTypes.bool,
  dragging: PropTypes.bool,
  dragOver: PropTypes.bool,
  dragOverTop: PropTypes.bool,
  dragOverBottom: PropTypes.bool,
  hasChildren: PropTypes.bool,
  className: PropTypes.string,
  classPrefix: PropTypes.string,
  style: PropTypes.object,
  onExpand: PropTypes.func,
  onSelect: PropTypes.func,
  onRenderTreeIcon: PropTypes.func,
  onRenderTreeNode: PropTypes.func,
  onDragStart: PropTypes.func,
  onDragEnter: PropTypes.func,
  onDragOver: PropTypes.func,
  onDragLeave: PropTypes.func,
  onDragEnd: PropTypes.func,
  onDrop: PropTypes.func
};
export default TreeNode;