import { extend, useFrame, useThree } from '../../modules/three';
import gsap from 'gsap';
import React, { forwardRef, 
// useEffect,
useImperativeHandle, useMemo, useRef, } from 'react';
import { AdditiveBlending, Color, CubicBezierCurve3, DoubleSide, } from 'three';
// import {useSpring, easings} from '@react-spring/three';
import { gpstoVec3 } from '../../utils/helpers';
import { shaderMaterial } from '@react-three/drei';
const vertexShader = /*glsl*/ `
    varying vec2 vUv;
    void main() {
        vUv = uv;
        gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.);
    }
`;
const fragmentShader = /*glsl*/ `
    #define PI ${Math.PI}

    varying vec2 vUv;
    uniform vec2 uResolution;
    uniform vec3 uColorFrom;
    uniform vec3 uColorTo;
    uniform float uArcLength;
    uniform float uProgress;
    uniform float uLength;

    void main() {
        vec2 uv = vUv;
        float p = uv.x;
        float len = uLength;
        float alpha = 0.2;
        p = mix(len, 1. - len, p);
        p = step(uProgress - len / 2., p) - step(uProgress + len / 2., p);

        vec3 fragColor = mix(uColorFrom, uColorTo, uv.x) * p;

        p *= alpha;

        if (p <= 0.000001) discard;

        gl_FragColor = vec4(fragColor, p);
    }
`;
const ArcMaterial = shaderMaterial({
    uArcLength: 0,
    uResolution: [0, 0],
    uProgress: 0,
    uColorFrom: new Color(0xffffff),
    uColorTo: new Color(0xffffff),
    uLength: 0.4,
}, vertexShader, fragmentShader);
extend({ ArcMaterial });
export default forwardRef(function Arc({ start, end, radius = 1 }, ref) {
    const { size } = useThree();
    const mesh = useRef(null);
    const progress = useRef(0);
    useImperativeHandle(ref, () => ({
        set progress(p) {
            // setProgress(p);
            progress.current = p;
        },
        get progress() {
            // return progress;
            return progress.current;
        },
        revert() {
            gsap.to(progress, {
                current: 0,
                ease: 'power2.inOut',
                duration: 0.8,
            });
        },
    }), []);
    const startXYZ = useMemo(() => gpstoVec3(start.coordinates.lat, start.coordinates.lng, radius), [start, radius]);
    const endXYZ = useMemo(() => gpstoVec3(end.coordinates.lat, end.coordinates.lng, radius), [end, radius]);
    const curve = useMemo(() => {
        const fromStartToEnd = startXYZ.clone().sub(endXYZ);
        const fromEndToStart = endXYZ.clone().sub(startXYZ);
        const arcHeight = fromStartToEnd.length() * 0.6 + radius;
        const control1 = startXYZ
            .clone()
            .lerp(fromEndToStart, 0.25)
            .normalize()
            .multiplyScalar(arcHeight);
        const control2 = endXYZ
            .clone()
            .lerp(fromStartToEnd, 0.25)
            .normalize()
            .multiplyScalar(arcHeight);
        return new CubicBezierCurve3(startXYZ, control1, control2, endXYZ);
    }, [endXYZ, startXYZ, radius]);
    useFrame(() => {
        var _a;
        const m = (_a = mesh.current) === null || _a === void 0 ? void 0 : _a.material;
        if (!m) {
            return;
        }
        m.uniforms.uProgress.value = progress.current;
        m.uniformsNeedUpdate = true;
    });
    return (React.createElement("mesh", { ref: mesh },
        React.createElement("tubeGeometry", { args: [curve, 32, 0.003, 8] }),
        React.createElement("arcMaterial", { attach: "material", side: DoubleSide, blending: AdditiveBlending, transparent: true, uArcLength: { value: curve.getLength() }, uResolution: { value: [size.width, size.height] } })));
});
