import React, { useCallback, useMemo, useRef, useState } from 'react';
import { DndContext } from './DndContext';
import { DndMonitorContext } from './DndMonitorContext';
import { useDndMonitorProvider } from './useDndMonitorProvider';
export var DndContextComponent = function (_a) {
    var onDragStart = _a.onDragStart, onDragEnd = _a.onDragEnd, onDragOver = _a.onDragOver, children = _a.children;
    var draggableNodesRef = useRef(new Map());
    var droppableNodesRef = useRef(new Map());
    var _b = useDndMonitorProvider(), dispatchMonitorEvent = _b[0], registerMonitorListener = _b[1];
    var dragActiveIdRef = useRef(null);
    var dragOverIdRef = useRef(null);
    var _c = useState(null), dragActive = _c[0], setDragActive = _c[1];
    var handleDragStart = useCallback(function (nodeId) {
        var draggableNode = draggableNodesRef.current.get(nodeId);
        dragActiveIdRef.current = nodeId;
        setDragActive(true);
        var event = {
            active: draggableNode
        };
        onDragStart === null || onDragStart === void 0 ? void 0 : onDragStart(event);
        dispatchMonitorEvent({
            type: 'onDragStart',
            event: event
        });
    }, [dispatchMonitorEvent, onDragStart]);
    var handleDragOver = useCallback(function (nodeId) {
        dragOverIdRef.current = nodeId;
        var draggableNode = draggableNodesRef.current.get(dragActiveIdRef.current);
        var droppableNode = droppableNodesRef.current.get(nodeId);
        var event = {
            active: draggableNode,
            over: droppableNode
        };
        onDragOver === null || onDragOver === void 0 ? void 0 : onDragOver(event);
        dispatchMonitorEvent({
            type: 'onDragOver',
            event: {
                active: draggableNode,
                over: droppableNode
            }
        });
    }, [dispatchMonitorEvent, onDragOver]);
    var handleDragEnd = useCallback(function () {
        var draggableNode = draggableNodesRef.current.get(dragActiveIdRef.current);
        var droppableNode = droppableNodesRef.current.get(dragOverIdRef.current);
        var event = {
            active: draggableNode,
            over: droppableNode
        };
        setDragActive(false);
        onDragEnd === null || onDragEnd === void 0 ? void 0 : onDragEnd(event);
        dispatchMonitorEvent({
            type: 'onDragEnd',
            event: event
        });
        dragActiveIdRef.current = null;
        dragOverIdRef.current = null;
    }, [dispatchMonitorEvent, onDragEnd]);
    var contextValue = useMemo(function () { return ({
        draggableNodesRef: draggableNodesRef,
        droppableNodesRef: droppableNodesRef,
        onDragStart: handleDragStart,
        onDragEnd: handleDragEnd,
        onDragOver: handleDragOver,
        dragActive: dragActive,
        measureDroppableContainers: function () { }
    }); }, [dragActive, handleDragStart, handleDragEnd, handleDragOver]);
    return (React.createElement(DndContext.Provider, { value: contextValue },
        React.createElement(DndMonitorContext.Provider, { value: registerMonitorListener }, children)));
};
