#pragma once

#include "ofMain.h"
#include "ofxFXObject.h"

class ofxTuringPattern_A : public ofxFXObject {
public:

	ofxTuringPattern_A() {
		passes = 1;
		internalFormat = GL_RGBA32F;
		fragmentShader = STRINGIFY(
			uniform float     time;           // shader playback time (in seconds)
			uniform vec3      mouse;
			uniform vec2      resolution;           // viewport resolution (in pixels)

			vec3 func1(vec2 uv, float t, vec2 screen_uv) {
				float e = 1.0;
				for (float i = 0.; i < 5.; i += 0.6) {
					float d1 = (distance(cos(uv.x + i + t*0.01)*100.1, tan(uv.y + i + t*0.01)*100.1));
					float d2 = (distance(cos(uv.y + i + t*0.01)*100.1, tan(uv.x + i + t*0.01)*100.1 - t*0.1));
					e += cos(distance(i + d1, i + d2))*e;
				}
				vec3 cv = vec3(e - t*0.02, e / 2. - t*0.003-cos(time+e)*0.01, e / 3. + t*0.005);
				//return pow(cv, vec3((0.5-(0.5-screen_uv.y))));
				return cv;
			}

			vec3 func2(vec2 uv, float t, vec2 screen_uv) {
				float e = 1.0;
				uv.y -= time*0.00005;
				screen_uv.y += time*0.00005;
				for (float i = 0.; i < 5.; i += 0.6) {
					float d1 = (distance(cos(uv.x + i + t*0.01)*100.1, tan(uv.y + i + t*0.01)*100.1));
					float d2 = (distance(cos(uv.y + i + t*0.01)*100.1, tan(uv.x + i + t*0.01)*100.1 - t*0.1));
					e += cos(distance(i + d1, i + d2))*e;
					uv.y += d2*(0.000001*time*0.01 - d1*0.000001);
				}
				vec3 cv = vec3(e - t*0.02, e / 2. - t*0.003 - cos(time + e)*0.01, e / 3. + t*0.005);
				//return pow(cv, vec3((0.5-(0.5-screen_uv.y))));
				return cv;
			}

			void main()
			{
				vec2 uv = gl_FragCoord.xy / resolution.xy;

				vec2 screen_uv = uv;
				vec3 c = vec3(0.0);
				float tt = 1.0;
				if (uv.y > 0.5*tt) { uv.y = 1.0 - uv.y*tt; }
				if (uv.x > 0.5*tt) { uv.x = 1.0 - uv.x*tt; }

				c.rgb += func1(uv*(0.0001 + tan(time*0.001)), time*1.4, screen_uv)*0.5;
				c.rgb += func2(uv*(0.0001 + tan(time*0.001)), time*0.4, screen_uv)*0.2;
				for (int i = 0; i < 5; i++)
					c.rgb -= func1(uv*(0.001 + (time*0.01 + float(i)*uv.y*0.0001 + time*0.001)), time*0.04, screen_uv)*cos(float(i)*0.9 + time*0.1)*0.01;

				//c.rgb = vec3(0.5-(0.5-screen_uv.y));


				if (screen_uv.y < 0.5) {
					float v = -0.5 + (smoothstep(0.0, 2.0, pow((0.6 - (0.5 - screen_uv.y))*1.5, 2.0)));
					c.rgb -= v;
					float adhoc = clamp(pow((0.3 - (0.5 - screen_uv.y))*2.0, 2.7), 0.01, 1.0);
					c.rgb = mix(vec3(0, 0, 0.1 + time*0.004), c.rgb, adhoc);
				}
				gl_FragColor = vec4(clamp(c, 0.0, 3.0), 1.0);
			});

	};
	void update(float time) {

		shader.setUniform1f("time", time);
		shader.setUniform2f("resolution", (float)width, (float)height);
		shader.setUniform2f("mouse", (float)ofGetMouseX() / width, (float)ofGetMouseY() / height);
	};

};

