in vec2 uv;

out vec4 C;

const float SPLIT_GATE = 0.6;

uniform float u_t;
uniform int tex_typo;
uniform float u_wave_amp;
uniform float u_wave_orig;

#include scene_jyrevis25/common.glsl

const int GREETZ[17*19] = {
    _G, _O, _O, _S, _E, -1, _G, _O, _O, _S, _I, _N, _G, _T, _O, _N, -1,
    _T, _O, _T, _E, _T, _M, _A, _T, _T, -1, _D, _E, _S, _I, _R, _E, -1,
    _W, _R, _I, _G, _H, _T, _E, _R, -1, _S, _P, _4, _G, _H, _E, _T, -1,
    _M, _E, _D, -1, _C, _P, _D, _T, -1, _J, _A, _Y, -1, _Y, _U, _E, -1,
    _L, _Y, _N, _N, -1, _M, _O, _C, _O, _O, -1, _S, _H, _H, _R, _A, -1,

    _R, _A, _C, _C, _O, _O, _N, -1, -1, _V, _I, _O, _L, _E, _T, -1, -1,
    _N, _U, _S, _A, _N, -1, _Y, _X, -1, _E, _V, _V, _V, _V, _I, _L, -1,
    _D, _J, _H, _O, _M, _E, _R, -1, _P, _S, _E, _N, _O, _U, _G, _H, -1,
    _0, _B, _5, _V, _R, -1, _L, _I, _M, _P, -1, _N, _I, _N, _J, _A, -1,
    _K, _I, _N, _A, _N, _K, _O, _M, _O, _T, _I, -1, _O, _H, _L, _I, -1,

    _R, _E, _N, _A, _R, _D, -1, -1, _G, _A, _M, _0, _0, _2, _2, -1, -1,
    _U, _K, _O, _N, _P, _O, _W, _E, _R, -1, _S, _L, _E, _R, _P, _Y, -1,
    _K, _A, _M, _O, _S, _H, _I, _K, _A, -1, _0, _X, _4, _0, _1, _5, -1,
    _J, _E, _E, _N, _I, _O, -1, _A, _N, _T, _I, _C, _O, _R, _E, -1, -1,
    _B, _A, _L, _I, _N, _T, -1, _V, _I, _K, _T, _O, _R, -1, _K, _B, -1,

    _D, _A, _R, _Y, _A, -1, _Z, _A, _V, _I, _E, -1, _H, _U, _G, _O, -1,
    _M, _A, _N, _U, _E, _L, -1, -1, _A, _L, _K, _A, _M, _A, -1, -1, -1,
    _P, _O, _R, _O, _C, _Y, _O, _N, -1, _A, _L, _D, _R, _O, _I, _D, -1,
    _G, _A, _R, _G, _A, _J, -1, -1, _N, _0, _4, -1, -1, _L, _J, -1, -1,
};
// goose goosible goosington, 
// totetmatt, desire, 
// wrighter, sp4ghet, 
// med, cpdt, jay, yue, 
// lynn, mocoo, shhra, 
// raccoon violet, 
// NuSan, yx, evvvvil,
// dj homer, psenough, 
// 0b5vr, limp ninja, 
// kinankomoti, OhLi, 
// renard, gam0022, 
// ukonpower, slerpy, 
// kamoshika, 0x4015, 
// jeenio, anticore, 
// balint, viktor, kb, 
// darya, zavie, hugo, 
// manuel, alkama, 
// porocyon, aldroid
// gargaj, n04, LJ

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;
    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(0.0,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(0.0,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;
}

float waveGate(vec2 i_p) {
    return step(i_p.x+i_p.y,0.0);
}

vec2 wave(vec2 p) {
    const float FREQ = 3.0;
    float musicT = u_t/BEAT_DUR;
    float segEnd = musicT/7.0/4.0 - 13.0;

    p *= rot(-PI/4.0);
    p *= 2.0;

    vec2 i_p = floor(p),
         f_p = fract(p);
    
    vec3 show = vec3(
        waveGate(i_p+vec2(1,0)),
        waveGate(i_p+vec2(0,1)),
        waveGate(i_p)
    );
    
    float yellownize = pow(clamp(max(0.0,segEnd)*1.1,0.0,1.0),0.9);
    float val = -1.0;
    if (length(f_p-vec2(1,0))<1.0 && show.x>0.5) {
        val = step(0.0-yellownize, sin(length(f_p-vec2(1,0))*FREQ*TAU));
    }
    if (length(f_p-vec2(0,1))<1.0 && show.y>0.5) {
        val = step(0.0-yellownize, sin(length(f_p-vec2(0,1))*FREQ*TAU));
    }
    if (length(f_p)<1.0 && show.z>0.5) {
        val = step(0.0-yellownize, sin(length(f_p)*FREQ*TAU));
    }
    return vec2(1.0-val, step(0.015, abs(val+1.0)));
}

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

    vec3 col = c_beige;

    float musicT = u_t/BEAT_DUR;

    float segStart = musicT/7.0/4.0 - 10.0;

    float timeSpark;
    for(float i=0.0; i<7.0; i+=0.5){ timeSpark += expease(max(0.0,fract(musicT/7.0)*7.0-i),6.0); }
    float deltaSpark;
    for(float i=0.0; i<7.0; i+=0.5){ deltaSpark += step(i,fract(musicT/7.0)*7.0); }
    deltaSpark -= timeSpark;
    timeSpark += floor(musicT/7.0)*9.0;

    // camera shake
    {
        float shakeAmount = step(0.0, segStart)*(1.0-expease(segStart, 280.0));
        UV.x+=sin(u_t*99.9)*shakeAmount*0.6;
    }

    col = mix(col, c_pink, map(UV*rot(-0.1)+vec2(u_t,0.0)));

    vec2 jpWave = wave(UV*rot(sin(u_t*3.0)*u_wave_amp*0.075)+vec2(u_t, sin(u_t*3.0)*u_wave_amp-u_wave_orig));
    col = mix(col, mix(c_yellow, c_beige, jpWave.x), jpWave.y);

    vec2 p = UV*(3.0+length(UV))*mix(1.0, 1.2, segStart);
    p += vec2(u_t*2.0, u_t*1.75);
    p *= rot(0.2*(1.0-pow(segStart*0.2,0.5)));
    vec2 i_uv = floor(p);
    
    seed = uint(i_uv.y*34.2+floor(musicT)*726.3+87764.46);
    float offcurr = floor(hash_f()*5.0);
    seed = uint(i_uv.y*34.2+floor(musicT+1.0)*726.3+87764.46);
    float offnext = floor(hash_f()*5.0);

    p += vec2(
        mix(offcurr, offnext, sinease(fract(musicT))), 
    0.0);
    i_uv = floor(p*vec2(1.5,1.0));
    vec2 f_uv = fract(p*vec2(1.5,1.0));

    int ch = GREETZ[int(i_uv.x)%17+(int(i_uv.y)/2%19)*17];
    if (int(i_uv.y)%2==0) {
        ch = -1;
    }
    if (ch >= 0) {
        col = mix(col, mix(c_blue, c_blue, jpWave.y), ascii(textures[tex_typo],
            (f_uv/vec2(1.5,1.0)*2.0-1.0)*mix(0.55, 1.3, 
                deltaSpark*step(0.0, sin(i_uv.x*24.0+i_uv.y*80.0+u_t*5.0)))*
                mix(99., 1., expease(segStart,mix(6.0,15.0,sin(i_uv.x)*0.5+0.5))), ch));
    }


    C = vec4(col, 1.0);
}
