in vec2 uv;

out vec4 C;

uniform float u_t;
uniform float u_bpm;
uniform vec3 bg_col;
uniform vec3 main_col;
uniform vec3 hl_col;

const float PI=acos(-1.);
const float TAU=PI*2.;
const float BEAT_DUR=60./u_bpm;
const int NORDLICHT[] = int[](72,65,76,76,79, 78,79,82,68,58, 76,73,67,72,84);
const ivec2 NORDLICHT_DIM = ivec2(5,NORDLICHT.length()/5);
const int VLTAVSKA[] = int[](86,76,84, 65,86,83, 75,65,58);
const ivec2 VLTAVSKA_DIM = ivec2(3,VLTAVSKA.length()/3);

#include scene_nordlicht24/jy-sdf-font.glsl
#include scene_nordlicht24/rand.glsl

//float rand(vec2 p){return dot(fract(sin(p*849.163)*636.164),fract(sin(p*734.845)*936.368));}
float Bayer2(vec2 a) {
    a = floor(a);
    return fract(a.x / 2. + a.y * a.y * .75);
}

#define Bayer4(a)   (Bayer2 (.5 *(a)) * .25 + Bayer2(a))
const float t=u_t-Bayer4(gl_FragCoord.xy)/50.0;

float ease(float n){return smoothstep(0.,1.,smoothstep(0.,1.,n));}
float sdSegment( in vec2 p, in vec2 a, in vec2 b )
{
    vec2 pa = p-a, ba = b-a;
    float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );
    return length( pa - ba*h );
}
float sdArc( in vec2 p, in vec2 sc, in float ra, float rb )
{
    // sc is the sin/cos of the arc's aperture
    p.x = abs(p.x);
    return ((sc.y*p.x>sc.x*p.y) ? length(p-sc*ra) :
    abs(length(p)-ra)) - rb;
}
float letter(vec2 p, int ascii)
{
    p*=3.;
    
    float accum=9999.;
    for(int j=0;j<SEGMENTS.length();j++){
        if((ascii_to_bitmask(ascii)&(1<<j))!=0){
            accum=min(accum,sdSegment(p,SEGMENTS[j][0],SEGMENTS[j][1]));
        }
    }

    return accum;
}
float xor(float a, float b){return min(max(-a,b),max(-b,a));}
float smiley(vec2 p){
    float openEye=abs(length(p-vec2(.2,.2))-.1)*3.;
    float wink=min(
    sdArc((p-vec2(-.175,0.))*rot(.2),vec2(sin(PI/4.),cos(PI/4.)),.15,0.)*3.,
    sdSegment(p,vec2(-.15,.25),vec2(-.05,.1))*3.
    );
    float smile=min(
    sdArc((p-vec2(-.05,.4))*rot(PI-.1),vec2(sin(PI/8.),cos(PI/8.)),.55,0.)*3.,
    sdArc((p-vec2(.15,-.15))*rot(PI-.4),vec2(sin(PI*.6),cos(PI*.6)),.1,0.)*3.
    );
    return min(smile,min(openEye,wink));
}
float nordlicht(vec2 p){
    float i_t=floor(t*.125/BEAT_DUR),
          f_t=fract(t*.125/BEAT_DUR);
    float i_t2=floor(t*1./BEAT_DUR),
          f_t2=fract(t*1./BEAT_DUR);
    
    float accum=1.;
    for(int i=0; i<NORDLICHT.length(); i++){
        vec2 off=vec2(
        float(i%NORDLICHT_DIM.x) - float(NORDLICHT_DIM.x-1)/2.,
        -float(i/NORDLICHT_DIM.x) + float(NORDLICHT_DIM.y-1)/2.
        );
        int j=int(rand(vec2(float(i), i_t)+10.)*NORDLICHT_DIM.x+i)%NORDLICHT.length();
        vec2 off2=vec2(
        float(j%NORDLICHT_DIM.x) - float(NORDLICHT_DIM.x-1)/2.,
        -float(j/NORDLICHT_DIM.x) + float(NORDLICHT_DIM.y-1)/2.
        );
        vec2 new_p=p-mix(off2,off,ease(min(f_t*2.,1.)));
        new_p*=rot(
        mix(0,rand(vec2(i+200))*PI-PI/2.,ease(f_t2))*
        max(0.,1.-abs(float(i)-mod(i_t2,float(NORDLICHT.length()))))
        );
        float thicc=mix(.3,.1,ease(min(f_t*1.5,1.)));
        if(i+1==10){
            accum=xor(accum,smiley(new_p)-thicc);
            continue;
        }
        accum=xor(accum,letter(new_p,NORDLICHT[i])-thicc);
    }
    return accum;
}
float arrow(vec2 p){
    const float SQR2=sqrt(2.);
    p*=2.;p=vec2(abs(p.x),p.y+.25);
    float a=max(max((p.x-p.y)/SQR2,p.x-.35),min(p.y,max(p.x,max((p.y-p.x-.2)/SQR2,p.y-.6))))-.35;
    return abs(a)*3.-.1;
}
float vltavska(vec2 p){
    float i_t=floor(t*.125/BEAT_DUR),
          f_t=fract(t*.125/BEAT_DUR);
    float i_t2=floor(t*1./BEAT_DUR),
          f_t2=fract(t*1./BEAT_DUR);

    float accum=1.;
    for(int i=0; i<VLTAVSKA.length(); i++){
        vec2 off=vec2(
        float(i%VLTAVSKA_DIM.x) - float(VLTAVSKA_DIM.x-1)/2.,
        -float(i/VLTAVSKA_DIM.x) + float(VLTAVSKA_DIM.y-1)/2.
        );
        int j=int(rand(vec2(float(i), i_t)+60.)*VLTAVSKA_DIM.x+i)%VLTAVSKA.length();
        vec2 off2=vec2(
        float(j%VLTAVSKA_DIM.x) - float(VLTAVSKA_DIM.x-1)/2.,
        -float(j/VLTAVSKA_DIM.x) + float(VLTAVSKA_DIM.y-1)/2.
        );
        vec2 new_p=p-mix(off2,off,ease(min(f_t*2.,1.)));
        new_p*=rot(
        mix(0,rand(vec2(i+200))*PI-PI/2.,ease(f_t2))*
        max(0.,1.-abs(float(i)-mod(i_t2,float(VLTAVSKA.length()))))
        );
        float thicc=mix(.3,.1,ease(min(f_t*1.5,1.)));
        if(i+1==9){
            accum=xor(accum,arrow(new_p)-thicc);
            continue;
        }
        accum=xor(accum,letter(new_p,VLTAVSKA[i])-thicc);
    }
    return accum;
}
void main() {
    const float PREV_END=96.;

    vec2 UV=vec2(uv.x*R.x/R.y,uv.y);
    
    UV*=2.;
    
    float i_t=floor(t/BEAT_DUR),
          f_t=fract(t/BEAT_DUR);
    
    float display=
    mix(
    nordlicht(UV),
    vltavska(UV),
    step(PREV_END+16.,i_t)
    );
    
    C = vec4(mix(main_col,bg_col,step(0.,display)), 1.0);
}
