/** @license MIT | @cube-dev/ui-kit v0.135.1 | Cube Dev Team */
import { useEvent } from "../../_internal/hooks/use-event.js";
import { useCallback, useEffect, useMemo, useRef } from "react";
import { ListDropTargetDelegate, ListKeyboardDelegate, mergeProps, useDraggableCollection, useDroppableCollection } from "react-aria";
import { useDraggableCollectionState, useDroppableCollectionState } from "react-stately";

//#region src/components/shared/DraggableCollection.tsx
const getAllowedDropOperations = () => ["move"];
/**
* Creates a no-op mock of DraggableCollectionState.
* Used to satisfy useDraggableItem when drag is disabled (Rules of Hooks).
*/
function createMockDragState(collection, selectionManager) {
	return {
		collection,
		selectionManager,
		isDragging: () => false,
		getKeysForDrag: () => /* @__PURE__ */ new Set(),
		draggedKey: null,
		draggingKeys: /* @__PURE__ */ new Set(),
		getAllowedDropOperations: () => [],
		preview: null,
		isDisabled: false,
		startDrag: () => {},
		endDrag: () => {}
	};
}
/**
* Generic wrapper that enables drag-and-drop reordering for a collection.
*
* Used by both DraggableTabList (horizontal) and DraggableListBox (vertical).
* Encapsulates all drag/drop hook calls so they are only invoked when
* reordering is actually enabled.
*/
function DraggableCollection({ state, listRef, orderedKeys, orientation, onReorder, children }) {
	const handleReorder = useEvent((e) => {
		if (!onReorder) return;
		const { target, keys: movableKeys } = e;
		const { dropPosition, key: targetKey } = target;
		const movableKey = [...movableKeys][0];
		const movableIndex = orderedKeys.indexOf(movableKey);
		const targetIndex = orderedKeys.indexOf(String(targetKey));
		if (movableIndex === -1 || targetIndex === -1) return;
		onReorder(movableIndex !== targetIndex ? orderedKeys.reduce((arr, key, i) => {
			if (i === movableIndex) return arr;
			if (i === targetIndex) if (dropPosition === "before") {
				arr.push(movableKey);
				arr.push(key);
			} else {
				arr.push(key);
				arr.push(movableKey);
			}
			else arr.push(key);
			return arr;
		}, []) : orderedKeys);
	});
	const getItems = useCallback((keys) => {
		return [...keys].map((key) => {
			const item = state.collection.getItem(key);
			return { "text/plain": item?.textValue || String(key) };
		});
	}, [state.collection]);
	const dragSelectionManager = useMemo(() => new Proxy(state.selectionManager, { get(target, prop) {
		if (prop === "selectedKeys") return /* @__PURE__ */ new Set();
		if (prop === "isSelected") return () => false;
		const value = Reflect.get(target, prop);
		return typeof value === "function" ? value.bind(target) : value;
	} }), [state.selectionManager]);
	const dragState = useDraggableCollectionState({
		collection: state.collection,
		selectionManager: dragSelectionManager,
		getItems,
		getAllowedDropOperations
	});
	useDraggableCollection({
		getItems,
		getAllowedDropOperations
	}, dragState, listRef);
	const dropState = useDroppableCollectionState({
		collection: state.collection,
		selectionManager: state.selectionManager,
		onReorder: handleReorder
	});
	const { collectionProps } = useDroppableCollection({
		keyboardDelegate: useMemo(() => new ListKeyboardDelegate(state.collection, state.disabledKeys, listRef), [
			state.collection,
			state.disabledKeys,
			listRef
		]),
		dropTargetDelegate: useMemo(() => new ListDropTargetDelegate(state.collection, listRef, { orientation }), [
			state.collection,
			listRef,
			orientation
		]),
		onReorder: handleReorder
	}, dropState, listRef);
	const isDragActive = dragState.draggingKeys.size > 0;
	const endDragRef = useRef(dragState.endDrag);
	endDragRef.current = dragState.endDrag;
	useEffect(() => {
		if (!isDragActive) return;
		const handleEscape = (e) => {
			if (e.key === "Escape") endDragRef.current({
				type: "cancel",
				x: 0,
				y: 0,
				dropOperation: "cancel",
				isInternal: false
			});
		};
		document.addEventListener("keydown", handleEscape, true);
		return () => document.removeEventListener("keydown", handleEscape, true);
	}, [isDragActive]);
	return children(dragState, dropState, mergeProps(collectionProps, { onKeyDownCapture: useEvent((e) => {
		if (!e.altKey || !onReorder) return;
		const target = e.target;
		if (target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement || target.isContentEditable) return;
		const moveKeys = orientation === "vertical" ? {
			backward: "ArrowUp",
			forward: "ArrowDown"
		} : {
			backward: "ArrowLeft",
			forward: "ArrowRight"
		};
		const direction = e.key === moveKeys.backward ? -1 : e.key === moveKeys.forward ? 1 : 0;
		if (direction === 0) return;
		e.preventDefault();
		e.stopPropagation();
		const focusedKey = String(state.selectionManager.focusedKey);
		const idx = orderedKeys.indexOf(focusedKey);
		if (idx === -1) return;
		const targetIdx = idx + direction;
		if (targetIdx < 0 || targetIdx >= orderedKeys.length) return;
		const newKeys = [...orderedKeys];
		[newKeys[idx], newKeys[targetIdx]] = [newKeys[targetIdx], newKeys[idx]];
		onReorder(newKeys);
	}) }));
}

//#endregion
export { DraggableCollection, createMockDragState };
//# sourceMappingURL=DraggableCollection.js.map