#version 330 core
out vec4 FragColor;
in vec2 vUV;
uniform vec3 iResolution;
uniform float iTime;
uniform float uAlpha;

// Firework Rainbow - Procedural rainbow fireworks
// Converted for desktop GLSL (remove precision qualifiers)

const float PI = 3.14159265359;
const float TWO_PI = 6.28318530718;

// Tweakable parameters moved to uniforms so they can be set per-scene
uniform float uExplosionCount; // default 6.0
uniform float uSparksPerExplosion; // default 150.0
uniform float uExplosionDuration; // default 20.0
uniform float uExplosionSpeed; // default 5.0
uniform float uExplosionRadiusThreshold; // default 0.07

const vec3 RAINBOW_OFFSET = vec3(0.0,0.33,0.67);

// Hash function to generate pseudo-random values
vec3 hash33(vec3 p3) {
    p3 = fract(p3 * vec3(0.1031, 0.11369, 0.13787));
    p3 += dot(p3, p3.yxz + 19.19);
    return fract((p3.xxy + p3.yxx) * p3.zyx);
}

// Function to generate rainbow colors
vec3 rainbow(float t) {
    vec3 c = 0.5 + 0.5 * cos(TWO_PI * (t + RAINBOW_OFFSET));
    return c * c;
}

void mainImage(out vec4 fragColor, in vec2 fragCoord) {
    vec2 uv = fragCoord / iResolution.y;
    float aspectRatio = iResolution.x / iResolution.y;
    float t = mod(iTime + 10.0, 7200.0);
    vec3 col = vec3(0.0);

    // Loop through all sparks for all explosions
    float totalSparks = uSparksPerExplosion * uExplosionCount;
    for (float i = 0.0; i < totalSparks; i += 1.0) {
        float j = floor(i / uSparksPerExplosion);
        vec3 oh = hash33(vec3(j + 1234.1939, 641.6974, 1.0));
        vec2 origin = vec2(oh.x * aspectRatio, oh.y) * 0.6 + 0.2;
        float localT = t + (j + 1.0) * 9.6491 * oh.z;

        vec3 h = hash33(vec3(j, i, 497.8943));
        float a = h.x * TWO_PI;
        float rScale = h.y * uExplosionRadiusThreshold;

        if (mod(localT * uExplosionSpeed, uExplosionDuration) > 2.0) {
            float r = mod(localT * uExplosionSpeed, uExplosionDuration) * rScale;
            vec2 sparkPos = vec2(r * cos(a), r * sin(a));

            sparkPos.y -= pow((length(sparkPos) - (rScale - 0.04)) / 0.04, 3.0) * 6e-5;

            float spark = 0.0002 / pow(length(uv - sparkPos - origin), 1.65);
            float sd = 2.0 * length(origin - sparkPos);
            float shimmer = max(0.0, sqrt(sd) * sin((localT + h.y * 2.0 * PI) * 20.0));

            float fade = max(0.0, (uExplosionDuration - 5.0) * rScale - r);

            // Generate a random rainbow color for each spark
            vec3 sparkColor = rainbow(h.x + iTime * 0.1);
            col += spark * mix(1.0, shimmer, smoothstep(6.4 * rScale, 7.4 * rScale, r)) * fade * sparkColor;
        }
    }

    fragColor = vec4(col, 1.0);
}

void main()
{
    vec2 fragCoord = vUV * iResolution.xy;
    mainImage(FragColor, fragCoord);
    FragColor.a *= uAlpha;
}
