import type { Ref } from 'vue'
import { onBeforeUnmount, onMounted, watch } from 'vue'

const SMOOTH_PTG = 14 / 15
export default function useMobileTouchMove(
  inVirtual: Ref<boolean>,
  listRef: Ref<HTMLDivElement | undefined>,
  callback: (offsetY: number, smoothOffset?: boolean) => boolean,
) {
  let touched = false
  let touchY = 0

  let element: HTMLElement | null = null

  // Smooth scroll
  let interval: any = null

  const cleanUpEvents = () => {
    if (element) {
      element.removeEventListener('touchmove', onTouchMove)
      element.removeEventListener('touchend', onTouchEnd)
    }
  }

  const onTouchMove = (e: TouchEvent) => {
    if (touched) {
      const currentY = Math.ceil(e.touches[0].pageY)
      let offsetY = touchY - currentY
      touchY = currentY

      if (callback(offsetY)) {
        e.preventDefault()
      }

      // Smooth interval
      clearInterval(interval)
      interval = setInterval(() => {
        offsetY *= SMOOTH_PTG

        if (!callback(offsetY, true) || Math.abs(offsetY) <= 0.1) {
          clearInterval(interval)
        }
      }, 16)
    }
  }

  const onTouchEnd = () => {
    touched = false

    cleanUpEvents()
  }

  const onTouchStart = (e: TouchEvent) => {
    cleanUpEvents()

    if (e.touches.length === 1 && !touched) {
      touched = true
      touchY = Math.ceil(e.touches[0].pageY)

      element = e.target as HTMLElement
      element!.addEventListener('touchmove', onTouchMove, { passive: false })
      element!.addEventListener('touchend', onTouchEnd)
    }
  }
  const noop = () => {}

  onMounted(() => {
    document.addEventListener('touchmove', noop, { passive: false })
    watch(
      inVirtual,
      (val) => {
        listRef.value.removeEventListener('touchstart', onTouchStart)
        cleanUpEvents()
        clearInterval(interval)
        if (val) {
          listRef.value.addEventListener('touchstart', onTouchStart, { passive: false })
        }
      },
      { immediate: true },
    )
  })
  onBeforeUnmount(() => {
    document.removeEventListener('touchmove', noop)
  })
}
