#ifdef GL_ES
precision mediump float;
#endif


//https://www.shadertoy.com

#define time (iTime*.5)
#define mouse (u_mouse/iResolution)
#define resolution iResolution


const float e = 2.718281828459;
const float pi = 3.14159265359;
float sin01( in float angle ) { return .5 + .5*sin( angle ); }
float cos01( in float angle ) { return .5 + .5*cos( angle ); }
float cosft( in float from, in float to, in float val ) { return from + cos01( val )*(to - from); }
float sinft( in float from, in float to, in float val ) { return from + sin01( val )*(to - from); }

float RandFloat( int i ) { return (fract( sin( float( i ) ) * 43758.5453 )); }
int RandInt( int i ) { return int( 100000.0*RandFloat( i ) ); }

vec3 hsb2rgb( in vec3 c )
{
	vec3 rgb = clamp( abs( mod( c.x*6.0 + vec3( 0.0, 4.0, 2.0 ), 6.0 ) - 3.0 ) - 1.0, 0.0, 1.0 );
	rgb = rgb * rgb*(3.0 - 2.0*rgb);
	return c.z * mix( vec3( 1.0 ), rgb, c.y );
}

vec3 HsvToRgb( vec3 c )
{
    float s = c.y;
	float s_n = c.z - s * .5;
	return vec3( s_n ) + vec3( s ) * cos( 2.0 * pi * (c.x + vec3( 1.0, 0.6666, .3333 )) );
}

//####################
//[-1;+1]
float VFx_t( float x, float t,float id )
{
	//return cos(x+-1.780);
    float da = RandFloat(int(id)) * 1.;
	float amplitude = 1.;
	float frequency = 1.;
	float y = sin( x * frequency );
	float t_t = 0.01*(-t * 130.0);
	y += sin( x*frequency*(2.1+da) + t_t )*4.5;
	y += sin( x*frequency*(1.72+da) + t_t * 1.121 )*4.0;
	y += sin( x*frequency*(2.221+da) + t_t * 0.437 )*5.0;
	y += sin( x*frequency*(3.1122+da) + t_t * 4.269 )*2.5;
	y *= amplitude * 0.06;
	return y;
}

float VFx_t01( float x, float t, float id){ return .5 + .5*VFx_t( x, t, id );}

float Fx( float x, vec2 scale )
{

    const float d_sig = 5.;
    float sc_y = scale.y/d_sig;
	float ret = smoothstep( -scale.x, 0., x ) - smoothstep( .0, +scale.x, x );

	ret *= sc_y;
	float sig = sign( sc_y );
	ret = smoothstep( .0, sig * d_sig, ret - sig ) * sc_y;
	return ret;
}

//#undef time
//#define time (10.*1.936)

//#define TEST_ONCE_4_CONSTANT_EYES
#ifndef TEST_ONCE_4_CONSTANT_EYES

#define COUNT_L 15

const float max_w = 0.5 / float( COUNT_L );

const vec2 scale = vec2( .1, 2. )*5.;
const vec2 d_uv = vec2( 0., -.3 );
#else
#define COUNT_L 8

const float max_w = .000025 / float( COUNT_L );

const vec2 scale = vec2( .1, 2. )*3.;
const vec2 d_uv = vec2(-0.150,-0.420);
#endif

vec3 color = vec3( 0 );
//#define FUNC_VFX(id)	 ( max_w * (1. + VFx_t(id , time )) )
#define FUNC_VFX(id)	 ( max_w * (1. + VFx_t((id) + uv.y, uv.y - time, id )) )
struct Line
{
	float id;
	float id_2;

	float xs;
	float Vx;
	float c_pos;

	float eye_l;
	float eye_r;

	float eye_fl;
	float eye_fr;

	vec2 eye_pos; //todo delete x is always c_pos

	vec3 color_eye;

	vec2 scale_eye;
};

Line setLine(in Line line_in,in vec2 uv){
    Line line = line_in;
    line.xs = line.id / float( COUNT_L );
	line.id_2 = RandFloat( int(line.id) ) * 2.;
	line.Vx = FUNC_VFX( line.id_2 );
	line.c_pos = line.xs + line.Vx;
    return line;
}

Line setLine( in vec2 uv )
{
    Line line;
	line.id = floor( uv.x * float( COUNT_L ) );
    return setLine(line, uv);
}

Line setLine( in vec2 uv, in float id )
{
    Line line;
	line.id = id;
    return setLine(line, uv);
}

//____________________________________________________________
// https://www.shadertoy.com/view/MlXyWM
//original type
//const int recursionCount		= 8;	// how deep to recurse
float GetRecursionFade( int recursionCount, int r, float timePercent )
{
	if (r > recursionCount)
		return timePercent;

	// fade in and out recusion
	float rt = max( float( r ) - timePercent, 0.0 );
	float rc = float( recursionCount );
	return rt / rc;
}

