import React, { useState, useRef, useEffect } from 'react';
import classNames from 'classnames';
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
/** A Drag-And-Drop wrapper creates a drag-and-drop area around children and passes dataTransfer payload to provided dropAction */
export function DragNDropWrapper({
  onDropAction,
  onDragOverAction,
  children,
  isDisabled = false,
  isDropAllowed = () => true,
  containerClassName = 'drag-and-drop-wrapper',
  onDragClassName = 'is-dragging',
  onDropNotAllowedClassName = 'isDropNotAllowed',
  testId = 'drag-n-drop-zone'
}) {
  const [isDragging, setIsDraggingState] = useState(false);
  const [isDropNotAllowed, setIsDropNotAllowed] = useState(false);
  const enterLeaveCounter = useRef(0);
  const updateCounter = value => {
    enterLeaveCounter.current = enterLeaveCounter.current + value;
  };
  const onDragEnterAction = () => onDragOverAction && onDragOverAction(true);
  const onDragLeaveAction = () => onDragOverAction && onDragOverAction(false);
  const endDrag = () => {
    onDragLeaveAction();
    setIsDraggingState(false);
    setIsDropNotAllowed(false);
  };
  const onDragOver = e => {
    e.preventDefault();
    const {
      dataTransfer
    } = e;
    if (!isDropAllowed(dataTransfer)) {
      e.dataTransfer.dropEffect = 'none';
      if (!isDropNotAllowed) {
        setIsDropNotAllowed(true);
      }
    }
  };
  const onDragEnter = e => {
    e.preventDefault();
    updateCounter(1);
    if (!isDragging) {
      onDragEnterAction();
      setIsDraggingState(true);
    }
  };
  const onDragLeave = e => {
    e.preventDefault();
    updateCounter(-1);
    if (!enterLeaveCounter.current && isDragging) {
      endDrag();
    }
  };
  const onDrop = e => {
    e.preventDefault();
    enterLeaveCounter.current = 0;
    endDrag();
    const {
      dataTransfer
    } = e;
    if (!isDropAllowed(dataTransfer)) {
      return;
    }
    onDropAction(dataTransfer);
  };
  const protectedDragNDrop = e => {
    e.preventDefault();
  };
  useEffect(() => {
    window.addEventListener('drop', protectedDragNDrop);
    window.addEventListener('dragover', protectedDragNDrop);
    return () => {
      window.removeEventListener('drop', protectedDragNDrop);
      window.removeEventListener('dragover', protectedDragNDrop);
    };
  });
  if (isDisabled) {
    return /*#__PURE__*/_jsx(_Fragment, {
      children: children
    });
  }
  return /*#__PURE__*/_jsx("div", {
    className: classNames({
      [containerClassName]: containerClassName,
      [onDragClassName]: isDragging,
      [onDropNotAllowedClassName]: isDropNotAllowed
    }),
    onDragOver: onDragOver,
    onDrop: onDrop,
    onDragLeave: onDragLeave,
    onDragEnter: onDragEnter,
    "test-id": testId,
    "aria-dropeffect": "move",
    children: children
  });
}