#version 330 core

uniform vec3 iResolution;
uniform float iTime;
uniform float uAlpha;

out vec4 FragColor;

#define TAU 6.283185307179586

mat2 birra_rot(float a)
{
    float c = cos(a);
    float s = sin(a);
    return mat2(c, -s, s, c);
}

float birra_hash21(vec2 p)
{
    vec3 p3 = fract(vec3(p.x, p.y, p.x) * 0.1031);
    p3 += dot(p3, p3.yzx + vec3(33.33));
    return fract((p3.x + p3.y) * p3.z);
}

float birra_noise2(vec2 p)
{
    vec2 i = floor(p);
    vec2 f = fract(p);
    vec2 u = f * f * (3.0 - 2.0 * f);

    float a = birra_hash21(i);
    float b = birra_hash21(i + vec2(1.0, 0.0));
    float c = birra_hash21(i + vec2(0.0, 1.0));
    float d = birra_hash21(i + vec2(1.0, 1.0));

    return mix(mix(a, b, u.x), mix(c, d, u.x), u.y);
}

float birra_clockHand(vec2 p, float angle, float len, float thick)
{
    vec2 q = birra_rot(angle) * p;
    float h = step(0.0, q.y) * step(q.y, len);
    return exp(-abs(q.x) * thick) * h;
}

vec3 birra_clockFace(vec2 p, float t)
{
    vec3 col = vec3(0.0);
    float r = length(p);

    float outer = exp(-abs(r - 0.78) * 85.0);
    float inner = exp(-abs(r - 0.62) * 45.0);
    float glass = smoothstep(0.80, 0.05, r) * 0.18;
    float pulse = 0.65 + 0.35 * sin(t * 2.7);

    col += vec3(0.10, 0.17, 0.42) * glass;
    col += vec3(0.25, 0.42, 1.25) * outer;
    col += vec3(0.10, 0.19, 0.52) * inner;

    for(int i = 0; i < 60; i++)
    {
        float fi = float(i);
        float a = fi / 60.0 * TAU;
        vec2 q = birra_rot(a) * p;

        float major = 1.0 - step(0.5, mod(fi, 5.0));
        float tickLen = mix(0.045, 0.105, major);
        float tickThick = mix(230.0, 95.0, major);

        float tick =
            exp(-abs(q.x) * tickThick) *
            smoothstep(0.78, 0.72 - tickLen, q.y) *
            step(0.0, q.y);

        col += mix(vec3(0.18, 0.30, 0.75), vec3(0.60, 0.75, 1.70), major) * tick * 0.35;
    }

    float jitter = birra_noise2(p * 18.0 + vec2(t * 0.14, -t * 0.09));

    float secA = -t * 0.95 + sin(t * 0.41) * 0.12;
    float minA = -t * 0.075 + sin(t * 0.17) * 0.18;
    float hourA = -t * 0.011 + 0.25;

    col += vec3(0.18, 0.25, 0.70) * birra_clockHand(p, hourA, 0.36, 55.0);
    col += vec3(0.35, 0.50, 1.25) * birra_clockHand(p, minA, 0.55, 75.0);
    col += vec3(1.00, 0.22, 0.42) * birra_clockHand(p, secA, 0.67, 150.0) * (0.8 + jitter * 0.6);

    col += vec3(0.90, 0.95, 1.80) * exp(-r * 42.0);
    col += vec3(0.15, 0.22, 0.70) * exp(-abs(r - 0.34) * 30.0) * 0.15;

    float reflection =
        smoothstep(0.55, -0.2, p.x + p.y * 0.55) *
        smoothstep(0.78, 0.15, r) *
        pow(max(0.0, 1.0 - abs(p.y - p.x * 0.25)), 8.0);

    col += vec3(0.35, 0.55, 1.0) * reflection * 0.16;
    col *= 0.85 + 0.15 * pulse;

    return col;
}

void main()
{
    vec2 res = max(iResolution.xy, vec2(1.0));
    vec2 fragCoord = gl_FragCoord.xy;

    vec2 uv = fragCoord / res;
    vec2 p = uv * 2.0 - 1.0;
    p.x *= res.x / res.y;

    float t = iTime;

    vec3 bg = vec3(0.004, 0.005, 0.014);
    bg += vec3(0.018, 0.020, 0.050) * smoothstep(1.6, 0.0, length(p));

    vec3 col = bg + birra_clockFace(p * 0.95, t);

    float grain = birra_hash21(floor(fragCoord) + vec2(floor(t * 24.0)));
    col += (grain - 0.5) * 0.025;

    float vignette = pow(clamp(1.0 - length(p) * 0.42, 0.0, 1.0), 1.6);
    col *= vignette;

    col = vec3(1.0) - exp(-col * 1.55);
    col = pow(max(col, vec3(0.0)), vec3(0.92));

    FragColor = vec4(col, uAlpha);
}