import type { Ref } from 'vue';
import { onBeforeUnmount, watch, onMounted } 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);
  });
}