in vec2 uv;

out vec4 C;

uniform float u_t;
uniform int tex_typo;

#include scene_jyrevis25/common.glsl

bool getText(vec2 p, vec2 ind, vec2 range) {
    if (abs(p.x)>range.x/2.0 || abs(p.y)>range.y/2.0) return false;
    return 0.5<texture(textures[tex_typo], (p+ind+4.0+vec2(0.5)*(fract(range/2.0)*2.0))/8.0).r;
}

vec2 melt(vec2 p, float amount) {
    return p+vec2(0,pow(sin(cos(p.x*4.9)*8.9+p.x-u_t)*0.5+0.7,.4))*amount;
}

vec2 fracture(vec2 p, float amount) {
    float part = 4.0;

    vec2 silly = sin(cos((p.yx)*2.8)*2.12)*0.5+0.5;
    silly *= 0.8;
    mat2 wobb = mat2(1.0+silly.x,0.0,0.0,1.0+silly.y);
    mat2 unwobb = mat2(1.0/(1.0+silly.x),0.0,0.0,1.0/(1.0+silly.y));
    vec2 q = (p*wobb-0.5/part)*wobb;

    vec2 i_p = floor(q*part),
         f_p = fract(q*part);
    seed = (uint)(i_p.y-i_p.x*35.124+5832.0);
    vec2 off = floor(0.5*(1.0+6.0/length(i_p+0.5))/(hash_v2()*2.0-1.0));
    return ((mix(i_p,off,amount)/part+f_p/part)*unwobb+0.5/part)*unwobb;
}

float funnyText(vec2 p, float reso) {
    return float(getText(p/reso,vec2(0),vec2(3,1)));
}

float cloud(vec2 p, float reso) {
    vec2 i_p = floor(p*reso),
         f_p = fract(p*reso);

    float neigh[9] = {
        funnyText(i_p+vec2(-1, 1),reso),funnyText(i_p+vec2(0, 1),reso),funnyText(i_p+vec2(1, 1),reso),
        funnyText(i_p+vec2(-1, 0),reso),funnyText(i_p+vec2(0, 0),reso),funnyText(i_p+vec2(1, 0),reso),
        funnyText(i_p+vec2(-1,-1),reso),funnyText(i_p+vec2(0,-1),reso),funnyText(i_p+vec2(1,-1),reso)
    };
    vec2 r = vec2(step(0.5,length(f_p-0.5)),0.0);
    r = mix(r, vec2(1.0)-r, neigh[4]);

    ivec2 corner = ivec2(sign(f_p-0.5));
    ivec2 choose[3] = {corner, corner*ivec2(0,1), corner*ivec2(1,0)};
    float chosen[3];
    for(int i=0; i<3; i++) { chosen[i] = neigh[choose[i].x+1+3*(1-choose[i].y)]; }
    
    return mix(r.x,r.y,
        mix(1.0-min(chosen[1], chosen[2]), max(chosen[0], max(chosen[1], chosen[2])), neigh[4])
    );
}

