import { useMemo } from 'react';
import * as THREE from 'three';

const SNAP_ANGLE_THRESHOLD = 15; // Degrees within which to snap to orthogonal direction

const SNAP_DISTANCE_THRESHOLD = 0.5; // Minimum distance to consider for directional snap

const CAN_SNAP = true; // Whether snapping is enabled or not

export const useDirectionalSnapping = (
    currentPoint: [number, number, number] | null,
    previousPoint: [number, number, number] | null
): { position: [number, number, number], isSnapped: boolean } => {
    return useMemo(() => {
        if (!currentPoint || !previousPoint || !CAN_SNAP) return { position: currentPoint || [0, 0, 0], isSnapped: false }; // No snapping if no points

        const currentVec = new THREE.Vector2(currentPoint[0], currentPoint[2]);
        const previousVec = new THREE.Vector2(previousPoint[0], previousPoint[2]);
        const directionVec = new THREE.Vector2().subVectors(currentVec, previousVec);

        const angle = THREE.MathUtils.radToDeg(directionVec.angle());
        const normalizedAngle = (angle + 360) % 360;
        const closestAngle = Math.round(normalizedAngle / 90) * 90 % 360;

        const angleDiff = Math.abs(normalizedAngle - closestAngle);
        const shortestDiff = Math.min(angleDiff, 360 - angleDiff);

        if (shortestDiff <= SNAP_ANGLE_THRESHOLD) {
            const distance = directionVec.length();
            const snappedDirection = new THREE.Vector2(
                Math.cos(THREE.MathUtils.degToRad(closestAngle)),
                Math.sin(THREE.MathUtils.degToRad(closestAngle))
            ).multiplyScalar(distance);

            const newPosition = new THREE.Vector2(previousPoint[0] + snappedDirection.x, previousPoint[2] + snappedDirection.y)

            if (newPosition.distanceTo(currentVec) > SNAP_DISTANCE_THRESHOLD) {
                return { position: currentPoint, isSnapped: false };
            }

            return {
                position: [
                    previousPoint[0] + snappedDirection.x,
                    currentPoint[1],
                    previousPoint[2] + snappedDirection.y
                ],
                isSnapped: true
            };
        }

        return { position: currentPoint, isSnapped: false };
    }, [currentPoint, previousPoint]);
};