import * as THREE from 'three';
import * as Constants from '../../../types/world/worldConstants';
import { useRef, useState, useEffect, useMemo } from 'react';
import { useToolMode } from '../../../store/builder/store';

function Point({ point, userData }: { readonly point: Point, readonly userData: any }) {
    const materialRef = useRef<THREE.ShaderMaterial>(null);
    const [isHovered, setIsHovered] = useState(false);
    const { toolMode } = useToolMode();

    const boxScale: [number, number, number] = Constants.pointConfig.boxScale;
    const defaultInnerColor = Constants.pointConfig.defaultInnerColor;
    const borderColor = Constants.pointConfig.aisleOuterColor;

    useEffect(() => {
        if (materialRef.current && toolMode === 'move') {
            materialRef.current.uniforms.uInnerColor.value.set(
                isHovered ? borderColor : defaultInnerColor
            );
            materialRef.current.uniformsNeedUpdate = true;
        } else if (materialRef.current && toolMode !== 'move') {
            materialRef.current.uniforms.uInnerColor.value.set(defaultInnerColor);
            materialRef.current.uniformsNeedUpdate = true;
        }
    }, [isHovered, borderColor, defaultInnerColor, toolMode]);

    const uniforms = useMemo(() => ({
        uColor: { value: new THREE.Color(borderColor) },
        uInnerColor: { value: new THREE.Color(defaultInnerColor) },
    }), [borderColor, defaultInnerColor]);

    if (!point) {
        return null;
    }

    return (
        <mesh
            uuid={point.uuid}
            position={new THREE.Vector3(...point.position)}
            onPointerOver={() => setIsHovered(true)}
            onPointerOut={() => setIsHovered(false)}
            userData={userData}
        >
            <boxGeometry args={boxScale} />
            <shaderMaterial
                ref={materialRef}
                uniforms={uniforms}
                vertexShader={`
                    varying vec2 vUv;
                
                    void main() {
                        vUv = uv;
                        gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
                    }
                `}
                fragmentShader={`
                    varying vec2 vUv;
                    uniform vec3 uColor;
                    uniform vec3 uInnerColor;
                
                    void main() {
                        // Define the size of the white square as a proportion of the face
                        float borderThickness = 0.2; // Adjust this value for border thickness
                        if (vUv.x > borderThickness && vUv.x < 1.0 - borderThickness && 
                            vUv.y > borderThickness && vUv.y < 1.0 - borderThickness) {
                            gl_FragColor = vec4(uInnerColor, 1.0); // Inner square
                        } else {
                            gl_FragColor = vec4(uColor, 1.0); // Border
                        }
                    }
                `}
            />
        </mesh>
    );
}

export default Point;