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, mul
import math


class RingShader(ShaderProgram):
	vertex_shader = """
		attribute vec4 vPosition;
		varying vec4 texPosition;
		uniform float ampl;
		uniform float rota;
		uniform float ord;

		const mat4 view = mat4(
			1.0 * 0.4, 0, 0, 0,
			0, 1.333 * 0.4, 0, 0,
			0, 0, 1, 0,
			0, 0, 0, 1
		);

		void main()
		{
			mat4 translateMatrix = mat4(
				1, 0, 0, 0,
				0, 1, 0, 0,
				0, 0, 1, 0,
				ampl * cos(rota), ampl * sin(rota), ord * -0.01, 1
			);
			texPosition = vPosition + vec4(0.5, 0.5, 0.0, 0.0);
			gl_Position = translateMatrix * view * vPosition;
		}
	"""

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

		uniform sampler2D uSampler;
		varying vec4 texPosition;

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

	def __init__(self):
		check_gl_error()
		super(RingShader, self).__init__()
		check_gl_error()
		self.vertex_position_attr = glGetAttribLocation(self.program_object, 'vPosition')
		check_gl_error()
		self.ampl_unif = glGetUniformLocation(self.program_object, 'ampl')
		check_gl_error()
		self.rota_unif = glGetUniformLocation(self.program_object, 'rota')
		check_gl_error()
		self.ord_unif = glGetUniformLocation(self.program_object, 'ord')
		check_gl_error()
		self.sampler_unif = glGetUniformLocation(self.program_object, 'uSampler')
		check_gl_error()


class RingMesh(Mesh):
	mode = GL_TRIANGLE_STRIP

	def __init__(self, z=0.8):
		self.vertices = [
			(-0.5, -0.5, z),
			(-0.5, 0.5, z),
			(0.5, -0.5, z),
			(0.5, 0.5, z),
		]
		super(RingMesh, self).__init__()


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

		self.shader = RingShader()
		self.mesh = RingMesh()
		self.texture = Texture('data/avocado.png', transparency=True)

	def draw(self, time):
		beat = time / self.app.beat_length

		self.shader.use()
		check_gl_error()

		self.texture.activate(GL_TEXTURE1)
		glUniform1i(self.shader.sampler_unif, 1)
		check_gl_error()

		base_rota = beat * math.pi / 8
		ampl = math.sin(beat * math.pi * 0.125)
		glUniform1f(self.shader.ampl_unif, ampl)
		check_gl_error()

		for i in range(8):
			rota = base_rota + i * math.pi / 4
			glUniform1f(self.shader.rota_unif, rota)
			check_gl_error()
			glUniform1f(self.shader.ord_unif, i)
			check_gl_error()

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