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 float scale=12.;
const float px=scale*2./R.x;
const int SCENEPT[] = int[](83,67,69,78,69,-1,80,84);
const int PTGANG[] = int[](
-1,74,69,69,78,73,79,-1,
65,78,84,73,67,79,82,69,
-1,66,65,76,73,78,84,-1,
-1,-1,72,85,71,79,-1,-1,
-1,77,65,78,85,69,76,-1
);
const int ANNOUNCEMENTS[] = int[](
73,-1,65,77,-1,-1,-1,-1,
71,79,73,78,71,-1,-1,-1,
66,65,67,75,-1,84,79,-1,
84,65,73,87,65,78,-1,-1,

65,78,68,-1,87,79,78,84,
66,69,-1,72,69,82,69,-1,
70,79,82,-1,-1,-1,-1,-1,
69,86,79,75,69,-1,-1,-1,

83,69,69,-1,89,79,85,-1,
65,84,-1,-1,-1,-1,-1,-1,
83,69,83,83,73,79,78,83,
84,72,79,85,71,72,-1,-1,

83,80,69,67,73,65,76,-1,
84,72,88,-1,-1,84,79,-1,
80,83,69,78,79,85,71,72,
78,-1,70,65,77,83,-1,-1,

-1,-1,-1,65,83,-1,-1,-1,
77,69,76,72,79,82,65,83,
-1,65,70,79,78,83,79,-1,
-1,-1,-1,64,64,-1,-1,-1,

68,65,78,75,69,-1,-1,-1,
69,85,67,72,64,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,
75,65,77,-1,85,78,64,-1,

69,83,67,-1,-1,69,83,67,
84,83,67,72,85,69,83,83,
67,72,65,73,-1,72,79,69,
69,83,67,-1,-1,69,83,67
);
const int ANN_PAGE_LENGTH = 8*4;

#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));}
vec3 sdgSegment( in vec2 p, in vec2 a, in vec2 b, in float r )
{
    vec2 ba = b-a, pa = p-a;
    float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );
    vec2  q = pa-h*ba;
    float d = length(q);
    return vec3(d-r,q/d);
}
vec3 letter(vec2 p, int ascii)
{
    float distA=9999.,distB=9999.;
    int indA,indB;
    for(int j=0;j<SEGMENTS.length();j++){
        if((ascii_to_bitmask(ascii)&(1<<j))!=0){
            vec3 seg=sdgSegment(p,SEGMENTS[j][0],SEGMENTS[j][1],0.);
            if(seg.x<distA){
                indB=indA; distB=distA;
                indA=j;    distA=seg.x;
            }
            else if(seg.x<distB){
                indB=j;    distB=seg.x;
            }
        }
    }
    vec3 segA=sdgSegment(p,SEGMENTS[indA][0],SEGMENTS[indA][1],0.),
    segB=sdgSegment(p,SEGMENTS[indB][0],SEGMENTS[indB][1],0.);
    vec3 accum=segA;
    accum.yz=mix(segA.yz,segB.yz,.5 * (1.-smoothstep(0.,.1,abs(segA.x-segB.x))) * max(0.,min(1.,1.-segA.x)) );
    accum.yz=normalize(accum.yz);

    return accum;
}
float bubble(vec2 uv, int ch, float thicc){
    vec3 here=letter(uv,ch);
    vec3 up=   letter(uv+vec2(0, px),ch),
         down= letter(uv+vec2(0,-px),ch),
         left= letter(uv+vec2(-px,0),ch),
         right=letter(uv+vec2( px,0),ch);

    float da=min(
    dot(here.yz,   up.yz), min(
    dot(here.yz, down.yz), min(
    dot(here.yz, left.yz),
    dot(here.yz,right.yz)
    )));

    float val=here.x-thicc<0.?da-.8:abs(here.x-thicc)-.045;
    val=max(-here.x+.05,val);

    return step(0.,val);
}
float scenePT(vec2 p){ 
    float thicc=ease(sin(TAU*t*.125/BEAT_DUR)*.5+.5)+.1;
    float accum=1.;
    for(int i=0; i<SCENEPT.length(); i++){
        if(SCENEPT[i]==-1) continue;
        float off=float(i%SCENEPT.length()) - float(SCENEPT.length()-1)/2.;
        off*=2.05+thicc*2.;
        accum=min(accum,bubble(p-vec2(off,0),SCENEPT[i],thicc));
    }
    return accum;
}
float ptGang(vec2 p){
    float accum=1.;

    float thicc=ease(sin(TAU*t*.125/BEAT_DUR)*.5+.5)+.1;
    float thicc2=ease(-sin(TAU*t*.125/BEAT_DUR)*.5+.5)+.1;
    p.y-=2.;
    p/=4.05+thicc*.5;
    vec2 f_p=fract(p),
         i_p=floor(p);
    f_p-=.5;f_p*=4.5+thicc*1.5;
    int ind=int(i_p.x-4.-(i_p.y-2.)*8.);
    if(abs(i_p.x+.5)>4. || ind<0 || ind>=PTGANG.length()) return accum;
    if(PTGANG[ind]==-1) return accum;
    
    return bubble(f_p,PTGANG[ind],mix(thicc2,thicc,step(1.,mod(i_p.y,2.))));
}
float announcements(vec2 p, int page){
    float accum=1.;

    float thicc=ease(sin(TAU*t*.125/BEAT_DUR)*.5+.5)+.1;
    float thicc2=ease(-sin(TAU*t*.125/BEAT_DUR)*.5+.5)+.1;
    p.y-=0.;
    p/=4.05+thicc*.5;
    vec2 f_p=fract(p),
    i_p=floor(p);
    f_p-=.5;f_p*=4.5+thicc*1.5;
    int ind=int(i_p.x-4.-(i_p.y-2.)*8.);
    if(abs(i_p.x+.5)>4. || ind<0 || ind>=ANN_PAGE_LENGTH) return accum;
    if(ANNOUNCEMENTS[ind+page*ANN_PAGE_LENGTH]==-1) return accum;

    return bubble(f_p,ANNOUNCEMENTS[ind+page*ANN_PAGE_LENGTH],mix(thicc2,thicc,step(1.,mod(i_p.y,2.))));
}


void main(){
    const float PREV_END=224.;
    vec2 UV=vec2(uv.x*R.x/R.y,uv.y);
    UV*=scale;

    float i_t=floor(t/BEAT_DUR),
          f_t=fract(t/BEAT_DUR);
    
    float ind=floor((i_t-PREV_END)/16.);
    float dist;
    if(ind<.5) dist=scenePT(UV);
    else if(ind<1.5) dist=ptGang(UV);
    else dist=announcements(UV, int(min(ind-2.,6.)));
    
    C.rgb=mix(bg_col, main_col, dist);
}