vec3 CombinePixelColor( int recursionCount, vec3 color, float timePercent, int i, int r )
{
	vec3 myColor = vec3
	(
		mix( -0.1, 0.1, RandFloat( i + r ) ),
		mix( 0.0, 0.8, RandFloat( i + r + 100 ) ),
		mix( 0.0, 0.8, RandFloat( i + r + 200 ) )
	);

	// combine with my color
	float f = GetRecursionFade( recursionCount, r, timePercent );
	myColor.y = pow( myColor.y, 4.0 );
	myColor.z = pow( myColor.z, 4.0 );
	color += myColor * f;
	return color;
}

vec3 FinishPixel( vec3 color, vec2 uv )
{
	// color wander
	color.x += 0.02*time;
	return HsvToRgb( color );
}
//____________________________________________________________

bool get_eye( in Line line_in,out Line line, in vec2 uv )
{
#if 1
return false;
#else
    line = line_in;
    //скорость раскрытия
    //expansion speed
	//---
    const vec2 max_scale = vec2( (4.32), (6.680) );
	//line.scale_eye = vec2(max_scale.x,1.15) ;
	line.scale_eye = max_scale * 1.;

	float udid = RandFloat( int( line.id ) );
	//t = .94;
	//t= .89+.04*sinft(.0,1.,line.id+t);
	float t_time = time * .3;
	line.scale_eye *= sinft( .0, 1.3, t_time + udid * scale.y );
	//line.scale_eye *= sinft(.0,1., t_time+line.id*t*scale.y );

#ifdef TEST_ONCE
	//test open eye
	line.scale_eye = max_scale * clamp( 0.968, .0, 1. );
    line.scale_eye = max_scale * sinft(.9,1.2,time*2.);//0.936;
#endif

    // movement speed
	line.eye_pos.y = scale.y*(-1. + 3.*fract( .25*time*udid ));
	line.eye_pos.x = line.c_pos;

#ifdef TEST_ONCE
	//test pos eye
	line.eye_pos.y = 0.084;
#endif

	line.eye_fl = Fx( line.eye_pos.y - uv.y, -line.scale_eye );
	line.eye_fr = Fx( line.eye_pos.y - uv.y, line.scale_eye );

	//color += plot_Fy( pos_eye.x + fl ,color, uv);
	//color += plot_Fy( pos_eye.x + fr ,color, uv);
    //line itself (line.xs + line.Vx) + eye
	line.eye_l = line.c_pos + line.eye_fl;
	line.eye_r = line.c_pos + line.eye_fr;

	const float dw = .0001;
	float fill = smoothstep( line.eye_l, line.eye_l + dw, uv.x )
		- smoothstep( line.eye_r, line.eye_r + dw, uv.x );


	if (fill > .00001)
	{
        float t_l = smoothstep(line.eye_pos.x, line.eye_l, uv.x);
        float t_r = smoothstep(line.eye_pos.x, line.eye_r, uv.x);
        float to_dark_1 = pow(t_l + t_r, 2.9);


        float max_r = pow(Fx( line.eye_pos.y , line.scale_eye ) , .04);
        float to_dark_2 =
             //smoothstep(.0,
                            length( (line.eye_pos - uv) * line.scale_eye *vec2(2.,1.) / scale)// /max_r

                        //, max_r*.25)
            ;
#if 0
        //center positions
        float it = to_dark_2*10.;
        float ret = it - floor(it);
        line.color_eye = vec3(
        //to_dark_2
            ret
             //+
            //smoothstep(line.eye_r, line.eye_pos.x, uv.x)
        );

        //line.color_eye = plot_Fy(line.eye_pos.x ,line.color_eye ,uv);
        //line.color_eye = plot_Fx(line.eye_pos.y ,line.color_eye ,uv);

        //line.color_eye = plot_Fy(line.eye_l ,line.color_eye ,uv);
        //line.color_eye = plot_Fy(line.eye_r ,line.color_eye ,uv);
        return true;
#endif


        //__________________________________________________________________________________________
        //first option
	vec3 ret_col1 = vec3(to_dark_2);
#if 1
	{
        ret_col1 = hsb2rgb(
			vec3(
				RandFloat( int(
					to_dark_2*30. + line.id_2*line.id + time * 10.
					) )
				,
				1., 1.-to_dark_1
			) );
	}

#endif
//uv second)
vec3 ret_col2 = vec3(.0);
#if 1
	{
        float rand_id = RandFloat( int( line.id_2 ));
		float iterations = to_dark_2 * (25.*sinft( .5, 1., time ) + rand_id )+ time * -.5;
		float pct2 = iterations - floor( iterations );
		//_____
		const int recursionCount = 5;
		for (int r = 0; r <= recursionCount + 1; ++r)
			ret_col2 = CombinePixelColor( recursionCount, ret_col2, pct2, int( iterations + rand_id * time ), r );

		ret_col2.x += time * 1.5;
		ret_col2 = HsvToRgb( ret_col2 );
	}
#endif

        ret_col2 = mix(ret_col2,vec3(.0),to_dark_1);
		color = mix(
            ret_col1,
            ret_col2,
            //0.
            sinft(.0,1.,time*udid)
        );

        //color = vec3(to_dark_2);


#if 0 //type eye
		if (mod( line.id, 2. ) > .5)return true;
		vec2 tuv = line.eye_pos - uv;
		tuv *= line.scale_eye / scale;
		//tuv.y *= line.scale_eye.y / (scale.y*.25);

		float angle = atan( tuv.y, tuv.x ) + time * 5.;
		float r = length( tuv ) / line.scale_eye.x*2.5;


		float sign = mod( r, sinft( .5, 1.000,
									time*.5
		) ) >= 0.25 ? -1. : +1.;
		//sign = 1.;

		float it_sp = 100.*(-1.620 * sqrt( r ) + angle * (-.060 * sign));

		float sp = cos( it_sp );
		float sp_2 = sp;
		sp = sp > .5*r ? 1. : .0;

		//line.color_eye = vec3(sp);
		//line.color_eye = mix(vec3(sp), line.color_eye ,sinft(.0, 1., time*4.) );
		///*
		line.color_eye = mix(//hsb2rgb(vec3(sp,sp,to_dark)),
							  vec3( sp ),
							  hsb2rgb( vec3(
								  RandFloat( int(
									  sign*(r + time * .5)*10.
									  ) )
								  , 1., to_dark_2 ) ),

							  sinft( .0, 1.5, time ) * sp_2 * r );
		/**/



#endif
		return true;
		//line.color_eye = vec3(t_eye);
	}
    return false;
#endif
}




