import _toConsumableArray from '@babel/runtime/helpers/toConsumableArray';
import _defineProperty from '@babel/runtime/helpers/defineProperty';
import isEqual from '../../../node_modules/lodash-es/isEqual.js';
import 'core-js/modules/es.symbol.js';
import 'core-js/modules/es.array.concat.js';
import 'core-js/modules/es.array.filter.js';
import 'core-js/modules/es.array.includes.js';
import 'core-js/modules/es.array.map.js';
import 'core-js/modules/es.array.slice.js';
import 'core-js/modules/es.object.get-own-property-descriptor.js';
import 'core-js/modules/es.object.get-own-property-descriptors.js';
import 'core-js/modules/es.object.keys.js';
import 'core-js/modules/es.object.to-string.js';
import 'core-js/modules/es.string.includes.js';
import 'core-js/modules/web.dom-collections.for-each.js';
import React__default, { useMemo } from 'react';
import { SkeletonText, Checkbox } from '@carbon/react';
import classnames from 'classnames';
import PropTypes from 'prop-types';
import { settings } from '../../../constants/Settings.js';
import ListItem from '../ListItem/ListItem.js';
import EmptyState from '../../EmptyState/EmptyState.js';
import Button from '../../Button/Button.js';
import { EditingStyle, editingStyleIsMultiple } from '../../../utils/DragAndDropUtils.js';
import { ListItemPropTypes } from '../ListPropTypes.js';
import { HtmlElementRefProp } from '../../../constants/SharedPropTypes.js';
import { ITEM_LEVEL_OFFSET, ITEM_COLUMN_GAP } from '../VirtualListContent/listConstants.js';
import { usePrevious } from '../../../hooks/usePrevious.js';

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; }
var iotPrefix = settings.iotPrefix;
var propTypes = {
  /** content shown if list is empty */
  emptyState: PropTypes.oneOfType([PropTypes.node, PropTypes.string]),
  /** content shown if list is empty on search */
  emptySearchState: PropTypes.oneOfType([PropTypes.node, PropTypes.string]),
  /** i18n strings */
  i18n: PropTypes.shape({
    searchPlaceHolderText: PropTypes.string,
    expand: PropTypes.string,
    close: PropTypes.string,
    loadMore: PropTypes.string
  }),
  /** data source of list items */
  items: PropTypes.arrayOf(PropTypes.shape(ListItemPropTypes)),
  /** if true shows empty search state, instead of empty state, when there are no search results */
  isFiltering: PropTypes.bool,
  /** use full height in list */
  isFullHeight: PropTypes.bool,
  /** use large/fat row in list */
  isLargeRow: PropTypes.bool,
  /** optional skeleton to be rendered while loading data */
  isLoading: PropTypes.bool,
  /** the ids of locked items that cannot be reordered */
  lockedIds: PropTypes.arrayOf(PropTypes.string),
  /** true if the list should have multiple selectable rows using checkboxes */
  isCheckboxMultiSelect: PropTypes.bool,
  testId: PropTypes.string,
  /** Multiple currently selected items */
  selectedIds: PropTypes.arrayOf(PropTypes.string),
  /** ids of row expanded */
  expandedIds: PropTypes.arrayOf(PropTypes.string),
  /** callback function of select */
  handleSelect: PropTypes.func,
  /** callback used to limit which items that should get drop targets rendered.
   * receives the id of the item that is being dragged and returns a list of ids. */
  getAllowedDropIds: PropTypes.func,
  /** call back function of expansion */
  toggleExpansion: PropTypes.func,
  /** callback function for reorder */
  onItemMoved: PropTypes.func,
  /** callback function when reorder will occur - can cancel the move by returning false */
  itemWillMove: PropTypes.func,
  /** callback function for when load more row is clicked  (rowId) => {} */
  handleLoadMore: PropTypes.func,
  /** ids of selectable rows with indeterminate selection state */
  indeterminateIds: PropTypes.arrayOf(PropTypes.string),
  /** RowIds for rows currently loading more child rows */
  loadingMoreIds: PropTypes.arrayOf(PropTypes.string),
  /** list editing style */
  editingStyle: PropTypes.oneOf([EditingStyle.Single, EditingStyle.Multiple, EditingStyle.SingleNesting, EditingStyle.MultipleNesting]),
  /** icon can be left or right side of list row primary value */
  iconPosition: PropTypes.oneOf(['left', 'right']),
  selectedItemRef: HtmlElementRefProp,
  /** called after the row has expanded or collapsed and is passed the array of expanded ids */
  onExpandedChange: PropTypes.func,
  /** enables horizontal scrollbar to appear if content is wider then container */
  enableHorizontalScrollbar: PropTypes.bool
};
var ConditionalWrapper = function ConditionalWrapper(_ref) {
  var condition = _ref.condition,
    wrapper = _ref.wrapper,
    children = _ref.children;
  return condition ? wrapper(children) : children;
};
var defaultProps = {
  editingStyle: null,
  emptyState: 'No list items to show',
  emptySearchState: 'No results found',
  expandedIds: [],
  getAllowedDropIds: null,
  handleLoadMore: function handleLoadMore() {},
  handleSelect: function handleSelect() {},
  i18n: {
    searchPlaceHolderText: 'Enter a value',
    expand: 'Expand',
    close: 'Close',
    loadMore: 'View more...'
  },
  iconPosition: 'left',
  isFiltering: false,
  isFullHeight: false,
  isLargeRow: false,
  isLoading: false,
  isCheckboxMultiSelect: false,
  items: [],
  itemWillMove: function itemWillMove() {
    return true;
  },
  indeterminateIds: [],
  loadingMoreIds: [],
  lockedIds: [],
  onItemMoved: function onItemMoved() {},
  selectedIds: [],
  selectedItemRef: /*#__PURE__*/React__default.createRef(),
  testId: 'list',
  toggleExpansion: function toggleExpansion() {},
  onExpandedChange: null,
  enableHorizontalScrollbar: false
};
var getAdjustedNestingLevel = function getAdjustedNestingLevel(items, currentLevel) {
  return items.some(function (item) {
    return (item === null || item === void 0 ? void 0 : item.children) && item.children.length > 0;
  }) ? currentLevel + 1 : currentLevel;
};
var ListContent = function ListContent(_ref2) {
  var isLoading = _ref2.isLoading,
    isCheckboxMultiSelect = _ref2.isCheckboxMultiSelect,
    isFiltering = _ref2.isFiltering,
    isFullHeight = _ref2.isFullHeight,
    items = _ref2.items,
    testId = _ref2.testId,
    emptyState = _ref2.emptyState,
    emptySearchState = _ref2.emptySearchState,
    selectedIds = _ref2.selectedIds,
    expandedIds = _ref2.expandedIds,
    indeterminateIds = _ref2.indeterminateIds,
    loadingMoreIds = _ref2.loadingMoreIds,
    handleSelect = _ref2.handleSelect,
    editingStyle = _ref2.editingStyle,
    getAllowedDropIds = _ref2.getAllowedDropIds,
    iconPosition = _ref2.iconPosition,
    toggleExpansion = _ref2.toggleExpansion,
    onItemMoved = _ref2.onItemMoved,
    itemWillMove = _ref2.itemWillMove,
    isLargeRow = _ref2.isLargeRow,
    lockedIds = _ref2.lockedIds,
    handleLoadMore = _ref2.handleLoadMore,
    i18n = _ref2.i18n,
    selectedItemRef = _ref2.selectedItemRef,
    onExpandedChange = _ref2.onExpandedChange,
    enableHorizontalScrollbar = _ref2.enableHorizontalScrollbar;
  var mergedI18n = useMemo(function () {
    return _objectSpread(_objectSpread({}, defaultProps.i18n), i18n);
  }, [i18n]);
  var renderLoadMore = function renderLoadMore(item, isLoadingMore, level) {
    var indentation = "".concat(level * ITEM_LEVEL_OFFSET - ITEM_COLUMN_GAP, "px");
    return isLoadingMore ? /*#__PURE__*/React__default.createElement("div", {
      key: "".concat(item.id, "-list-item-load-more"),
      className: "".concat(iotPrefix, "--list-item")
    }, /*#__PURE__*/React__default.createElement("div", {
      style: {
        width: indentation
      }
    }), /*#__PURE__*/React__default.createElement(SkeletonText, {
      className: "".concat(iotPrefix, "--list--load-more-skeleton"),
      width: "30%",
      "data-testid": "".concat(testId, "-loading-more")
    })) : /*#__PURE__*/React__default.createElement(Button, {
      key: "".concat(item.id, "-list-item-load-more"),
      className: "".concat(iotPrefix, "--list-item ").concat(iotPrefix, "--load-more-row"),
      onClick: function onClick() {
        return handleLoadMore(item.id);
      },
      "data-testid": "".concat(testId, "-").concat(item.id, "-load-more"),
      kind: "ghost"
    }, /*#__PURE__*/React__default.createElement("div", {
      style: {
        width: indentation
      }
    }), /*#__PURE__*/React__default.createElement("div", {
      className: "".concat(iotPrefix, "--load-more-row--content")
    }, mergedI18n.loadMore));
  };
  var renderItemAndChildren = function renderItemAndChildren(item, index, parentId, level) {
    var hasChildren = (item === null || item === void 0 ? void 0 : item.children) && item.children.length > 0;
    var isSelected = selectedIds.some(function (id) {
      return item.id === id;
    });
    var isExpanded = expandedIds.filter(function (rowId) {
      return rowId === item.id;
    }).length > 0;
    var isLoadingMore = loadingMoreIds.includes(item.id);
    var isLocked = lockedIds.includes(item.id);
    var isIndeterminate = indeterminateIds.includes(item.id);
    var _item$content = item.content,
      value = _item$content.value,
      title = _item$content.title,
      secondaryValue = _item$content.secondaryValue,
      icon = _item$content.icon,
      rowActions = _item$content.rowActions,
      tags = _item$content.tags,
      isSelectable = item.isSelectable,
      isCategory = item.isCategory,
      disabled = item.disabled;
    return [/*#__PURE__*/React__default.createElement("div", {
      key: "".concat(item.id, "-list-item-parent-").concat(level, "-").concat(value)
      // data-floating-menu-container is a work around for this carbon issue: https://github.com/carbon-design-system/carbon/issues/4755
      ,
      "data-floating-menu-container": true,
      className: "".concat(iotPrefix, "--list-item-parent")
    }, /*#__PURE__*/React__default.createElement(ListItem, {
      id: item.id,
      index: index,
      key: "".concat(item.id, "-list-item-").concat(level, "-").concat(value),
      nestingLevel: item !== null && item !== void 0 && item.children && item.children.length > 0 ? level - 1 : level,
      title: title,
      value: value,
      icon: editingStyleIsMultiple(editingStyle) || isSelectable && isCheckboxMultiSelect ? /*#__PURE__*/React__default.createElement(Checkbox, {
        id: "".concat(item.id, "-checkbox"),
        name: item.value,
        "data-testid": "".concat(item.id, "-checkbox"),
        labelText: "",
        onChange: function onChange() {
          return handleSelect(item.id, parentId);
        },
        onClick: function onClick(event) {
          // This is needed as a workaround for a carbon checkbox bug
          // https://github.com/carbon-design-system/carbon/issues/10122#issuecomment-984692702
          event.stopPropagation();
        },
        checked: isSelected,
        disabled: disabled || isLocked,
        indeterminate: isIndeterminate
      }) : icon,
      disabled: disabled,
      iconPosition: iconPosition,
      editingStyle: isLocked ? null : editingStyle,
      secondaryValue: secondaryValue,
      rowActions: rowActions,
      onSelect: function onSelect() {
        return handleSelect(item.id, parentId);
      },
      onExpand: toggleExpansion,
      onItemMoved: onItemMoved,
      itemWillMove: itemWillMove,
      getAllowedDropIds: getAllowedDropIds,
      selected: isSelected,
      expanded: isExpanded,
      isExpandable: hasChildren,
      isLargeRow: isLargeRow,
      isLocked: isLocked,
      isCategory: isCategory,
      isSelectable: editingStyle === null && isSelectable,
      i18n: mergedI18n,
      selectedItemRef: isSelected ? selectedItemRef : null,
      tags: tags,
      preventRowFocus: isCheckboxMultiSelect
    }))].concat(_toConsumableArray(hasChildren && isExpanded ? item.children.map(function (child, nestedIndex) {
      return renderItemAndChildren(child, nestedIndex, item.id, level + 1);
    }).concat(item.hasLoadMore ? [renderLoadMore(item, isLoadingMore, level + 1)] : []) : []), _toConsumableArray(!hasChildren && item.hasLoadMore ? [renderLoadMore(item, isLoadingMore, level)] : []));
  };
  var previousExpandedIds = usePrevious(expandedIds, expandedIds);
  var selectionChanged = !isEqual(expandedIds, previousExpandedIds);
  // get the lastId of the diff between previous and current, this handles closes
  var previousLastId = selectionChanged && previousExpandedIds.filter(function (id) {
    return !expandedIds.includes(id);
  }).slice(-1)[0];
  // get the lastId of the diff between current and previous, this handles opens
  var lastId = selectionChanged && expandedIds.filter(function (id) {
    return !previousExpandedIds.includes(id);
  }).slice(-1)[0];
  var notifyOnLastExpansionChange = function notifyOnLastExpansionChange(itemId) {
    var isLastItem = lastId === itemId || previousLastId === itemId;
    if (isLastItem && expandedIds.includes(itemId) !== previousExpandedIds.includes(itemId)) {
      // the setTimeout within the request animation frame helps to ensure the event is fired
      // immediately after a repaint. See:
      // https://firefox-source-docs.mozilla.org/performance/bestpractices.html#how-do-i-avoid-triggering-uninterruptible-reflow
      window.requestAnimationFrame(function () {
        setTimeout(function () {
          onExpandedChange(expandedIds);
        });
      }, 0);
    }
  };
  var listItems = items.map(function (item, index) {
    notifyOnLastExpansionChange(item.id);
    return renderItemAndChildren(item, index, null, getAdjustedNestingLevel(items, 0));
  });
  var renderEmptyContent = function renderEmptyContent() {
    var emptyContent = isFiltering ? emptySearchState : emptyState;
    return typeof emptyContent === 'string' ? /*#__PURE__*/React__default.createElement("div", {
      className: classnames("".concat(iotPrefix, "--list--empty-state"), _defineProperty({}, "".concat(iotPrefix, "--list--empty-state__full-height"), isFullHeight))
    }, /*#__PURE__*/React__default.createElement(EmptyState, {
      icon: isFiltering ? 'no-result' : 'empty',
      title: emptyContent,
      body: ""
    })) : emptyContent;
  };
  return /*#__PURE__*/React__default.createElement("div", {
    className: classnames(_defineProperty(_defineProperty({}, "".concat(iotPrefix, "--list--content__full-height"), isFullHeight), "".concat(iotPrefix, "--list--content--w-horizontal-scrollbar"), enableHorizontalScrollbar), "".concat(iotPrefix, "--list--content"))
  }, /*#__PURE__*/React__default.createElement(ConditionalWrapper, {
    condition: isFullHeight && enableHorizontalScrollbar,
    wrapper: function wrapper(children) {
      return /*#__PURE__*/React__default.createElement("div", {
        className: "".concat(iotPrefix, "--list--content__full-height__support")
      }, children);
    }
  }, /*#__PURE__*/React__default.createElement(ConditionalWrapper, {
    condition: enableHorizontalScrollbar,
    wrapper: function wrapper(children) {
      return /*#__PURE__*/React__default.createElement("div", {
        className: "".concat(iotPrefix, "--list--content__scrollbar__support")
      }, children);
    }
  }, !isLoading ? /*#__PURE__*/React__default.createElement(React__default.Fragment, null, listItems.length ? listItems : renderEmptyContent()) : /*#__PURE__*/React__default.createElement(SkeletonText, {
    className: "".concat(iotPrefix, "--list--skeleton"),
    width: "90%",
    "data-testid": "".concat(testId, "-loading")
  }))));
};
ListContent.propTypes = propTypes;
ListContent.defaultProps = defaultProps;
ListContent.__docgenInfo = {
  "description": "",
  "methods": [],
  "displayName": "ListContent",
  "props": {
    "editingStyle": {
      "defaultValue": {
        "value": "null",
        "computed": false
      },
      "description": "list editing style",
      "type": {
        "name": "enum",
        "value": [{
          "value": "EditingStyle.Single",
          "computed": true
        }, {
          "value": "EditingStyle.Multiple",
          "computed": true
        }, {
          "value": "EditingStyle.SingleNesting",
          "computed": true
        }, {
          "value": "EditingStyle.MultipleNesting",
          "computed": true
        }]
      },
      "required": false
    },
    "emptyState": {
      "defaultValue": {
        "value": "'No list items to show'",
        "computed": false
      },
      "description": "content shown if list is empty",
      "type": {
        "name": "union",
        "value": [{
          "name": "node"
        }, {
          "name": "string"
        }]
      },
      "required": false
    },
    "emptySearchState": {
      "defaultValue": {
        "value": "'No results found'",
        "computed": false
      },
      "description": "content shown if list is empty on search",
      "type": {
        "name": "union",
        "value": [{
          "name": "node"
        }, {
          "name": "string"
        }]
      },
      "required": false
    },
    "expandedIds": {
      "defaultValue": {
        "value": "[]",
        "computed": false
      },
      "description": "ids of row expanded",
      "type": {
        "name": "arrayOf",
        "value": {
          "name": "string"
        }
      },
      "required": false
    },
    "getAllowedDropIds": {
      "defaultValue": {
        "value": "null",
        "computed": false
      },
      "description": "callback used to limit which items that should get drop targets rendered.\nreceives the id of the item that is being dragged and returns a list of ids.",
      "type": {
        "name": "func"
      },
      "required": false
    },
    "handleLoadMore": {
      "defaultValue": {
        "value": "() => {}",
        "computed": false
      },
      "description": "callback function for when load more row is clicked  (rowId) => {}",
      "type": {
        "name": "func"
      },
      "required": false
    },
    "handleSelect": {
      "defaultValue": {
        "value": "() => {}",
        "computed": false
      },
      "description": "callback function of select",
      "type": {
        "name": "func"
      },
      "required": false
    },
    "i18n": {
      "defaultValue": {
        "value": "{\n  searchPlaceHolderText: 'Enter a value',\n  expand: 'Expand',\n  close: 'Close',\n  loadMore: 'View more...',\n}",
        "computed": false
      },
      "description": "i18n strings",
      "type": {
        "name": "shape",
        "value": {
          "searchPlaceHolderText": {
            "name": "string",
            "required": false
          },
          "expand": {
            "name": "string",
            "required": false
          },
          "close": {
            "name": "string",
            "required": false
          },
          "loadMore": {
            "name": "string",
            "required": false
          }
        }
      },
      "required": false
    },
    "iconPosition": {
      "defaultValue": {
        "value": "'left'",
        "computed": false
      },
      "description": "icon can be left or right side of list row primary value",
      "type": {
        "name": "enum",
        "value": [{
          "value": "'left'",
          "computed": false
        }, {
          "value": "'right'",
          "computed": false
        }]
      },
      "required": false
    },
    "isFiltering": {
      "defaultValue": {
        "value": "false",
        "computed": false
      },
      "description": "if true shows empty search state, instead of empty state, when there are no search results",
      "type": {
        "name": "bool"
      },
      "required": false
    },
    "isFullHeight": {
      "defaultValue": {
        "value": "false",
        "computed": false
      },
      "description": "use full height in list",
      "type": {
        "name": "bool"
      },
      "required": false
    },
    "isLargeRow": {
      "defaultValue": {
        "value": "false",
        "computed": false
      },
      "description": "use large/fat row in list",
      "type": {
        "name": "bool"
      },
      "required": false
    },
    "isLoading": {
      "defaultValue": {
        "value": "false",
        "computed": false
      },
      "description": "optional skeleton to be rendered while loading data",
      "type": {
        "name": "bool"
      },
      "required": false
    },
    "isCheckboxMultiSelect": {
      "defaultValue": {
        "value": "false",
        "computed": false
      },
      "description": "true if the list should have multiple selectable rows using checkboxes",
      "type": {
        "name": "bool"
      },
      "required": false
    },
    "items": {
      "defaultValue": {
        "value": "[]",
        "computed": false
      },
      "description": "data source of list items",
      "type": {
        "name": "arrayOf",
        "value": {
          "name": "shape",
          "value": "import { ListItemPropTypes } from '../ListPropTypes';",
          "computed": true
        }
      },
      "required": false
    },
    "itemWillMove": {
      "defaultValue": {
        "value": "() => {\n  return true;\n}",
        "computed": false
      },
      "description": "callback function when reorder will occur - can cancel the move by returning false",
      "type": {
        "name": "func"
      },
      "required": false
    },
    "indeterminateIds": {
      "defaultValue": {
        "value": "[]",
        "computed": false
      },
      "description": "ids of selectable rows with indeterminate selection state",
      "type": {
        "name": "arrayOf",
        "value": {
          "name": "string"
        }
      },
      "required": false
    },
    "loadingMoreIds": {
      "defaultValue": {
        "value": "[]",
        "computed": false
      },
      "description": "RowIds for rows currently loading more child rows",
      "type": {
        "name": "arrayOf",
        "value": {
          "name": "string"
        }
      },
      "required": false
    },
    "lockedIds": {
      "defaultValue": {
        "value": "[]",
        "computed": false
      },
      "description": "the ids of locked items that cannot be reordered",
      "type": {
        "name": "arrayOf",
        "value": {
          "name": "string"
        }
      },
      "required": false
    },
    "onItemMoved": {
      "defaultValue": {
        "value": "() => {}",
        "computed": false
      },
      "description": "callback function for reorder",
      "type": {
        "name": "func"
      },
      "required": false
    },
    "selectedIds": {
      "defaultValue": {
        "value": "[]",
        "computed": false
      },
      "description": "Multiple currently selected items",
      "type": {
        "name": "arrayOf",
        "value": {
          "name": "string"
        }
      },
      "required": false
    },
    "selectedItemRef": {
      "defaultValue": {
        "value": "React.createRef()",
        "computed": true
      },
      "description": "",
      "type": {
        "name": "custom",
        "raw": "HtmlElementRefProp"
      },
      "required": false
    },
    "testId": {
      "defaultValue": {
        "value": "'list'",
        "computed": false
      },
      "description": "",
      "type": {
        "name": "string"
      },
      "required": false
    },
    "toggleExpansion": {
      "defaultValue": {
        "value": "() => {}",
        "computed": false
      },
      "description": "call back function of expansion",
      "type": {
        "name": "func"
      },
      "required": false
    },
    "onExpandedChange": {
      "defaultValue": {
        "value": "null",
        "computed": false
      },
      "description": "called after the row has expanded or collapsed and is passed the array of expanded ids",
      "type": {
        "name": "func"
      },
      "required": false
    },
    "enableHorizontalScrollbar": {
      "defaultValue": {
        "value": "false",
        "computed": false
      },
      "description": "enables horizontal scrollbar to appear if content is wider then container",
      "type": {
        "name": "bool"
      },
      "required": false
    }
  }
};
var DefaultListContent = ListContent;

export { DefaultListContent as default };
