/**
 * @author Zachary Johnson http://www.zachstronaut.com/ @zacharyjohnson
 */
 
/**
 *
 * This filter applies a glitch effect
 * @class GlitchFilter
 * @contructor
 */
PIXI.GlitchFilter = function()
{
	PIXI.AbstractFilter.call( this );
 
	this.passes = [this];
 
	// set the uniforms
	this.uniforms = {
		// invert: {type: '1f', value: 0},
		// dimensions: {type: '4fv', value:new Float32Array([10000, 100, 10, 10])},
		pixelSize: {type: '2f', value:{x:10, y:10}},
		blocks: {type: '1fv', value: new Float32Array([511, 512, 513, 514, 515, 516, 517, 411, 412, 413, 414, 294, 416, 417])},
		effects: {type: '1fv', value: new Float32Array([1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7])},
		rw: {type: '1f', value: (240 * 4) / (8 * 4)}, // eg 30
		rh: {type: '1f', value: (160 * 4) / (8 * 4)},
		bw: {type: '1f', value: 1 / ((240 * 4) / (8 * 4))}, // eg 1.0/30
		bh: {type: '1f', value: 1 / ((160 * 4) / (8 * 4))}
	};

	this.fragmentSrc = (function(){/*
		precision mediump float;
		varying vec2 vTextureCoord;
		uniform sampler2D uSampler;
		// varying vec4 vColor;
		// uniform vec2 testDim;
		// uniform vec4 dimensions;
		// uniform vec2 pixelSize;
		uniform float blocks[14];
		uniform float effects[14];
		uniform float bw;
		uniform float bh;
		uniform float rw;
		uniform float rh;

		vec4 apply_effect(float effect) {
			vec2 uv = vTextureCoord;// gl_FragCoord.xy / iResolution.xy;
			vec2 p = uv;
			// float offset = 0.2;
			vec4 color;
			vec4 color2;
			float color_val;

			// Some other ideas:
			// 	- fill an entire row with a color
			//	- fill a block with noise
			
			// Scramble in row
			if (effect == 7.0) {	
				float line = floor(8.0 * fract(uv.y * rh));

				p.x += line * (bw / 8.0);
				
				color = texture2D(uSampler, p);

				
				
			// Fill lines
			} else if (effect == 6.0) {	
				float line = fract(uv.y * rh * 4.0); // same as: float line = fract((uv.y * 160.0) / 2.0);
				
				if (line < 0.5) {
					color = vec4(0.8, 0.0, 0.8, 1.0);
				} else {
					// color = texture2D(uSampler, p);
					color = vec4(0.0, 0.0, 0.0, 0.0);
				}
				
				
				
			// Smear lines
			} else if (effect == 5.0) {
				// // Shuffle Lines
				// float line = fract(uv.y * rh * 4.0);
				// if (line < 0.5) {
				// 	p.y += bh / 8.0;
				// 	color = color2 = texture2D(uSampler, p);
				// 	// // And discolor alternating lines
				// 	// color.b = color2.g;
				// 	// color.g = color2.b;
				// } else {
				// 	p.y -= bh / 8.0;
				// 	color = texture2D(uSampler, p);
				// }

				p.x = floor(uv.x / bw) * bw - 0.001;
				color = texture2D(uSampler, p);

				
				
			// Offset lines
			} else if (effect == 4.0) {
				// // Lose color in a block
				// color = texture2D(uSampler, p);
				// color_val = max(max(color.r, color.g), color.b);
				// color.r = color_val;
				// color.g = color_val;
				// color.b = color_val;

				float line = fract(uv.y * rh * 4.0);
				if (line < 0.5) {
					p.x += 2.0 * (bw / 8.0);
					color = color2 = texture2D(uSampler, p);
				} else {
					color = texture2D(uSampler, p);
				}

				
			// Fill a block
			} else if (effect == 3.0) {
				color = vec4(0.8, 0.0, 0.8, 1.0);
			
				
				
			// Displace a block
			} else if (effect == 2.0) {
				p.x += 4.0 * bw;
				p.y += 2.0 * bh;
				color = texture2D(uSampler, p);
			
			// Empty displaced block
			} else if (effect == 1.0) {
				color = vec4(0.0, 0.0, 0.0, 0.0);
				
			
				
			// Normal
			} else {
				color = texture2D(uSampler, p);
			}

			return color;
		}

		float get_effect(float block) {
			vec2 uv = vTextureCoord;
			float effect = 0.0;

			/// TODO: could maybe create a function that yields a result between 1 and 7 using fract for any block b to make this totally programmatic without an if or for loop... but then blocks would always get the same effect every time they are glitched though
			for (int i = 0; i < 14; i++) {
				if (blocks[i] == block) {
					effect = effects[i];
				}
			}

			return effect;
		}

		float get_block() {
			vec2 uv = vTextureCoord;
			float block = floor(uv.x / bw) + floor(uv.y / bh) * rw;

			return block;
		}

		void main(void) {
			float block = get_block();

			float effect = get_effect(block);

			gl_FragColor = apply_effect(effect);
		}
	*/}).toString().match(/\/\*!?(?:\@preserve)?\s*(?:\r\n|\n)([\s\S]*?)(?:\r\n|\n)\s*\*\//)[1].split("\n");
};
 
PIXI.GlitchFilter.prototype = Object.create( PIXI.AbstractFilter.prototype );
PIXI.GlitchFilter.prototype.constructor = PIXI.GlitchFilter;
 

Object.defineProperty(PIXI.GlitchFilter.prototype, 'blocks', {
	get: function() {
		return this.uniforms.blocks.value;
	},
	set: function(value) {
		this.dirty = true;
		this.uniforms.blocks.value = value;
	}
});

Object.defineProperty(PIXI.GlitchFilter.prototype, 'effects', {
	get: function() {
		return this.uniforms.effects.value;
	},
	set: function(value) {
		this.dirty = true;
		this.uniforms.effects.value = value;
	}
});