void mainImage( out vec4 fragColor, in vec2 fragCoord )
{

    // Normalized pixel coordinates (from 0 to 1)
    vec2 uv = fragCoord/iResolution.xy;

//###################################################

	uv.x *= resolution.x / resolution.y;

	uv += d_uv;
	uv *= scale;

	Line line_c = setLine( uv );
    Line line_l = setLine(uv, line_c.id - 1. );
	Line line_r = setLine(uv, line_c.id + 1. );
	float id2 = line_c.id;
	float t_s1 = line_c.c_pos;
	float t_s2 = line_r.c_pos;

    bool hasEye = get_eye( line_c,line_c, uv );
    color += line_c.color_eye;

	if (uv.x < line_c.c_pos)
	{//l - c
		id2 = line_l.id;
		t_s1 = line_l.c_pos;
		t_s2 = line_c.c_pos;

		hasEye = hasEye || get_eye(line_l, line_l, uv );

		color += line_l.color_eye;

		t_s1 += line_l.eye_fr;
		t_s2 += line_c.eye_fl;

	}
	else
	{
		// c - r
		hasEye = hasEye || get_eye(line_r, line_r, uv );

        color += line_r.color_eye;

		t_s1 += line_c.eye_fr;
		t_s2 += line_r.eye_fl;
	}


	float pct = smoothstep( t_s1, t_s2, uv.x );
	//color lines
    //pct - bw gradient from the center (transition saturation here)
	pct = pow( 1.760*pct*(1.0 - pct), 1.1 );//0.376 );
											//pct = 1.-pct;
											///______________________
                                            //gradient color type

    //first option
	vec3 ret_col1 = vec3(pct);
#if 1    // makes lines colored
	{
#define gen_col(val) VFx_t01( id2 + pct * uv.y + (val), (val) + uv.y + time + floor(pct*60.), id2)
		float r = gen_col( 0.450 );
		float g = gen_col( 1.3445 );
		float b = gen_col( 2.021 );
		ret_col1 += (vec3( r, g, b )*pct) / (-.25888) + pct;
		ret_col1 += hsb2rgb( vec3(
			RandFloat( int(
			(id2*10.0001 + pct * 3. + time * .1) / .1
				) ) + fract( time*.2 )
			, 1., pct ) );
	}

//second)
    vec3 ret_col2 = vec3(.0);
	{
        //bw gradient multiply it and move it over time
		//float iterations =  pct*10. + u_time*-.5;//original
		float iterations = pct * (100.*sinft( .5, 1., time ) + RandFloat( int( id2 ) )) + time * -.5;
		float pct2 = iterations - floor( iterations );
		//_____
		const int recursionCount = 5;
		for (int r = 0; r <= recursionCount + 1; ++r)
			ret_col2 = CombinePixelColor( recursionCount, ret_col2, pct2, int( iterations + id2 * time ), r );
		//original
		//new_color =  FinishPixel(new_color, uv);

		//color.x += 0.02*u_time;
		//return HsvToRgb(color);

		ret_col2.x += time * .5;
		ret_col2 = HsvToRgb( ret_col2 );
	}
    if(!hasEye){
		color = mix(ret_col1,ret_col2,sinft(.0,
                                            //3. * sinft(.125,1.,time)
                                            1.
                                            ,time));
        //color = vec3(pow(.5,1.-pct));
        //color =  ret_col2;
    }
    //else color = vec3(1.);

#else
    color = vec3(pct);
#endif

    fragColor = vec4(color,1.0);
}