#version 330

out vec4 fragColor;


uniform vec2 iResolution;
uniform float iTime;

#define WIDTH 0.02
#define AMP 0.3*iTime*0.2
#define FREQ 2.0
#define SWART_R 0.2
#define FRACT_AMOUNT 20.

#define MYSTERY_CONSTANT 355./115.


#define timer1 8.0

float hash(vec2 p)
{
    return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453);
}

vec2 hash2(vec2 p)
{
    return vec2(hash(p), hash(p + 1.23));
}

float twinkles(vec2 uv)
{
    vec2 grid = uv * FRACT_AMOUNT;

    vec2 base = floor(grid);
    vec2 cell = fract(grid);

    float stars = 0.0;

    for (int y = -1; y <= 1; y++)
    {
        for (int x = -1; x <= 1; x++)
        {
            vec2 offset = vec2(x, y);
            vec2 id = base + offset;

            vec2 randOffset = hash2(id);

            vec2 anim = 0.2 * vec2(
                sin(iTime + hash(id)*10.0),
                cos(iTime + hash(id)*10.0)
            );

            vec2 starPos = randOffset + anim * 0.2;

            float d = length(cell - (offset + starPos));

            float size = mix(0.4, 1.2, hash(id + 10.0));
            size *= 0.9 + 0.3 * sin(iTime * 2.0 + hash(id)*20.0);

            float star = exp(-d * d / (WIDTH * size));

            float twinkle = 0.6 + 0.4 * sin(iTime * 5.0 + hash(id)*30.0);
            star *= twinkle;

            stars += star;
        }
    }

    return stars;
}

void main()
{
    vec2 uv = gl_FragCoord.xy / iResolution.xy;

    vec2 p = uv * 2.0 / (iTime*0.08) - 1.0 / (iTime*0.08);

    p.x *= iResolution.x / iResolution.y;

    float r = length(p);
    float schwarzschildRadius = SWART_R;

    float bend;

    if (iTime < 8.0)
        bend = 0.003 * 8. * cos(2.0 * MYSTERY_CONSTANT * 8. / 12.0 - 1.09)
            / max(r*r, 0.001);
    else if (iTime < 12.0)
        bend = 0.003 * iTime * cos(2.0 * MYSTERY_CONSTANT * iTime / 12.0 - 1.09)
            / max(r*r, 0.001);
        else 
            bend = 0.003 * (iTime*1.00002) * cos(2. * MYSTERY_CONSTANT * 12. / 12. - 1.09) / max(r*r, 0.001);

    vec2 dir = (r > 0.0) ? normalize(p) : vec2(0.0);
    p += dir * bend;

    vec2 starUV = p * 0.5 + 0.5;

    starUV.x += iTime * 0.25;

    float stars = twinkles(starUV);

    float vignette = exp(-pow(length(uv - 0.5) * 2.0, 2.0));
    stars *= vignette;

    vec3 col = vec3(0.2, 0.7, 0.8) * stars;

    float braight = iTime * 0.15;


    col = vec3(0.2 * braight * 0.7, 0.2* braight, 0.2* braight ) * stars;


    float glow;

// Glow 
    if (iTime < (timer1))
    {
        glow = smoothstep(0.3 + 0.06 * iTime, 0.3, r);

        col += vec3(
            glow * 0.7 * iTime,
            glow * 0.5,
            0.0
        ) * 0.7;

            float fade = 1.0 - smoothstep(
            timer1,
            timer1 + 6.0,
            iTime
        );
    }
    else {
    
    float frozenGlow = smoothstep(
        0.3 + 0.06 * timer1,
        0.3,
        r
    );

    
    float fade = 1.0 - smoothstep(
        timer1,
        timer1 + 6.0,
        iTime
    );

    col += vec3(
        frozenGlow * 0.7 * timer1,
        frozenGlow * 0.5,
        0.0
    ) * 0.7 * fade;
    }

    // ftn
    float streamY = 1.9 * sin(2. * MYSTERY_CONSTANT * iTime / 16.) *
                    sin(abs(sin(-iTime * 0.18)) * 3.0 + p.x * 3.0);

    float streamWidth = 0.2;

    float photonStream = exp(-pow((p.y - streamY) / streamWidth, 2.0));

    float horizGlow = smoothstep(0., 0.3, sin(p.x + iTime * 2.0)) + 0.5;
    photonStream *= horizGlow;

    float escapeMask = step(schwarzschildRadius * (iTime-timer1)*0.03, r);
    photonStream *= escapeMask;

    float falloff = smoothstep(schwarzschildRadius * 3.0,
                               schwarzschildRadius * (iTime-timer1)*0.03, r);
    photonStream *= falloff;

    if (iTime < 15)
        col += vec3(0.7, 0.7, 0.0) * photonStream * 0.3;
    else col += vec3(0.7-iTime/128.,0.7-iTime/128.,0.0+iTime/64.) * photonStream * 0.3;

    float glowFade = 1.0;

// horizon
    if (iTime >= (12.))
    {
        if (r < 0.005 * (iTime-12) * 2.5)
            col = vec3(0.0);
    }

if (iTime >= (timer1-6.))
{
    glowFade = exp(-(iTime - timer1) * 2.);
}


fragColor = vec4(col, 1.0);
}