from shortcrust.shader import ShaderProgram
from shortcrust.mesh import Mesh
from shortcrust.gl2 import *
from shortcrust.texture import Texture
from shortcrust.matrix import rotate_z, glmatrix, identity
import math


class RainbowShader(ShaderProgram):
	vertex_shader = """
		attribute vec4 vPosition;
		varying vec4 texPosition;
		uniform mat4 rotation;
		uniform mat4 view;
		void main()
		{
			texPosition = vPosition;
			gl_Position = view * rotation * vPosition;
		}
	"""

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

		const float PI = 3.1415926536;

		const float BEAT_LEN = 60.0 / 95.0;

		uniform sampler2D uSampler;
		varying vec4 texPosition;

		void main()
		{
			/* gl_FragColor = vec4(0.905, 0.776, 0.616, 1.0); */
			gl_FragColor = texture2D(uSampler, texPosition.xy);
		}
	"""

	def __init__(self):
		check_gl_error()
		super(RainbowShader, self).__init__()
		check_gl_error()
		self.vertex_position_attr = glGetAttribLocation(self.program_object, 'vPosition')
		check_gl_error()
		self.rotation_unif = glGetUniformLocation(self.program_object, 'rotation')
		check_gl_error()
		self.view_unif = glGetUniformLocation(self.program_object, 'view')
		check_gl_error()
		self.sampler_unif = glGetUniformLocation(self.program_object, 'uSampler')
		check_gl_error()


class RainbowMesh(Mesh):
	mode = GL_TRIANGLE_STRIP
	vertices = [
		(0.0, 0.0, -0.90),
		(0.0, 1.0, -0.90),
		(1.0, 0.0, -0.90),
		(1.0, 1.0, -0.90),
	]


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

		self.shader = RainbowShader()
		self.mesh = RainbowMesh()
		self.texture = Texture('data/rainbow.png', transparency=True)

		self.view_matrix = [
			[1, 0, 0, 0],
			[0, 1.333, 0, 0],
			[0, 0, 1, 0],
			[0, 0, 0, 1]
		]

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

		rota = rotate_z(time / self.app.beat_length * math.pi)

		glUniformMatrix4fv(self.shader.rotation_unif, 16, GL_FALSE, glmatrix(rota))
		glUniformMatrix4fv(self.shader.view_unif, 16, GL_FALSE, glmatrix(self.view_matrix))

		self.texture.activate(GL_TEXTURE0)
		glUniform1i(self.shader.sampler_unif, 0)
		check_gl_error()

		self.mesh.draw(self.shader.vertex_position_attr)
