import { useState, useEffect, useRef } from 'react';
import { isInstance } from '../utils';
const interactiveElementsTags = ['button', 'a', 'input', 'textarea', 'select', 'details'];
const shouldIgnoreEvent = (event) => {
    return interactiveElementsTags.some(tag => isInstance(event.target, Element) && event.target.tagName.toLowerCase() === tag);
};
/**
 * @param draggableElementRef Reference to the element which is draggable.
 * @param dragHandleRef Reference to the handle element which allows to move draggableElementRef.
 */
const useDraggable = (draggableElementRef, dragHandleRef, enabled = true) => {
    const [dragging, setDragging] = useState(false);
    const draggableElPosition = useRef({ x: 0, y: 0 });
    useEffect(() => {
        if (!enabled)
            return;
        const onMouseDown = (event) => {
            if (shouldIgnoreEvent(event))
                return;
            setDragging(true);
            if (draggableElementRef.current) {
                const { clientX, clientY } = 'touches' in event ? event.touches[0] : event;
                draggableElPosition.current.x =
                    clientX - draggableElementRef.current.getBoundingClientRect().left;
                draggableElPosition.current.y =
                    clientY - draggableElementRef.current.getBoundingClientRect().top;
            }
        };
        if (dragHandleRef.current) {
            // Save the current value so we can properly remove event listener after the ref has changed.
            const { current } = dragHandleRef;
            current.addEventListener('mousedown', onMouseDown);
            current.addEventListener('touchstart', onMouseDown);
            return () => {
                current.removeEventListener('mousedown', onMouseDown);
                current.removeEventListener('touchstart', onMouseDown);
            };
        }
    }, [dragHandleRef.current, enabled]);
    useEffect(() => {
        const onWindowResize = () => {
            const windowWidth = window.innerWidth;
            const windowHeight = window.innerHeight;
            if (draggableElementRef.current) {
                const limitX = draggableElementRef.current.offsetWidth - windowWidth;
                const limitY = draggableElementRef.current.offsetHeight - windowHeight;
                const positionX = draggableElementRef.current.getBoundingClientRect().left;
                const positionY = draggableElementRef.current.getBoundingClientRect().top;
                const horizontal = Math.min(Math.max(positionX, limitX), 0);
                const vertical = Math.min(Math.max(positionY, limitY), 0);
                draggableElementRef.current.style.transform = `translate(${horizontal}px, ${vertical}px)`;
            }
        };
        const onMouseMove = (event) => {
            const windowWidth = window.innerWidth;
            const windowHeight = window.innerHeight;
            if (!dragging)
                return;
            if (draggableElementRef.current) {
                const { clientX, clientY } = 'touches' in event ? event.touches[0] : event;
                const positionX = clientX - draggableElementRef.current.offsetLeft - draggableElPosition.current.x;
                const positionY = clientY - draggableElementRef.current.offsetTop - draggableElPosition.current.y;
                const limitX = draggableElementRef.current.offsetWidth - windowWidth;
                const limitY = draggableElementRef.current.offsetHeight - windowHeight;
                const horizontal = Math.min(Math.max(positionX, limitX), 0);
                const vertical = Math.min(Math.max(positionY, limitY), 0);
                draggableElementRef.current.style.transform = `translate(${horizontal}px, ${vertical}px)`;
            }
        };
        const onMouseUp = () => {
            setDragging(false);
        };
        window.addEventListener('resize', onWindowResize);
        if (dragging) {
            document.addEventListener('mouseup', onMouseUp);
            document.addEventListener('touchend', onMouseUp);
            document.addEventListener('mousemove', onMouseMove);
            document.addEventListener('touchmove', onMouseMove);
            return () => {
                document.removeEventListener('mouseup', onMouseUp);
                document.removeEventListener('touchend', onMouseUp);
                document.removeEventListener('mousemove', onMouseMove);
                document.removeEventListener('touchmove', onMouseMove);
            };
        }
        return () => {
            window.removeEventListener('resize', onWindowResize);
        };
    }, [dragging]);
};
export default useDraggable;
//# sourceMappingURL=useDraggable.js.map