#version 330 core

layout(location = 0, index = 0) out vec4 outcol;

uniform sampler2DRect tex0;
uniform vec4 tex0siz;

uniform sampler2D dancetex;

uniform vec4 fade;
uniform vec4 time_s;

uniform vec4 justcocio; //note: fade, fs, mirror, UNUSED
uniform vec4 parms0; //note: animidx, frameidx, beatits, animits
uniform vec4 parms1; //note: next0pos.x, next0pos.y, next0anim, next0its
uniform vec4 parms2; //note: next0frameidx, noiseoverlayits

// ======================

in vec2 texcoord0;

// ======================

float clamp01( float v )
{
	return clamp( v, 0.0, 1.0 );
}

float remap( float v, float i0, float i1, float o0, float o1 )
{
    return o0 + (o1-o0) * clamp( (v-i0)/(i1-i0), 0.0, 1.0 );
}

//note: uniform pdf rand [0;1[
vec3 hash33n(vec3 p)
{
	p  = fract(p * vec3(5.3987, 5.4421, 6.9371));
	p += dot(p.yzx, p.xyz  + vec3(21.5351, 14.3137, 15.3247));
	return fract(vec3(p.x * p.z * 95.4307, p.x * p.y * 97.5901, p.y * p.z * 93.8369));
}

vec3 luv( vec2 ssuv, vec2 pos, vec2 siz )
{
	float aspect = tex0siz.y/tex0siz.x;

	vec4 minmax;
	minmax.xy = pos;
	minmax.zw = minmax.xy + siz.xy * vec2( aspect, 1.0 );
	vec2 luv = vec2( remap( ssuv.x, minmax.x, minmax.z, 0.0, 1.0 ),
					 remap( ssuv.y, minmax.y, minmax.w, 0.0, 1.0 ) );

	bool valid = luv.x > 0 && luv.x < 1 &&
				 luv.y > 0 && luv.y < 1;
	float valid_f = valid ? 1.0 : 0.0;

	return vec3(luv, valid_f);
}

vec4 sample_dancetex( vec2 luv, int curanim, int curframe )
{

//	+---------------------------+
//	| AnST | AnF0 | AnF1 | AnF2?|
//	+---+---+---+---+---+---+---+
//	|...|...|...|...|...|...|...|
//	+---+---+---+---+---+---+---+
//	| A1ST | A1F0 | A1F1 | A1F2?|
//	+---+---+---+---+---+---+---+
//	| A0ST | A0F0 | A0F1 | A0F2?|
//	+---------------------------+

	const int NUM_TILES_X = 8;
	const int NUM_TILES_Y = 8;

	//note: this is the animated rect
	ivec2 coord_curtile = ivec2( curframe, curanim );
	vec2 curtile_mn = vec2(coord_curtile) / vec2(NUM_TILES_X, NUM_TILES_Y);
	vec2 curtile_sz = vec2(1,1) / vec2(NUM_TILES_X, NUM_TILES_Y);
	vec2 curtile_uv = curtile_mn + luv * curtile_sz;
	vec4 curtile_dance = texture( dancetex, curtile_uv );

	return curtile_dance;
}


vec4 just_cocio( vec2 ssuv )
{
	float aspect = tex0siz.y/tex0siz.x;

	//if ( abs(ssuv.x - 0.5/aspect) < 0.01 ) return vec4( 1,0, 0, 1 );

	const vec2 pos0 = vec2( 0.025, 0.05 );
	const vec2 siz0 = vec2(0.5, 0.5);
	vec2 siz0fs = vec2( 0.9, 0.9 );
	vec2 pos0fs = vec2( 0.5, 0.5 ) - 0.5*siz0fs*vec2(aspect,1);
	vec2 p0 = mix( pos0, pos0fs, justcocio.y);
	vec2 s0 = mix( siz0, siz0fs, justcocio.y);
	vec3 luv0 = luv( ssuv, p0, s0 );
	if ( luv0.z > 0.0 )
	{
		float animidx = parms0.x;
		float frameidx = parms0.y;
		float beatits = parms0.z;
		float animits = parms0.w;

		luv0.x = (justcocio.z>0.5) ? (1.0-luv0.x) : luv0.x;

		int curanim  = int( animidx + 0.5 );
		int curframe = int( frameidx + 0.5 ); //note: should be 1/2/3...
		vec4 curtile_dance = sample_dancetex( luv0.xy, curanim, curframe );

		vec4 retcol = vec4( curtile_dance.rgb, curtile_dance.a * animits );

		//note: outline, TODO: put into texture?	
		if ( luv0.x < 0.01 || luv0.x > 0.99 || luv0.y < 0.01 || luv0.y > 0.99 )
		{
			retcol = vec4(1,1,1,1);
		}

		retcol.a *= justcocio.x;

		retcol.rgb *= retcol.a;

		retcol.rgb += pow( remap( luv0.y, beatits, 0.0, 0.0, 1.0 ), 1.5 );

		return retcol;
	}

	vec2 next0pos = parms1.xy;
	//TODO: next0pos.y = abs(sin(0.5*3.1415*next0pos.y));
	int next0anim = int( parms1.z + 0.5 );
	int next0frame = int( parms2.x + 0.5 );
	float next0its = parms1.w;
	//const vec2 next0pos = vec2( 0.525, 0.05 ); //TODO: should bounce in?
	const vec2 next0siz = vec2(0.5, 0.5);
	vec3 luv1 = luv( ssuv, next0pos, next0siz );
	if ( luv1.z > 0.0 )
	{
		//const int next0anim = 0; //TODO: input
		//const int next0frame = 0; //note: always 0
		vec4 next0dance = sample_dancetex( luv1.xy, next0anim, next0frame );
		
		next0dance.a *= next0its;
		next0dance.a *= justcocio.x;

		next0dance.rgb *= next0dance.a;

		return next0dance;
	}

	 return vec4(0,0,0,0);
}

