from shortcrust.shader import ShaderProgram
from shortcrust.mesh import Mesh
from shortcrust.gl2 import *


class BackgroundShader(ShaderProgram):
	vertex_shader = """
		attribute vec4 vPosition;
		void main()
		{
			gl_Position = vPosition;
		}
	"""

	fragment_shader = """
		/* precision mediump float; */

		const float PI = 3.1415926536;

		const float TWISTER_CENTRE_X = 0.0;
		const float TWISTER_CENTRE_Y = -0.1;
		const float BEAT_LEN = 60.0 / 95.0;

		uniform float time;
		uniform vec2 resolution;

		void main()
		{
			/* screen position, scaled to -0.5..0.5 horizontally, origin in centre */
			vec2 position = (gl_FragCoord.xy - resolution / 2.0) / resolution.xx;

			float beat = time / BEAT_LEN;

			/* angle of rotation */
			float a = atan(position.y - TWISTER_CENTRE_Y, position.x - TWISTER_CENTRE_X) / PI;

			/* swaying bg: */
			float r = length(position);
			float a_twisty = a + sin(-r * 1.3 + fract(beat / 8.0) * 2.0 * PI) * 0.3;

			/* constant rotating bg */
			float a_straight = a + mod(beat / 8.0, PI/0.4);

			gl_FragColor = fract(a_twisty * 4.0) > 0.5 ?
				vec4(0.605, 0.776, 0.616, 1.0) :
				vec4(0.996, 0.765, 0.741, 1.0);

			/* initial fadein */
			gl_FragColor = mix(
				vec4(1.0, 1.0, 1.0, 1.0), /* solid white */
				gl_FragColor,
				smoothstep(0.0, 4.0, beat)
			);
		}
	"""

	def __init__(self):
		check_gl_error()
		super(BackgroundShader, self).__init__()
		check_gl_error()
		self.vertex_position_attr = glGetAttribLocation(self.program_object, 'vPosition')
		check_gl_error()
		self.time_unif = glGetUniformLocation(self.program_object, 'time')
		check_gl_error()
		self.resolution_unif = glGetUniformLocation(self.program_object, 'resolution')
		check_gl_error()


class BackgroundMesh(Mesh):
	mode = GL_TRIANGLE_STRIP
	vertices = [
		(-1.0, -1.0, 0.9),
		(-1.0, 1.0, 0.9),
		(1.0, -1.0, 0.9),
		(1.0, 1.0, 0.9),
	]


class BackgroundLayer(object):
	def __init__(self, app):
		self.app = app

		self.shader = BackgroundShader()
		self.background_mesh = BackgroundMesh()
		#self.background_mesh = ToastMesh()

		# why oh why does the buffered approach not work? :-(
		# (page 13, OpenGL Shading Language)
		#buffers = glGenBuffers(1)
		#print "buffers:"
		#print repr(buffers)
		#self.bg_vertex_position_buffer = glGenBuffers(1)
		#glBindBuffer(GL_ARRAY_BUFFER, self.bg_vertex_position_buffer)
		#glBufferData(GL_ARRAY_BUFFER, bg_vertices, GL_STATIC_DRAW)

	def draw(self, time):
		self.shader.use()

		glUniform1f(self.shader.time_unif, time)
		glUniform2f(self.shader.resolution_unif, self.app.width, self.app.height)

		self.background_mesh.draw(self.shader.vertex_position_attr)
