import * as THREE from "three";
import { useEffect, useMemo, useRef, useCallback } from "react";
import { useThree } from "@react-three/fiber";
import { useHeatMapStore } from "../../../store/simulation/useHeatMapStore";
import * as CONSTANTS from "../../../types/world/worldConstants";
import { exportHeatmapAsPNG } from "../functions/exportHeatmapAsPNG";

// Constants
const RADIUS = 0.0025;
const OPACITY = 0.8;
const GROWTH_RATE = 20.0;

// 🔹 React Component
const BakedHeatMap = () => {
    const { bakedPoints } = useHeatMapStore();
    const materialRef = useRef<THREE.ShaderMaterial>(null);
    const meshRef = useRef<THREE.Mesh>(null);
    const { gl } = useThree();

    const height = CONSTANTS.gridConfig.size;
    const width = CONSTANTS.gridConfig.size;

    const pointTexture = useMemo(() => {
        if (bakedPoints.length === 0) return null;
        const data = new Float32Array(bakedPoints.length * 4);
        bakedPoints.forEach((p, i) => {
            const index = i * 4;
            data[index] = (p.points.x + width / 2) / width;
            data[index + 1] = (p.points.y + height / 2) / height;
            data[index + 2] = 0.3;
            data[index + 3] = 0.0;
        });
        const texture = new THREE.DataTexture(data, bakedPoints.length, 1, THREE.RGBAFormat, THREE.FloatType);
        texture.needsUpdate = true;
        return texture;
    }, [bakedPoints, width, height]);

    const uniformsRef = useRef({
        u_points: { value: pointTexture },
        u_count: { value: bakedPoints.length },
        u_radius: { value: RADIUS },
        u_opacity: { value: OPACITY },
        u_growthRate: { value: GROWTH_RATE },
    });

    useEffect(() => {
        uniformsRef.current.u_points.value = pointTexture;
        uniformsRef.current.u_count.value = bakedPoints.length;
    }, [pointTexture, bakedPoints.length]);

    useEffect(() => {
        if (meshRef.current) {
            exportHeatmapAsPNG({
                bakedPoints,
                gl,
                width: width,
                height: height,
                mesh: meshRef.current,
            });
        }
    }, []);

    return (
        <></>
        // <mesh ref={meshRef} rotation={[Math.PI / 2, 0, 0]} position={[0, 0.025, 0]}>
        //     <planeGeometry args={[width, height]} />
        //     <shaderMaterial
        //         ref={materialRef}
        //         transparent
        //         depthWrite={false}
        //         blending={THREE.AdditiveBlending}
        //         uniforms={uniformsRef.current}
        //         side={THREE.DoubleSide}
        //         vertexShader={`
        //             varying vec2 vUv;
        //             void main() {
        //                 vUv = uv;
        //                 gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
        //             }
        //         `}
        //         fragmentShader={`
        //             uniform sampler2D u_points;
        //             precision highp float;
        //             uniform int u_count;
        //             uniform float u_radius;
        //             uniform float u_opacity;
        //             uniform float u_growthRate;
        //             varying vec2 vUv;

        //             float gauss(float dist, float radius) {
        //                 return exp(-pow(dist / radius, 2.0));
        //             }

        //             void main() {
        //                 float intensity = 0.0;

        //                 for (int i = 0; i < 10000; i++) {
        //                     if (i >= u_count) break;
        //                     float fi = float(i) + 0.5;
        //                     float u = fi / float(u_count);

        //                     vec4 point = texture2D(u_points, vec2(u, 0.5));
        //                     vec2 pos = point.rg;
        //                     float strength = point.b;

        //                     float d = distance(vUv, pos);
        //                     intensity += strength * gauss(d, u_radius);
        //                 }

        //                 float normalized = clamp(intensity / max(u_growthRate, 0.0001), 0.0, 1.0);

        //                 vec3 color = vec3(0.0);
        //                 if (normalized < 0.33) {
        //                     color = mix(vec3(0.0, 0.0, 1.0), vec3(0.0, 1.0, 0.0), normalized / 0.33);
        //                 } else if (normalized < 0.66) {
        //                     color = mix(vec3(0.0, 1.0, 0.0), vec3(1.0, 1.0, 0.0), (normalized - 0.33) / 0.33);
        //                 } else {
        //                     color = mix(vec3(1.0, 1.0, 0.0), vec3(1.0, 0.0, 0.0), (normalized - 0.66) / 0.34);
        //                 }

        //                 gl_FragColor = vec4(color, normalized * u_opacity);
        //             }
        //         `}
        //     />
        // </mesh>
    );
};

export default BakedHeatMap;