//note: [-1;1]
//note: honestly stolen from iq: https://www.shadertoy.com/view/Xsl3Dl
vec3 nhash33( vec3 p )
{
	p = vec3( dot(p,vec3(127.1,311.7, 74.7)),
			  dot(p,vec3(269.5,183.3,246.1)),
			  dot(p,vec3(113.5,271.9,124.6)));
	return fract(sin(p)*43758.5453123);
}
vec3 shash33( vec3 p )
{
    return -1.0+2.0*nhash33(p);
}

//note: [-1;1]
float sgnoise31( in vec3 p )
{
   vec3 i = floor( p );
   vec3 f = fract( p );

	vec3 u = f*f*(3.0-2.0*f);

   return mix( mix( mix( dot( shash33( i + vec3(0.0,0.0,0.0) ), f - vec3(0.0,0.0,0.0) ), 
                         dot( shash33( i + vec3(1.0,0.0,0.0) ), f - vec3(1.0,0.0,0.0) ), u.x),
                    mix( dot( shash33( i + vec3(0.0,1.0,0.0) ), f - vec3(0.0,1.0,0.0) ), 
                         dot( shash33( i + vec3(1.0,1.0,0.0) ), f - vec3(1.0,1.0,0.0) ), u.x), u.y),
               mix( mix( dot( shash33( i + vec3(0.0,0.0,1.0) ), f - vec3(0.0,0.0,1.0) ), 
                         dot( shash33( i + vec3(1.0,0.0,1.0) ), f - vec3(1.0,0.0,1.0) ), u.x),
                    mix( dot( shash33( i + vec3(0.0,1.0,1.0) ), f - vec3(0.0,1.0,1.0) ), 
                         dot( shash33( i + vec3(1.0,1.0,1.0) ), f - vec3(1.0,1.0,1.0) ), u.x), u.y), u.z );
}
float ngnoise31( in vec3 p )
{
	return 0.5 + 0.5 * sgnoise31( p );
}

float nfbm31( vec3 q )
{
    const mat3 m = mat3( 0.00,  0.80,  0.60,
                    -0.80,  0.36, -0.48,
                    -0.60, -0.48,  0.64 );

	float f = 0.0;
	f  = 0.5000*ngnoise31( q ); q = m*q*2.01;
	f += 0.2500*ngnoise31( q ); q = m*q*2.02;
	f += 0.1250*ngnoise31( q ); q = m*q*2.03;
	f += 0.0625*ngnoise31( q ); q = m*q*2.01;
	
	return f;
}

void main()
{
	vec2 ssuv = texcoord0;

	vec4 sample_col = texture( tex0, texcoord0*tex0siz.xy );

	float blendamount = parms2.y;
	//vec3 noise = vec3( 0.5 + 0.5 * cos( 20.0 * ssuv.x ) );
	float fbm = nfbm31( vec3(2.0*ssuv, 0.5*time_s.x) );
	fbm = remap( fbm, 0.2, 0.7, 0.0, 1.0 );
	fbm = pow( fbm, 2.0 );
	vec3 noise = vec3( fbm );
	sample_col.rgb = mix( sample_col.rgb, sample_col.rgb / (vec3(1.0f)-noise), blendamount );

	//outcol = vec4( noise, 1 ); return;

	float vignette_col;
	{
		float aspect = tex0siz.y/tex0siz.x;
		float l = length( (ssuv.xy - vec2(0.5, 0.5)) * vec2(1.0, aspect) );
		l = remap( l, 0.12, 0.575, 1.0, 0.0 );
		l = pow( l, 0.5 );
		vignette_col = l;
	}
	outcol = sample_col * vignette_col;
	outcol *= fade.xxxx;

	{
		vec4 dancecol = just_cocio( ssuv );
		outcol.rgb *= 1.0 - dancecol.a;
		outcol.rgb += dancecol.rgb;
		outcol.a += dancecol.a;
	}

	vec3 seed;
	seed.xy = ssuv.xy * vec2(81.0, 89.0);
	seed.z = time_s.x;
	vec3 rnd3 = hash33n( seed );
	outcol.rgb += (rnd3.xyz + rnd3.zxy - 1.0) / 255.0;
}
