// Uniforms for spectrogram frame count
uniform float totalFrames;
uniform float framesPerSecond;

#define VEC3_ZERO vec3(0.0, 0.0, 0.0)
#define VEC2_ZERO vec2(0.0, 0.0)
#define PINK vec3(157.0 / 255.0, 65.0 / 255.0, 75.0 / 255.0)
#define PURPLE vec3(73.0 / 255.0, 31.0 / 255.0, 126.0 / 255.0)
#define BLUE vec3(0.0 / 255.0, 117.0 / 255.0, 255.0 / 255.0)
#define PI 3.14159265358979323846264338327950
#define NUM_BANDS 5

float ease_out_sine(float x) {
    return sin((x * PI) / 2.0);
}

float sdCircle( in vec2 p, in float r ) 
{
    return length(p)-r;
}

float sdPulseBall(in vec2 p, in float radius, in vec2 offset)
{
    vec2 uv_a = p;
    uv_a.x += offset.x;
    uv_a.y += offset.y;
    
    float dist = sdCircle(uv_a, radius);
    float mix_factor = (1.0 - dist) - 0.1;
    return ease_out_sine(mix_factor);
}

vec2 rotatePoint(vec2 point, float angle, vec2 pivot) {
    // Create a 2D rotation matrix
    mat2 rotation = mat2(
        cos(angle), -sin(angle),
        sin(angle),  cos(angle)
    );
    
    // Translate so the pivot is at the origin, rotate, then translate back
    return rotation * (point - pivot) + pivot;
}

vec2 ratio_uv(in vec2 p, in vec2 res, in float scl)
{
    vec2 uv = p/res;
    float ratio_width_over_height = res.x / res.y;
    float ratio_height_over_width = res.y / res.x;
    
    uv.x -= 0.5;
    uv.y -= 0.5;
    
    vec2 scaledUV = uv;
    
    if (ratio_width_over_height <= 1.0) {
        scaledUV.y *= ratio_height_over_width;
    } else {
        scaledUV.x *= ratio_width_over_height;
    }
    
    scaledUV *= scl;
    return scaledUV;
}


void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 originalUV = fragCoord.xy / iResolution.xy;
    vec2 uv = ratio_uv(fragCoord.xy, iResolution.xy, 1.5);

    // Compute the current frame index from time (animation speed: 30 fps)
    float frameIdx = mod(iTime * framesPerSecond, totalFrames);
    // Horizontal position: evenly spaced across the screen

    float completion = (iTime * framesPerSecond) / totalFrames;

    float line_a_y = (0.5) / float(NUM_BANDS);
    float line_b_y = (1.5) / float(NUM_BANDS);
    float line_c_y = (2.5) / float(NUM_BANDS);
    float line_d_y = (3.5) / float(NUM_BANDS);
    float line_e_y = (4.5) / float(NUM_BANDS);
    
    // Fetch the amplitude from the spectrogram texture:
    // X coordinate uses current frame; Y coordinate is the band's center (0.5 of the band’s slice)
    float amplitude_a = texture(iChannel0, vec2(frameIdx / totalFrames, line_a_y)).r;
    float amplitude_b = texture(iChannel0, vec2(frameIdx / totalFrames, line_b_y)).r;
    float amplitude_c = texture(iChannel0, vec2(frameIdx / totalFrames, line_c_y)).r;
    float amplitude_d = texture(iChannel0, vec2(frameIdx / totalFrames, line_d_y)).r;
    float amplitude_e = texture(iChannel0, vec2(frameIdx / totalFrames, line_e_y)).r;

    float avg_amp = amplitude_a + amplitude_b + amplitude_c + amplitude_d + amplitude_e;
    avg_amp /= 5.0;

    float pink_pulse_a = amplitude_a;
    float pink_pulse_b = (amplitude_b + amplitude_c + amplitude_d + amplitude_e) / 4.0;

    float pulse_size_a = 0.4 * pink_pulse_a;
    float pulse_size_b = 0.4 * pink_pulse_b;

    float rot_angle = completion * PI * 2.0;
    
    vec2 pink_point = vec2(0.1, -0.1) * (1.0 + avg_amp);
    pink_point = rotatePoint(pink_point, rot_angle, VEC2_ZERO);
    
    vec2 blue_point = vec2(-0.1, 0.1) * (1.0 + avg_amp);
    blue_point = rotatePoint(blue_point, rot_angle, VEC2_ZERO);
    
    float dist_a = sdPulseBall(uv, pulse_size_a, pink_point);
    float dist_b = sdPulseBall(uv, pulse_size_b, blue_point);
    
    vec3 col_a = max(mix(VEC3_ZERO, PINK, dist_a), 0.0);
    vec3 col_b = max(mix(VEC3_ZERO, BLUE, dist_b), 0.0);
    
    vec3 col = vec3(mix(0.05, 0.15, originalUV.y));
    col = max(col, col_a);
    col = max(col, col_b);
    
    // Output to screen
    fragColor = vec4(col, 1.0);
}
