in vec2 uv;

out vec4 C;

uniform float u_t;
uniform float u_sparkle_activeness;
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;
}

float map(vec2 p) {
    float t = u_t/BEAT_DUR;

    float width = 0.125;

    vec2 i_p = floor(p*2.0),
         f_p = fract(p*2.0)*2.0-1.0;

    seed = (uint)(i_p.y+i_p.x*35243.124)+532u;
    float r = hash_f()*10.0+10.0*(1.0-u_sparkle_activeness);
    vec2 r2 = vec2(hash_f(), hash_f());
    vec2 r3 = vec2(hash_f(), hash_f()); //only for roll 2
    
    if (fract(r)<0.5) {
        f_p*=rot(PI/2.0);
    }

    float roll = step(1.0-u_sparkle_activeness,sin(p.x+p.y*sign(r2.y-0.5)+t*sign(r2.x-0.5)));
    if (r<2.0) {
        return step(abs(f_p.y),width)*roll;
    }
    else if (r<4.0) {
        float roll2 = step(1.0-u_sparkle_activeness,sin(p.x+p.y*sign(r3.y-0.5)+t*sign(r3.x-0.5)));
        return min(1.0, step(abs(f_p.y),width)*roll + step(abs(f_p.x),width)*step(0.3,abs(f_p.y))*roll2);
    }
    else if (r<6.0) {
        return step(abs(length(f_p-1.0)-1.0),width)*roll;
    }
    else if (r<8.0) {
        return step(abs(length(f_p+1.0)-1.0),width)*roll;
    }
    
    return 0.0;
}

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 = 1.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;
}

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

    float typo1 = t/7.0/4.0 - 4.0 - 0.75/7.0;
    float typo2 = t/7.0/4.0 - 4.0 - 3.5/7.0;
    float typo3 = t/7.0/4.0 - 4.0 - 4.25/7.0;
    float typo4 = t/7.0/4.0 - 4.0 - 5.1/7.0;
    float typo5 = t/7.0/4.0 - 4.0 - 5.75/7.0;
    float typo6 = t/7.0/4.0 - 5.0;
    float typo7 = t/7.0/4.0 - 5.0 - 0.75/7.0;
    float typo8 = t/7.0/4.0 - 5.0 - 1.75/7.0;
    float typo9 = t/7.0/4.0 - 5.0 - 3.5/7.0;
    float typo10= t/7.0/4.0 - 5.0 - 4.25/7.0;

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

    // camera shake
    {
        float shakeAmount;
        shakeAmount += step(0.0, typo1)*(1.0-expease(typo1, 96.0));
        shakeAmount += step(0.0, typo3)*(1.0-expease(typo3, 96.0));
        shakeAmount += step(0.0, typo7)*(1.0-expease(typo7, 96.0));
        shakeAmount += step(0.0, typo10)*(1.0-expease(typo10, 96.0));
        UV*=rot(sin(u_t*99.9)*shakeAmount*0.05);
    }

    vec2 uv_rot = UV*rot(0.1)+vec2(u_t,0.0);
    if (typo7>0.0) {
        uv_rot = mix(
            uv_rot, UV*0.5*rot(-0.7)+vec2(u_t,0.0),
            expease(clamp(typo7*12.0, 0.0, 1.0), 4.0)
        );
    }

    float prog = t/7.0/4.0-3.0; prog = clamp(prog, 0.0, 1.0); prog = sinease(prog);
    vec3 bg2 = c_blue;
    bg2 = mix(bg2, c_pink, step(0.0,typo5));
    bg2 = mix(bg2, c_beige, step(0.0,typo8));
    vec3 col = mix(mix(c_yellow, bg2, step(length(UV),pow(prog,0.8)*2.1
        +deltaKick*((sin(atan(UV.y,UV.x)*5.0-timeKick*4.0)*0.5+0.5)*0.2*min(prog,1.0)+0.2*min(prog,1.0))
        )), c_red, map(uv_rot));
    
    if (typo1>0.0 && typo2<0.0) {
        vec2 p = UV;
        p *= mix(0.1,1.0,expease(typo1, 64.0));
        p *= mix(1.0,0.7,typo1);
        if ( getText(p, vec2(0.0), vec2(3.0,1.0)) ) col = c_pink;
    }
    if (typo2>0.0 && typo3<0.0) {
        float r = fract(sin(sin(u_t*99.99)*99.99));
        if ( getText(UV*mat2(1.0,-r*3.0,0.0,1.0), vec2(0.0,1.0), vec2(3.0,1.0)) ) col = c_pink;
    }
    if (typo3>0.0 && typo4<0.0) {
        vec2 p = UV*mix(1.0,0.2,typo3);
        if ( max(abs(p.x/3.0), abs(p.y))<0.5 ) col = c_pink;
        if ( getText(UV, vec2(0.0,2.0), vec2(3.0,1.0)) ) col = c_blue;
    }
    if (typo4>0.0 && typo7<0.0) {
        vec2 p = melt(UV, typo4);
        if ( max(abs(p.x/3.0), abs(p.y))<0.5 ) col = c_red;
        if ( getText(p, vec2(0.0,3.0), vec2(3.0,1.0)) ) col = c_yellow;
    }
    if (typo6>0.0 && typo7<0.0) {
        float r = fract(sin(sin(u_t*99.99)*99.99));
        if ( getText(fract(UV*mat2(1.0,-r*3.0,0.0,1.0))*4.0, vec2(0.0,0.0), vec2(8.0,8.0)) ) col = c_blue;
    }
    if (typo7>0.0 && typo9<0.0) {
        seed = (uint)(U.y+U.x*31373.124)+601u;
        if ( getText(UV*1.2+typo7*pow(hash_f(),2.0)*2.0, vec2(2.0,5.0), vec2(4.0,1.0)) ) col = c_blue;
    }
    if (typo9>0.0 && typo10<0.0) {
        float r = fract(sin(sin(u_t*99.99)*99.99));
        vec2 p = fracture(UV, r*(1.0-expease(typo9,48.0))*0.1);
        if ( getText(p*0.6, vec2(2.0,6.0), vec2(2.0,1.0)) ) col = c_blue;
    }
    if (typo10>0.0) {
        vec2 p = UV;
        p *= mix(0.1,1.0,expease(typo10, 64.0));
        p *= mix(1.0,0.7,typo10);
        if ( getText(p*0.6, vec2(2.0,7.0), vec2(2.0,1.0)) ) col = c_blue;
    }

    C = vec4(col, 1.0);
}
