from shortcrust.shader import ShaderProgram
from shortcrust.mesh import Mesh
from shortcrust.gl2 import *
from shortcrust.texture import Texture
from shortcrust.matrix import glmatrix


class LyricsShader(ShaderProgram):
	vertex_shader = """
		attribute vec4 vPosition;
		varying vec4 texPosition;

		uniform float lyricLine;
		uniform mat4 view;
		void main()
		{
			texPosition = (vPosition + vec4(1.0, 1.0 - lyricLine / 2.0, 0.0, 0.0)) / 2.0;
			gl_Position = view * vPosition + vec4(0.0, 0.1, 0.0, 0.0);
		}
	"""

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

		uniform sampler2D uSampler;
		varying vec4 texPosition;

		void main()
		{
			vec4 texture_pix = texture2D(uSampler, texPosition.xy);
			gl_FragColor = texture_pix;
		}
	"""

	def __init__(self):
		check_gl_error()
		super(LyricsShader, self).__init__()
		check_gl_error()
		self.vertex_position_attr = glGetAttribLocation(self.program_object, 'vPosition')
		check_gl_error()
		self.sampler_unif = glGetUniformLocation(self.program_object, 'uSampler')
		check_gl_error()
		self.line_unif = glGetUniformLocation(self.program_object, 'lyricLine')
		check_gl_error()
		self.view_unif = glGetUniformLocation(self.program_object, 'view')
		check_gl_error()


class LyricsMesh(Mesh):
	mode = GL_TRIANGLE_STRIP
	vertices = [
		(-1.0, 0.5, -0.97),
		(-1.0, 1.0, -0.97),
		(1.0, 0.5, -0.97),
		(1.0, 1.0, -0.97),
	]


lyric_sequence = [3, 3, 0, 0, 0, 0, 3, 1, 1, 3, 0, 0, 0, 0, 3, 2, 2, 3, 0, 0, 0]

view_matrix = [
	[0.8, 0, 0, 0],
	[0, 0.8, 0, 0],
	[0, 0, 1, 0],
	[0, 0, 0, 1]
]


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

		self.shader = LyricsShader()
		self.mesh = LyricsMesh()
		self.texture = Texture('data/lyrics.png', transparency=True)

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

		beat = int(time / self.app.beat_length)
		if beat < len(lyric_sequence):
			check_gl_error()
			self.texture.activate(GL_TEXTURE2)
			glUniform1f(self.shader.line_unif, lyric_sequence[beat])
			glUniform1i(self.shader.sampler_unif, 2)
			check_gl_error()
			glUniformMatrix4fv(self.shader.view_unif, 16, GL_FALSE, glmatrix(view_matrix))
			check_gl_error()

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