void main() {
    vec2 UV=vec2(uv.x*R.x/R.y, uv.y);

    vec3 col = c_beige;
    
    float musicT = u_t/BEAT_DUR;

    float segLetterDrop = musicT/7.0/4.0 - 6.0;
    float segLetterFrac = musicT/7.0/4.0 - 6.0 - 0.75/7.0;
    float segLetterRot = musicT/7.0/4.0 - 6.0 - 1.25/7.0;
    float segLetterZoom = musicT/7.0/4.0 - 6.0 - 1.5/7.0;
    float segPixel = musicT/7.0/4.0 - 6.0 - 1.75/7.0;
    float segFlash = musicT/7.0/4.0 - 6.0 - 2.5/7.0;
    float segFlashEnd = musicT/7.0/4.0 - 6.0 - 3.25/7.0;
    float segB = musicT/7.0/4.0 - 6.0 - 3.5/7.0;
    float segA = musicT/7.0/4.0 - 6.0 - 4.25/7.0;
    float segC = musicT/7.0/4.0 - 6.0 - 5.0/7.0;
    float segD = musicT/7.0/4.0 - 6.0 - 5.25/7.0;
    float segEnd = musicT/7.0/4.0 - 7.0;

    float timeKick = expease(fract(musicT/7.0)*7.0,4.0)+
                     expease(max(0.0,fract(musicT/7.0)*7.0-2.5),4.0)+
                     expease(max(0.0,fract(musicT/7.0)*7.0-4.0),4.0)+
                     expease(max(0.0,fract(musicT/7.0)*7.0-6.5),4.0);
    float deltaKick = (
        step(0.0,fract(musicT/7.0)*7.0)+
        step(2.5,fract(musicT/7.0)*7.0)+
        step(4.0,fract(musicT/7.0)*7.0)+
        step(6.5,fract(musicT/7.0)*7.0)
    )-timeKick;
    timeKick += floor(musicT/7.0)*4.0;

    float timeSnare = expease(max(0.0,fract(musicT/7.0)*7.0-1.0),4.0)+
                      expease(max(0.0,fract(musicT/7.0)*7.0-3.0),4.0)+
                      expease(max(0.0,fract(musicT/7.0)*7.0-5.0),4.0);
    float deltaSnare = (
        step(1.0,fract(musicT/7.0)*7.0)+
        step(3.0,fract(musicT/7.0)*7.0)+
        step(5.0,fract(musicT/7.0)*7.0)
    )-timeSnare;
    timeSnare += floor(musicT/7.0)*3.0;

    float timeBass;
    for(float i=0.0; i<6.0; i+=0.75){ timeBass += expease(max(0.0,fract(musicT/7.0)*7.0-i),8.0); }
    float deltaBass;
    for(float i=0.0; i<6.0; i+=0.75){ deltaBass += step(i,fract(musicT/7.0)*7.0); }
    deltaBass -= timeBass;
    timeBass += floor(musicT/3.5)*4.0;

    // camera shake
    UV += sin(u_t*99.9)*pow(deltaKick,3.0)*0.05;

    if(segC>0 && segEnd<0) {
        float test = ceil(timeBass);
        UV += vec2(cos(test*99.9+9.), sin(test*88.8+8.))*1.0 + deltaBass*0.1;
        UV *= 0.5+sin(test*333.3+3.)*0.3;
    }

    vec2 polar = vec2((atan(UV.y,UV.x)+PI)/TAU, log(length(UV))/4.0);
    polar.y -= timeKick*0.25;
    polar.x += sign(step(0.5,fract(musicT/7.0/2.0))-0.5) * (timeKick*0.1-polar.y*0.5);

    vec2 i_pol = floor(polar*5.0),
         f_pol = fract(polar*5.0);

    vec3 back = c_beige;
    vec3 front = c_pink;
    if(segFlash>0 && segFlashEnd<0 && sin(musicT*2.0*TAU)>0) {
        back = c_blue;
        front = c_red;
    }
    if(segB>0 && segEnd<0) {
        vec2 p = UV*1.5;
        float s = floor(p.y*4.0);
        seed = (uint)(s*888.8+37675.64);
        float shift = hash_f()*2.0-1.0;
        float gateBack = hash_f();
        if(segD<0) {
            p.x += sin(p.y*88.888)*deltaSnare;
            p.x += shift * step((timeSnare - floor(musicT/7.0)*3.0)/3.0, gateBack);
        }

        bool text = getText(p, vec2(2,5), vec2(6,3));
        if (segA>0) {
            if (!text) {
                back = c_blue;
                front = c_red;
            }
        }
        else{
            if (text) {
                back = c_blue;
                front = c_red;
            }
        }
    }

    col = mix(back, front, step(sin(polar.y*16.0-timeSnare*4.0)*0.2+0.6, abs(f_pol.x)));

    if(segLetterDrop>0 && segLetterRot<0) {
        vec2 p = UV*0.6;
        p += sin(p.x*40.0)*deltaSnare*0.05;
        p = fracture(p, clamp(p.x-1.0+1.0*expease(segLetterFrac, 128.0),0.0,1.0));
        if (getText(p - vec2(0,(1.0-expease(segLetterDrop,256.0))), vec2(5,5), vec2(2,1))) {
            col = c_blue;
        }
    }
    if(segLetterRot>0 && segPixel<0) {
        vec2 p = UV*0.6;
        p=melt(p,segLetterRot);
        p*=mat2(2.0,-0.5,0.0,1.0);
        p*=rot(expease(segLetterRot,256.0)*0.2);
        p*=2.0-expease(segLetterZoom,256.0);
        if (getText(p, vec2(3), vec2(4,1))) {
            col = c_red;
        }
    }
    if(segPixel>0 && segFlashEnd<0) {
        vec2 p = UV;
        p += sin(p.x*20.0)*deltaSnare*0.2;
        if(segFlash>0) {
            p *= mix(0.3,1.0,expease(segFlash,256.0));
        }
        col = mix(col, c_blue, cloud(p, 12.0+expease(segFlash,128.0)*24.0));
    }

    C = vec4(col, 1.0);
}
