import { useThree } from "@react-three/fiber";
import { useCallback, useEffect, useRef } from "react";

import { Vector2 } from "three";

type SplatStack = {
  mouseX: number;
  mouseY: number;
  velocityX: number;
  velocityY: number;
};

export const usePointer = ({ force }: { force: number }) => {
  const size = useThree((three) => three.size);

  const splatStack: SplatStack[] = useRef([]).current;
  const lastMouse = useRef<Vector2>(new Vector2());
  const hasMoved = useRef<boolean>(false);

  const onPointerMove = useCallback(
    (event: { x: number; y: number }) => {
      const deltaX = event.x - lastMouse.current.x;
      const deltaY = event.y - lastMouse.current.y;

      if (!hasMoved.current) {
        hasMoved.current = true;
        lastMouse.current.set(event.x, event.y);
        return;
      }

      lastMouse.current.set(event.x, event.y);

      const splatInfo = {
        mouseX: event.x / size.width,
        mouseY: 1.0 - event.y / size.height,
        velocityX: deltaX * force,
        velocityY: -deltaY * force,
      };

      splatStack.push(splatInfo);
    },
    [force, size.height, size.width, splatStack],
  );

  useEffect(() => {
    addEventListener("pointermove", onPointerMove);
    return () => {
      removeEventListener("pointermove", onPointerMove);
    };
  }, [onPointerMove]);

  return splatStack;
};
