import React, { useMemo, useRef } from 'react';
import { useFrame } from '@react-three/fiber';
import { SceneData, SceneEdge } from './Generator';
import * as THREE from 'three';
import { Line } from '@react-three/drei';

// A single CatmullRomCurve3 cable with particles moving along it
const Cable: React.FC<{ edge: SceneEdge }> = ({ edge }) => {
    const points = useMemo(() => edge.path.map(p => new THREE.Vector3(p[0], p[1], p[2])), [edge.path]);
    const curve = useMemo(() => new THREE.CatmullRomCurve3(points), [points]);

    // We extract the line points for rendering the static line
    const linePoints = useMemo(() => curve.getPoints(20), [curve]);
    const linePositions = useMemo(() => linePoints.flatMap(p => [p.x, p.y, p.z]), [linePoints]);

    const particleRef = useRef<THREE.Mesh>(null!);
    const timeRef = useRef(Math.random()); // Random offset for particles

    useFrame((state, delta) => {
        if (!particleRef.current) return;

        // Move particle along the curve. Speed based on edge type.
        const speed = edge.type === 'transmission' ? 0.3 : 0.15;
        timeRef.current = (timeRef.current + delta * speed) % 1;

        const pos = curve.getPointAt(timeRef.current);
        particleRef.current.position.copy(pos);
    });

    return (
        <group>
            {/* The actual cable. Underground cables can just be transparent or slightly visible */}
            {edge.type === 'transmission' && (
                <Line
                    points={linePoints}
                    color="#334155"
                    lineWidth={1.5}
                />
            )}
            {/* The glowing particle */}
            <mesh ref={particleRef}>
                <sphereGeometry args={[edge.type === 'transmission' ? 0.8 : 0.4, 8, 8]} />
                <meshBasicMaterial color="#82ed20" transparent opacity={0.8} />
            </mesh>
        </group>
    );
};

const TransmissionLines: React.FC<{ data: SceneData }> = ({ data }) => {
    return (
        <group>
            {data.edges.map(edge => (
                <Cable key={edge.id} edge={edge} />
            ))}
        </group>
    );
};

export default TransmissionLines;
