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 CIOSAI[] = int[](67,73,79, 83,65,73);
const ivec2 CIOSAI_DIM = ivec2(3,CIOSAI.length()/3);
const int LIHO[] = int[](76,73,72,79, 70,82,79,77);
const ivec2 LIHO_DIM = ivec2(4,LIHO.length()/4);
const int TAIWAN[] = int[](84,65,73, 87,65,78);
const ivec2 TAIWAN_DIM = ivec2(3,TAIWAN.length()/3);

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

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 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 ciosai(vec2 p){
    float accum=1.;
    for(int i=0; i<CIOSAI.length(); i++){
        vec2 off=vec2(
        float(i%CIOSAI_DIM.x) - float(CIOSAI_DIM.x-1)/2.,
        -float(i/CIOSAI_DIM.x) + float(CIOSAI_DIM.y-1)/2.
        );
        accum=min(accum,letter(p-off,CIOSAI[i]));
    }
    return accum;
}

float liho(vec2 p){
    float accum=1.;
    for(int i=0; i<LIHO.length(); i++){
        vec2 off=vec2(
        float(i%LIHO_DIM.x) - float(LIHO_DIM.x-1)/2.,
        -float(i/LIHO_DIM.x) + float(LIHO_DIM.y-1)/2.
        );
        accum=min(accum,letter(p-off,LIHO[i]));
    }
    return accum;
}

float taiwan(vec2 p){
    float accum=1.;
    for(int i=0; i<TAIWAN.length(); i++){
        vec2 off=vec2(
        float(i%TAIWAN_DIM.x) - float(TAIWAN_DIM.x-1)/2.,
        -float(i/TAIWAN_DIM.x) + float(TAIWAN_DIM.y-1)/2.
        );
        accum=min(accum,letter(p-off,TAIWAN[i]));
    }
    return accum;
}

//                  (from, to, direction)
vec2 squish(vec2 p, vec3 cut, float amt){
    cut.y=mix(cut.x,cut.y,amt);
    if(cut.z>0.){
        p.x=p.x>cut.y?(p.x-cut.y)*(1.-cut.x)/(1.-cut.y)+cut.x:p.x*cut.x/cut.y;
    }
    else{
        p.y=p.y>cut.y?(p.y-cut.y)*(1.-cut.x)/(1.-cut.y)+cut.x:p.y*cut.x/cut.y;
    }
    return p;
}

vec3 rotato(vec2 uv){
    const float PREV_END=64.;

    vec2 UV=uv*.5+.5;

    float i_t=floor(t/BEAT_DUR),
          f_t=fract(t/BEAT_DUR);

    for(int i=0; i<8; i++){
        float amt=ease(f_t);
        if(i_t-i -.5 > PREV_END+24.) amt=1.;
        if(i_t-i +.5 < PREV_END+24.) amt=0.;
        vec3 cut=rand(i+21);
        UV=squish(UV,cut*vec3(.4,.4,2.)+vec3(.5,.5,-1.),amt);
    }

    UV=vec2(UV.x*R.x/R.y,UV.y)-vec2(.5*R.x/R.y,.5);
    UV*=3.;

    float display=
    mix(
    ciosai(UV),
    mix(
    liho(UV),
    taiwan(UV),
    step(PREV_END+16.,i_t)
    ),
    step(PREV_END+8.,i_t)
    );

    float back =step(fract(.5-atan(UV.y,UV.x)/TAU+.5 + t*.2 + (i_t+ease(f_t))*.35)*.3+.05,display);
    float front=step(fract(   atan(UV.y,UV.x)/TAU+.5 - t*.2 - (i_t+ease(f_t))*.35)*.3+.05,display);

    vec3 col=mix(main_col,mix(hl_col,bg_col,back),front);
    if(i_t +.5 > PREV_END+30.){
        return mix(bg_col,mix(hl_col,main_col,back),front);
    }
    return col;
}

void main() {
    C = vec4(rotato(uv), 1.0);
}
