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 sdCircle(vec2 p, float r) {
    return length(p) - r;
}

float sdBox(vec2 p, vec2 b) {
    vec2 d = abs(p) - b;
    return length(max(d, 0.0)) + min(max(d.x, d.y), 0.0);
}

vec2 rotate(vec2 p, float a) {
    float s = sin(a);
    float c = cos(a);
    return mat2(c, -s, s, c) * p;
}

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);

    // Aspect correction for shapes
    vec2 p = (uv - 0.5);
    p.x *= u_resolution.x / u_resolution.y;

    float t = u_time * 0.4 + u_seed;
    float beatImpact = u_beat * 0.1;

    // Background color shift
    vec3 colorA = vec3(0.05, 0.05, 0.1);
    vec3 colorB = vec3(0.1, 0.0, 0.2);
    if (u_colorCount >= 2) {
        colorA = u_colors[0] * 0.2;
        colorB = u_colors[int(mod(1.0 + floor(t * 0.1), float(u_colorCount)))] * 0.3;
    }
    vec3 finalColor = mix(colorA, colorB, sin(t) * 0.5 + 0.5);

    // Render shapes
    float shapes = 0.0;
    for (int i = 0; i < 6; i++) {
        float fi = float(i);
        float shapeSeed = u_seed + fi * 123.456;
        
        // Motion
        vec2 pos = vec2(
            sin(t * 0.5 + shapeSeed) * 0.8,
            cos(t * 0.3 + shapeSeed * 1.1) * 0.4
        );
        
        vec2 sp = p - pos;
        sp = rotate(sp, t * (0.5 + fract(shapeSeed)));
        
        float d;
        float size = 0.1 + fract(shapeSeed * 0.7) * 0.2 + beatImpact;
        
        if (mod(fi, 2.0) == 0.0) {
            d = sdCircle(sp, size);
        } else {
            d = sdBox(sp, vec2(size * 0.8));
        }
        
        float intensity = smoothstep(0.01, 0.0, d);
        
        // Pick a color for the shape
        vec3 shapeColor = vec3(1.0);
        if (u_colorCount > 0) {
            int colorIdx = int(mod(fi + floor(t), float(u_colorCount)));
            shapeColor = u_colors[colorIdx];
        }
        
        finalColor = mix(finalColor, shapeColor, intensity * 0.8);
        
        // Add a slight glow/aura
        finalColor += shapeColor * (1.0 - smoothstep(0.0, size * 2.0, abs(d))) * 0.2 * (0.5 + u_beat);
    }

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

export class FloatingShapesVisualizer extends VisualizerInterface {
    getName() {
        return "Floating Geometry";
    }

    getFragmentShader() {
        return fragmentShader;
    }
}