import React, { useCallback, useState, useEffect, useMemo } from 'react';
import { DndProvider } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
import { DragNDropListItem } from './drag-and-drop-list-item';
import { jsx as _jsx } from "react/jsx-runtime";
/** DragNDropList components implements a row list, items of which can be drag-n-dropped
 * as reordering mechanism. You can also customize how each row look like (See examples below)
 * @midnight-gray-supported
 * @alpine-light-supported
 */
export function DragNDropList({
  data,
  onDataChanged,
  canDrag,
  canDrop,
  onDragEnd,
  ListItemContent,
  ListItemComponent,
  listItemClassName,
  keyGetter = dataItem => dataItem.id,
  shouldUseSeparateDragRef = false,
  backend,
  dndManager,
  dragItemType,
  additionalListItemProps,
  dndContainerRef
}) {
  // this is needed as a workaround for WebKit bug with drag n drop and hovering:
  // https://bugs.webkit.org/show_bug.cgi?id=134555
  const [isAnyItemDragging, setIsAnyItemDragging] = useState(false);
  const handleItemMove = useCallback((dragIndex, hoverIndex) => {
    const nextData = [...data];
    const draggedItem = nextData[dragIndex];
    nextData.splice(dragIndex, 1);
    nextData.splice(hoverIndex, 0, draggedItem);
    onDataChanged(nextData, dragIndex, hoverIndex);
  }, [data, onDataChanged]);
  const dndProviderProps = {
    backend: backend || HTML5Backend
  };

  // Provide manager only if it's not undefined
  if (dndManager) {
    dndProviderProps.manager = dndManager;
  }
  function getIndexById(id) {
    return data.findIndex(item => keyGetter(item) === id);
  }

  // code below is to fix react-dnd bug: https://github.com/react-dnd/react-dnd/issues/3304
  // this is needed to invoke component re-render once ref is initialized
  const [dndArea, setDnDArea] = useState(null);
  // this actually sets ref's value to the state
  useEffect(() => {
    if (dndContainerRef) {
      setDnDArea(dndContainerRef?.current);
    }
  }, [dndContainerRef]);
  // this will prevent react-dnd from breaking native dnd interactions
  const html5Options = useMemo(() => ({
    rootElement: dndArea
  }), [dndArea]);
  const shouldRender = dndContainerRef === undefined ? true : !!dndArea;
  return shouldRender ? /*#__PURE__*/_jsx(DndProvider, {
    ...dndProviderProps,
    options: html5Options,
    children: data.map((dataItem, index) => {
      const id = keyGetter(dataItem);
      return /*#__PURE__*/_jsx(DragNDropListItem, {
        id: id,
        index: index,
        listItem: dataItem,
        onItemMove: handleItemMove,
        canDrag: canDrag,
        canDrop: canDrop,
        isActive: dataItem.isActive,
        isError: dataItem.isError,
        onDragEnd: onDragEnd,
        getIndexById: getIndexById,
        ListItemComponent: ListItemComponent,
        ListItemContent: ListItemContent,
        isAnyItemDragging: isAnyItemDragging,
        setIsAnyItemDragging: setIsAnyItemDragging,
        listItemClassName: listItemClassName,
        shouldUseSeparateDragRef: shouldUseSeparateDragRef,
        dragItemType: dragItemType,
        additionalListItemProps: additionalListItemProps
      }, id);
    })
  }) : null;
}