import _extends from "@babel/runtime/helpers/esm/extends";
import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
import React, { useCallback } from 'react';
import PropTypes from 'prop-types';
import isNil from 'lodash/isNil';
import SpinnerIcon from '@rsuite/icons/legacy/Spinner';
import AngleLeftIcon from '@rsuite/icons/legacy/AngleLeft';
import AngleRightIcon from '@rsuite/icons/legacy/AngleRight';
import { useClassNames, shallowEqual, useCustom } from '../utils';
import { DropdownMenuCheckItem } from '../Picker';
import { isSomeParentChecked, isSomeChildChecked } from './utils';
var defaultProps = {
  as: 'div',
  disabledItemValues: [],
  uncheckableItemValues: [],
  cascadeData: [],
  cascadePaths: [],
  menuWidth: 156,
  menuHeight: 200,
  childrenKey: 'children',
  valueKey: 'value',
  labelKey: 'label'
};
var DropdownMenu = /*#__PURE__*/React.forwardRef(function (props, ref) {
  var Component = props.as,
      classPrefix = props.classPrefix,
      className = props.className,
      cascade = props.cascade,
      cascadeData = props.cascadeData,
      cascadePaths = props.cascadePaths,
      childrenKey = props.childrenKey,
      disabledItemValues = props.disabledItemValues,
      menuWidth = props.menuWidth,
      menuHeight = props.menuHeight,
      uncheckableItemValues = props.uncheckableItemValues,
      value = props.value,
      valueKey = props.valueKey,
      labelKey = props.labelKey,
      loadingText = props.loadingText,
      renderMenuItem = props.renderMenuItem,
      renderMenu = props.renderMenu,
      _onCheck = props.onCheck,
      onSelect = props.onSelect,
      rest = _objectWithoutPropertiesLoose(props, ["as", "classPrefix", "className", "cascade", "cascadeData", "cascadePaths", "childrenKey", "disabledItemValues", "menuWidth", "menuHeight", "uncheckableItemValues", "value", "valueKey", "labelKey", "loadingText", "renderMenuItem", "renderMenu", "onCheck", "onSelect"]);

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

  var classes = merge(className, prefix('items'));
  var rtl = useCustom('DropdownMenu');
  var getCascadeItems = useCallback(function (items, layer, node, isLeafNode) {
    var data = [];
    var paths = [];

    for (var i = 0; i < cascadeData.length && i < layer; i += 1) {
      data.push(cascadeData[i]);

      if (i < layer - 1 && cascadePaths) {
        paths.push(cascadePaths[i]);
      }
    }

    paths.push(node);

    if (!isLeafNode) {
      data.push(items);
    }

    return {
      cascadeData: data,
      cascadePaths: paths
    };
  }, [cascadeData, cascadePaths]);
  var handleSelect = useCallback(function (layer, node, event) {
    var children = node[childrenKey];
    var isLeafNode = isNil(children);
    var items = (children || []).map(function (item) {
      return _extends({}, item, {
        parent: node
      });
    });

    var _getCascadeItems = getCascadeItems(items, layer + 1, node, isLeafNode),
        cascadeData = _getCascadeItems.cascadeData,
        cascadePaths = _getCascadeItems.cascadePaths;

    onSelect === null || onSelect === void 0 ? void 0 : onSelect(node, cascadeData, cascadePaths, event);
  }, [childrenKey, getCascadeItems, onSelect]);

  var renderCascadeNode = function renderCascadeNode(node, index, layer, focus, uncheckable) {
    var children = node[childrenKey];
    var nodeValue = node[valueKey];
    var nodeLabel = node[labelKey];
    var disabled = disabledItemValues.some(function (disabledValue) {
      return shallowEqual(disabledValue, nodeValue);
    }); // Use `value` in keys when If `value` is string or number

    var onlyKey = typeof value === 'number' || typeof value === 'string' ? value : index;
    var Icon = rtl ? AngleRightIcon : AngleLeftIcon;
    var active = value.some(function (v) {
      return v === nodeValue;
    });

    if (cascade) {
      active = active || isSomeParentChecked(node, value, {
        valueKey: valueKey
      });
    }

    return /*#__PURE__*/React.createElement(DropdownMenuCheckItem, {
      as: "li",
      key: layer + "-" + onlyKey,
      disabled: disabled,
      active: active,
      focus: focus // Pass the node as a value to Item, and use it in event callbacks.
      ,
      value: nodeValue,
      className: children ? prefix('has-children') : undefined,
      indeterminate: cascade && !active && isSomeChildChecked(node, value, {
        valueKey: valueKey,
        childrenKey: childrenKey
      }),
      onSelectItem: function onSelectItem(_value, event) {
        return handleSelect(layer, node, event);
      },
      onCheck: function onCheck(_value, event, checked) {
        return _onCheck === null || _onCheck === void 0 ? void 0 : _onCheck(node, event, checked);
      },
      checkable: !uncheckable
    }, renderMenuItem ? renderMenuItem(nodeLabel, node) : nodeLabel, children ? /*#__PURE__*/React.createElement(Icon, {
      className: prefix('caret')
    }) : null);
  };

  var renderCascade = function renderCascade() {
    var styles = {
      width: cascadeData.length * menuWidth
    };
    var columnStyles = {
      height: menuHeight,
      width: menuWidth
    };
    var cascadeNodes = cascadeData.map(function (children, layer) {
      var uncheckableCount = 0;
      var onlyKey = layer + "_" + children.length;
      var menu = /*#__PURE__*/React.createElement("ul", {
        role: "listbox"
      }, children.map(function (item, index) {
        var uncheckable = uncheckableItemValues.some(function (uncheckableValue) {
          return shallowEqual(uncheckableValue, item[valueKey]);
        });

        if (uncheckable) {
          uncheckableCount++;
        }

        return renderCascadeNode(item, index, layer, cascadePaths[layer] && shallowEqual(cascadePaths[layer][valueKey], item[valueKey]), uncheckable);
      }));
      var parentNode = cascadePaths[layer - 1];
      var columnClasses = prefix('column', {
        'column-uncheckable': uncheckableCount === children.length
      });

      var renderMenuElement = function renderMenuElement() {
        if (renderMenu) {
          return renderMenu(children, menu, parentNode);
        }

        return (parentNode === null || parentNode === void 0 ? void 0 : parentNode.loading) ? /*#__PURE__*/React.createElement("div", {
          className: prefix('column-loading')
        }, /*#__PURE__*/React.createElement(SpinnerIcon, {
          spin: true
        }), " ", /*#__PURE__*/React.createElement("span", null, loadingText)) : menu;
      };

      var node = /*#__PURE__*/React.createElement("div", {
        key: onlyKey,
        className: columnClasses,
        "data-layer": layer,
        style: columnStyles
      }, renderMenuElement());
      return node;
    });
    return /*#__PURE__*/React.createElement("div", {
      style: styles
    }, cascadeNodes);
  };

  return /*#__PURE__*/React.createElement(Component, _extends({}, rest, {
    ref: ref,
    className: classes
  }), renderCascade());
});
DropdownMenu.displayName = 'DropdownMenu';
DropdownMenu.defaultProps = defaultProps;
DropdownMenu.propTypes = {
  classPrefix: PropTypes.string,
  data: PropTypes.array,
  disabledItemValues: PropTypes.array,
  value: PropTypes.array,
  childrenKey: PropTypes.string,
  valueKey: PropTypes.string,
  labelKey: PropTypes.string,
  menuWidth: PropTypes.number,
  menuHeight: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
  className: PropTypes.string,
  cascade: PropTypes.bool,
  cascadeData: PropTypes.array,
  cascadePaths: PropTypes.array,
  uncheckableItemValues: PropTypes.array,
  renderMenuItem: PropTypes.func,
  renderMenu: PropTypes.func,
  onSelect: PropTypes.func,
  onCheck: PropTypes.func
};
export default DropdownMenu;