in vec2 uv;

out vec4 C;

const float SPLIT_GATE = 0.6;

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;
}

// vec3(vec2 tile_uv, float tile_id)
vec3 quadtree(vec2 p, float t){
    float t_i=floor(t);

    int layer=0;
    float accum=noise(vec3(floor(p*2.)+vec2(t_i),0)).x;
    for(;layer<3;layer++){
        accum=noise(vec3(floor(p*float(1<<(layer+2)))+vec2(t_i),0)).x;
        if(accum<SPLIT_GATE) break;
    }
    float zoom=float(1<<(layer+2));
    return vec3(p*zoom-floor(p*zoom),accum);
}

float truchet(vec2 p) {
    float musicT = u_t/BEAT_DUR;
    float segTruchetGone = musicT/7.0/4.0 - 8.0 - 5.25/7.0;

    return step(min(abs(length(p-1.0)-1.0), abs(length(p+1.0)-1.0)), 0.2 - clamp(segTruchetGone*7.0,0.0,1.0)*0.2);
}

vec2 box(vec3 p) {
    vec3 q=abs(p);
    return vec2(
        max(q.x,max(q.y,q.z)),
        q.x>max(q.y,q.z)?
            round(sign(p.x)*0.5+0.5)
        :(
            q.y>q.z?
                round(sign(p.y)*0.5+0.5)+2.0
            :
                round(sign(p.z)*0.5+0.5)+4.0
        )
    );
}

void main() {
    vec2 UV=vec2(uv.x*R.x/R.y, uv.y);
    seed = uint(uv.y*33333.+uv.x*3333.+333333.);
    UV += (hash_v2()*2.0-1.0)*hash_f()*0.2*step(0.85,hash_f());

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

    float segBass = musicT/7.0/4.0 - 8.0 - 5.25/7.0;
    float segTruchetGone = musicT/7.0/4.0 - 8.0 - 5.25/7.0;

    float timeKick = expease(fract(musicT/7.0)*7.0,2.0)+
                     expease(max(0.0,fract(musicT/7.0)*7.0-4.25),2.0)+
                     expease(max(0.0,fract(musicT/7.0)*7.0-6.0),2.0);
    float deltaKick = (
        step(0.0,fract(musicT/7.0)*7.0)+
        step(4.25,fract(musicT/7.0)*7.0)+
        step(6.0,fract(musicT/7.0)*7.0)
    )-timeKick;
    timeKick += floor(musicT/7.0)*3.0;

    float timeSnare = expease(max(0.0,fract(musicT/7.0)*7.0-3.0),4.0);
    float deltaSnare = step(3.0,fract(musicT/7.0)*7.0)-timeSnare;
    timeSnare += floor(musicT/7.0)*1.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  - (8.0 + 5.25/7.0)*8.0)*4.0;

    if(segBass>0.0) {
        UV = fract(UV*(timeBass-0.0)+0.5)*2.0-1.0;
    }

    vec2 proj = UV*rot(-0.2)*0.1;
    proj *= (5.0-deltaKick+length(UV));
    proj.x += timeSnare;

    vec2 i_proj = floor(proj*2.0),
         f_proj = fract(proj*2.0);
    
    seed = uint(67461.+i_proj.y*462.312+i_proj.x*95.2);
    col = mix(c_yellow, c_beige, truchet((f_proj*2.0-1.0)*rot(round(hash_f())*PI)));

    vec3 c_pre_rm = col;
    vec3 rd=normalize(vec3(UV,1)), ro=vec3(0,0,-5), po=ro;
    float td, ld;
    for (int i=0; i<99; i++) {
        po = ro+rd*td;

        vec3 p = po-vec3(0,0,2);
        p.zy *= rot(timeKick*PI/2.0);
        p.xz *= rot(timeSnare*PI/2.0);

        vec2 b = box(p);

        ld = b.x-2.85-deltaSnare*0.4;

        if (ld < 0.25*(1.0-clamp(segTruchetGone*12.0,0.0,1.0))) {
            col = c_red;
        }
        if (ld < 0.015) {
            vec2 p = UV*td;
            float off2;
            if (b.y > 2.5) {
                p *= 2.0;
            }
            if (b.y > 4.5) {
                vec3 q = quadtree(p/12.0+0.5, 0.0);
                p = q.xy*2.0-1.0; p*=1.5;
                off2 = floor(q.z*7.0);
            }

            if (getText(p*0.2, vec2(b.y,off2), vec2(7))) {
                col = c_blue;
            }
            else {
                col = c_pre_rm;
            }
            break;
        }
        if (td > 999.) {
            break;
        }

        td += ld*0.5;
    }

    C = vec4(col, 1.0);
}
