import { VisualizerInterface } from './VisualizerInterface.js';

const fragmentShader = `
uniform float u_time;
uniform float u_beat;
uniform float u_opacity;
uniform vec2 u_resolution;
uniform vec3 u_colors[16];
uniform int u_colorCount;
uniform float u_seed;
varying vec2 vUv;

float hash(float n) { return fract(sin(n) * 43758.5453123); }

float noise(vec2 p) {
    vec2 i = floor(p);
    vec2 f = fract(p);
    f = f * f * (3.0 - 2.0 * f);
    float n = i.x + i.y * 57.0;
    return mix(mix(hash(n + 0.0), hash(n + 1.0), f.x),
               mix(hash(n + 57.0), hash(n + 58.0), f.x), f.y);
}

void main() {
    // LED Grid Setup
    float ledCountX = u_resolution.x;
    float ledCountY = u_resolution.y;
    vec2 gridUV = vec2(vUv.x * ledCountX, vUv.y * ledCountY);
    vec2 gridDeriv = fwidth(gridUV);
    float gridDensity = max(gridDeriv.x, gridDeriv.y);
    float blurFactor = smoothstep(0.3, 0.8, gridDensity);
    vec2 cell = fract(gridUV);
    vec2 uv = mix((floor(gridUV) + 0.5) / vec2(ledCountX, ledCountY), vUv, blurFactor);
    
    float distMask = distance(cell, vec2(0.5));
    float edgeSoftness = clamp(gridDensity * 1.5, 0.0, 0.5);
    float mask = 1.0 - smoothstep(0.35 - edgeSoftness, 0.45 + edgeSoftness, distMask);
    mask = mix(mask, 1.0, blurFactor);

    // --- Synthwave Logic ---
    vec2 p = uv * 2.0 - 1.0;
    p.x *= u_resolution.x / u_resolution.y;
    
    float t = u_time * 1.5 + u_seed;
    float beat = u_beat;

    // Colors
    vec3 colorMain = vec3(1.0, 0.0, 0.8); // Pink/Magenta
    vec3 colorSec = vec3(0.0, 0.8, 1.0);  // Cyan
    vec3 colorBg = vec3(0.02, 0.0, 0.05);
    
    if (u_colorCount >= 2) {
        colorMain = u_colors[0];
        colorSec = u_colors[int(mod(1.0, float(u_colorCount)))];
    }

    vec3 finalColor = colorBg;

    // Horizon
    float horizon = 0.0;
    
    // 1. Perspective Grid (Ground)
    if (p.y < horizon) {
        float perspective = 1.0 / (horizon - p.y + 0.05);
        vec2 gridP = vec2(p.x * perspective, perspective + t * 2.0);
        
        float gridLines = smoothstep(0.05, 0.0, abs(fract(gridP.x + 0.5) - 0.5)) +
                         smoothstep(0.05, 0.0, abs(fract(gridP.y + 0.5) - 0.5));
        
        finalColor = mix(finalColor, colorSec, gridLines * 0.5 * (0.5 + beat));
        
        // Road highlight
        if (abs(p.x * perspective) < 0.8) {
            finalColor += colorMain * 0.2 * perspective;
        }
    }

    // 2. Wireframe Mountains
    float mountainHeight = 0.0;
    if (p.y > horizon - 0.1) {
        float side = sign(p.x);
        float mountainX = abs(p.x) - 0.5;
        if (mountainX > 0.0) {
            float mNoise = noise(vec2(mountainX * 2.0 + t * 0.1, u_seed));
            mountainHeight = mNoise * 0.6 * smoothstep(0.0, 0.5, mountainX);
            
            if (p.y - horizon < mountainHeight) {
                float distToEdge = abs(p.y - horizon - mountainHeight);
                float wireframe = smoothstep(0.02, 0.0, distToEdge);
                
                // Internal wireframe lines
                wireframe += smoothstep(0.01, 0.0, abs(fract((p.y - horizon) * 10.0) - 0.5));
                wireframe += smoothstep(0.01, 0.0, abs(fract(mountainX * 10.0) - 0.5));
                
                finalColor = mix(finalColor, colorMain, wireframe * 0.4);
            }
        }
    }

    // 3. Retro Sun
    vec2 sunPos = vec2(0.0, 0.1);
    float sunRad = 0.4;
    float distToSun = length(p - sunPos);
    if (distToSun < sunRad && p.y > horizon) {
        // Scanlines / Cutouts
        float scanline = sin((p.y - t * 0.1) * 50.0);
        if (scanline < mix(0.8, -1.0, (p.y - sunPos.y + sunRad) / (sunRad * 2.0))) {
            float grad = 1.0 - (distToSun / sunRad);
            vec3 sunCol = mix(colorMain, vec3(1.0, 0.8, 0.0), p.y * 2.0);
            finalColor = mix(finalColor, sunCol, 0.8 + beat * 0.2);
        }
    }

    // 4. Car Silhouette
    float carDrift = sin(t * 0.1) * 0.2;
    float carVibration = sin(t * 30.0) * 0.001;
    vec2 carPos = vec2(carDrift, -0.78 + carVibration);
    vec2 cp = p - carPos;
    float cpX = abs(cp.x);
    
    float mainBody = step(cpX, 0.35) * step(abs(cp.y), 0.12);
    float rearGlass = step(cpX, 0.22) * step(abs(cp.y - 0.18), 0.07);
    float wingTop = step(cpX, 0.32) * step(abs(cp.y - 0.20), 0.025);
    float wingSides = step(abs(cpX - 0.30), 0.03) * step(abs(cp.y - 0.12), 0.1);
    
    if (mainBody + rearGlass + wingTop + wingSides > 0.0) {
        finalColor = mix(finalColor, vec3(0.015), 0.95); // Dark silhouette
        
        // Iconic quad round taillights
        float tlY = 0.03;
        float tlRadius = 0.025;
        float l1 = smoothstep(tlRadius, tlRadius * 0.6, length(vec2(cpX - 0.21, cp.y - tlY)));
        float l2 = smoothstep(tlRadius, tlRadius * 0.6, length(vec2(cpX - 0.29, cp.y - tlY)));
        vec3 lightColor = vec3(1.0, 0.0, 0.0) * (0.6 + beat * 1.4);
        finalColor = mix(finalColor, lightColor, clamp(l1 + l2, 0.0, 1.0));
    }

    gl_FragColor = vec4(finalColor, mask * u_opacity);
}
`;

export class SynthwaveRunVisualizer extends VisualizerInterface {
    getName() {
        return "Synthwave Run";
    }

    getFragmentShader() {
        return fragmentShader;
    }
}