/* eslint-disable @typescript-eslint/no-explicit-any */
// #region Imports
// #endregion
// #region Registry
/**
 * Central registry for all drag and drop operations.
 * Singleton that coordinates between active drag instances.
 *
 * @public
 */
export class DragDropRegistry {
    // #region Fields
    static _instance = null;
    _dragItems;
    _dropContainers;
    _activeDragItem;
    _globalListeners;
    _pointerMoveThrottleId;
    // #endregion
    // #region Ctor
    /**
     * @private
     */
    constructor() {
        this._dragItems = new Set();
        this._dropContainers = new Set();
        this._activeDragItem = null;
        this._globalListeners = new Map();
        this._pointerMoveThrottleId = null;
    }
    // #endregion
    // #region Properties
    /**
     * Get singleton instance.
     *
     * @public
     */
    static get instance() {
        DragDropRegistry._instance ??= new DragDropRegistry();
        return DragDropRegistry._instance;
    }
    /**
     * Whether any drag operation is currently active.
     *
     * @public
     */
    get isDragging() {
        return this._activeDragItem !== null;
    }
    /**
     * Active drag item (if any).
     *
     * @public
     */
    get activeDragItem() {
        return this._activeDragItem;
    }
    // #endregion
    // #region Methods
    /**
     * Register a drag item.
     *
     * @param item - Drag item to register.
     *
     * @public
     */
    registerDragItem(item) {
        this._dragItems.add(item);
    }
    /**
     * Unregister a drag item.
     *
     * @param item - Drag item to unregister.
     *
     * @public
     */
    removeDragItem(item) {
        this._dragItems.delete(item);
        if (this._activeDragItem === item) {
            this._activeDragItem = null;
        }
    }
    /**
     * Register a drop container.
     *
     * @param container - Drop container to register.
     *
     * @public
     */
    registerDropContainer(container) {
        console.log('%c[DragDropRegistry] registerDropContainer', 'color: #673AB7', {
            containerId: container?.id || 'unknown',
            totalContainers: this._dropContainers.size + 1
        });
        this._dropContainers.add(container);
    }
    /**
     * Unregister a drop container.
     *
     * @param container - Drop container to unregister.
     *
     * @public
     */
    removeDropContainer(container) {
        console.log('%c[DragDropRegistry] removeDropContainer', 'color: #673AB7', {
            containerId: container?.id || 'unknown',
            totalContainers: this._dropContainers.size - 1
        });
        this._dropContainers.delete(container);
    }
    /**
     * Start a drag operation.
     *
     * @param item - Drag item that is starting.
     *
     * @public
     */
    startDragging(item) {
        console.log('%c[DragDropRegistry] startDragging', 'color: #FF5722; font-weight: bold', {
            hasActiveDrag: this._activeDragItem !== null,
            totalContainers: this._dropContainers.size,
            totalItems: this._dragItems.size
        });
        // If another item is dragging, stop it first
        if (this._activeDragItem && this._activeDragItem !== item) {
            // Force stop the previous drag
            console.log('%c[DragDropRegistry] startDragging - stopping previous drag', 'color: #FF5722');
            if (typeof this._activeDragItem._endDragSequence === 'function') {
                this._activeDragItem._endDragSequence(false);
            }
        }
        this._activeDragItem = item;
        this._setupGlobalListeners();
        console.log('%c[DragDropRegistry] startDragging - active', 'color: #FF5722');
    }
    /**
     * Stop a drag operation.
     *
     * @param item - Drag item that is stopping.
     *
     * @public
     */
    stopDragging(item) {
        console.log('%c[DragDropRegistry] stopDragging', 'color: #FF5722', {
            isActiveItem: this._activeDragItem === item
        });
        if (this._activeDragItem === item) {
            this._activeDragItem = null;
            this._removeGlobalListeners();
            console.log('%c[DragDropRegistry] stopDragging - stopped', 'color: #FF5722');
        }
    }
    /**
     * Get all registered drag items.
     *
     * @returns Array of drag items.
     *
     * @public
     */
    getDragItems() {
        return Array.from(this._dragItems);
    }
    /**
     * Get all registered drop containers.
     *
     * @returns Array of drop containers.
     *
     * @public
     */
    getDropContainers() {
        return Array.from(this._dropContainers);
    }
    /**
     * Find drop container at a specific point.
     *
     * @param x - X coordinate.
     * @param y - Y coordinate.
     * @returns Drop container or null.
     *
     * @public
     */
    getDropContainerAtPoint(x, y) {
        console.log('%c[DragDropRegistry] getDropContainerAtPoint', 'color: #9C27B0', {
            x,
            y,
            totalContainers: this._dropContainers.size
        });
        for (const container of this._dropContainers) {
            const cont = container;
            if (cont.disabled) {
                continue;
            }
            const element = cont.element;
            if (!element) {
                continue;
            }
            const rect = element.getBoundingClientRect();
            if (x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom) {
                console.log('%c[DragDropRegistry] getDropContainerAtPoint - found', 'color: #4CAF50', {
                    containerId: cont.id || 'unknown'
                });
                return container;
            }
        }
        console.log('%c[DragDropRegistry] getDropContainerAtPoint - no container found', 'color: #f44336');
        return null;
    }
    // #endregion
    // #region Private Methods
    /**
     * Setup global listeners for active drag.
     *
     * @private
     */
    _setupGlobalListeners() {
        if (this._globalListeners.size > 0) {
            return;
        }
        // Prevent default drag behavior
        const preventDefaultListener = (event) => {
            event.preventDefault();
        };
        document.addEventListener('dragstart', preventDefaultListener, { passive: false });
        document.addEventListener('selectstart', preventDefaultListener, { passive: false });
        this._globalListeners.set('dragstart', preventDefaultListener);
        this._globalListeners.set('selectstart', preventDefaultListener);
    }
    /**
     * Remove global listeners.
     *
     * @private
     */
    _removeGlobalListeners() {
        this._globalListeners.forEach((listener, eventName) => {
            document.removeEventListener(eventName, listener);
        });
        this._globalListeners.clear();
        if (this._pointerMoveThrottleId !== null) {
            cancelAnimationFrame(this._pointerMoveThrottleId);
            this._pointerMoveThrottleId = null;
        }
    }
}
// #endregion
// #region Factory
/**
 * Get the singleton registry instance.
 *
 * @returns Registry instance.
 *
 * @public
 */
export function getDragDropRegistry() {
    return DragDropRegistry.instance;
}
// #endregion
//# sourceMappingURL=DragDropRegistry.js.map