import { useEventListener } from '@vueuse/core'
import { onMounted, ref, unref } from 'vue'

export function useDragControls(options = {}) {
    const { target = null, onUpdate = () => {} } = options

    const x = ref(0)
    const y = ref(0)
    const isDragging = ref(false)

    let bounds = null

    const updateBounds = () => {
        if (target) {
            bounds = unref(target).getBoundingClientRect()
        } else {
            bounds = new DOMRect(0, 0, window.innerWidth, window.innerHeight)
        }
    }

    const updatePosition = (clientX, clientY) => {
        if (!bounds) return

        const relativeX = (clientX - bounds.left) / bounds.width
        const relativeY = (clientY - bounds.top) / bounds.height

        // Clamp between 0 and 1
        x.value = Math.min(1, Math.max(0, relativeX))
        y.value = Math.min(1, Math.max(0, relativeY))

        onUpdate?.({ x, y })
    }

    const start = (e) => {
        isDragging.value = true
        updateBounds()
        move(e)
    }

    const move = (e) => {
        if (!isDragging.value) return
        if (e instanceof MouseEvent) {
            updatePosition(e.clientX, e.clientY)
        } else {
            const touch = e.touches[0]
            if (touch) updatePosition(touch.clientX, touch.clientY)
        }
    }

    const end = () => {
        isDragging.value = false
    }

    onMounted(() => {
        const el = target ?? window

        // Mouse
        useEventListener(el, 'mousedown', start)
        useEventListener(window, 'mousemove', move)
        useEventListener(window, 'mouseup', end)

        // Touch
        useEventListener(el, 'touchstart', start, { passive: true })
        useEventListener(window, 'touchmove', move, { passive: true })
        useEventListener(window, 'touchend', end)
        useEventListener(window, 'touchcancel', end)

        // Resize
        useEventListener(window, 'resize', updateBounds)
    })

    return {
        x,
        y,
        isDragging,
    }
}
