EffectPulsing = Effect:new({r = 1, g = 1, b = 1, alpha_max = 0.1})

function EffectPulsing:setup()
	self.alpha = 0 -- self.alpha_max
	self.x = -0.5 * width()
	self.y = -0.5 * height()
	self.w = width()
	self.h = height()
	self.start_z = -1000
	self.sign_multiplier = 2
	self.camera_radius = 5
	self.points = {}
	self.lines_distance = 20
	self.tunnel_radius = 5
	self.lightning = 0
	
	
	self.camera = { x = 50, y = 0, z = 100, look_x = 0, look_y = 0, look_z = -100, up_x = 0, up_y = 1, up_z = 0, fov = 90, aspect_ratio = width() * 1.0 / height() }
		
end

function EffectPulsing:update (time)
	local elapsed = time - self.lastTimeUpdated
	local cam = self.camera
	
	local r = self.camera_radius
	
	--cam.x = r * math.sin(time)
	--cam.y = r * math.cos(time)	
	
	local t = time * self.sign_multiplier * 0.5
	local n
	n = #self.points
	local p
	p = self.points[n]
	
	cam.x = p.x + r * ( math.sin(t))
	cam.y = p.y + r * ( math.cos(math.pi + t)) -- r * math.cos(t) --r * ( math.cos(math.pi + t))
	cam.z = p.z + 0.5 * r * math.sin(t)
	--cam.look_x = cam.x
	--cam.look_y = cam.y
	
	cam.look_y = 0 -- self.camera.y
	cam.look_x = 0--self.camera.x --0 -- self.camera.x
	cam.look_z = p.z - 10
	
	camera(
		cam.x, cam.y, cam.z,
		cam.look_x, cam.look_y, cam.look_z,
		cam.up_x, cam.up_y, cam.up_z
	)
	perspective(cam.fov, cam.aspect_ratio, 1, 2000)	
	
		
	color(self.r, self.g, self.b, self.alpha)
	
	self.alpha = self.alpha - elapsed
	if self.alpha < 0 then
		self.alpha = 0
	end
	
	-- debug
	--drawAxis()

	blending(BLENDING_ADDITIVE)

	color(0, 0.5, 1, 0.3)	
	
	beginShape(SHAPE_LINES)
	lineh = 100
	linex = 30
	linez = self.start_z
	for i = 1, #self.points, 1 do
		vertex(linex, -lineh, linez)
		vertex(linex, lineh, linez)
		vertex(-linex, -lineh, linez)
		vertex(-linex, lineh, linez)
		linez = linez + 20
	end
	endShape()
	
	beginShape(SHAPE_QUADS)
	
		-- TODO rotaciones
		-- TODO quiza tb se podria hacer en 3D esta scene 
		for i = 1, #self.points, 1 do
			p = self.points[i]
			-- rectangle(p.x, p.y, p.s, p.s)
			
			vertex(p.x, p.y, p.z)
			vertex(p.x+ p.s, p.y, p.z)
			vertex(p.x + p.s, p.y+p.s, p.z)
			vertex(p.x, p.y + p.s, p.z)
	
		end
	endShape()
	
	
	local r2 = self.tunnel_radius
	local t2
	local phase = 0
	local repeats = 10
	local phase_inc = 2 * math.pi / repeats
	
	strokeWeight(1)
	
	for j = 1, repeats, 1 do
	
		beginShape(SHAPE_LINE_STRIP)

		color(0, 0.4, 1, 0.4)
	
		for i = 1, #self.points, 1 do

			t2 = (i + math.random()) * 0.1 + phase
			local p = self.points[i]
	
			vertex(r2 * math.sin(t2) + p.x, p.y + r2 * math.cos(t2), p.z)
	
		end

		endShape()
	
		color(0, 0.8, 0.6, 0.4)
		beginShape(SHAPE_LINE_STRIP)
		for i = 1, #self.points, 1 do

			t2 = (i + math.random()) * 0.1 + phase 
			local p = self.points[i]
	
			vertex(r2 * math.cos(t2) + p.x, p.y + r2 * math.sin(t2), p.z)
	
		end

	
		endShape()
		
		phase = phase + phase_inc
	
	end
	
	
	-- "lightning"
	if self.lightning > 0 then
		--noBlending()
		strokeWeight(2)
		color(1, 1, 1, 0.05)
		
		beginShape(SHAPE_LINE_STRIP)
		
		vertex(0, 0, -1000)
		vertex(0, 0, 0)
		vertex(0, 0, 1000)
		
		endShape()
		
		local d = self.lightning
		local nx, ny
		local z1, z2
		for i = 1, 15, 1 do

		nx = math.random() * self.h * 0.01
		ny = math.random() * self.h * 0.01

		z1 = -10000
		z2 = 10000
		
		beginShape(SHAPE_QUADS)
			vertex(-d + nx, -d + ny, z1)
			vertex(-d + nx, d + ny, z1)
			vertex(-d + nx, d + ny, z2)
			vertex(-d + nx, -d + ny, z2)

			vertex(d + nx, -d + ny, z1)
			vertex(d + nx, d + ny, z1)
			vertex(d + nx, d + ny, z2)
			vertex(d + nx, -d + ny, z2)

			
			vertex(-d + nx, -d + ny, z1)
			vertex(d + nx, -d + ny, z1)
			vertex(d + nx, -d + ny, z2)
			vertex(-d + nx, -d + ny, z2)
			
			vertex(-d + nx, d + ny, z1)
			vertex(d + nx, d + ny, z1)
			vertex(d + nx, d + ny, z2)
			vertex(-d + nx, d + ny, z2)
			
		endShape()
		
		end
		--drawAxis()
	end
	strokeWeight(1)
	noBlending()

	restoreProjection()

	Effect.update(self, time)	
end

function EffectPulsing:processEvent(event)

	if event.type == EVENT_CHANGE_ROW then
	
		if event.row % 16 == 0 then
			self.sign_multiplier = self.sign_multiplier * -1
			--self.camera_radius = 10 + math.sin(event.row) --math.random(10, 30)
			--self.camera_radius = 10 + math.random(10, 30)
			
			if self.sign_multiplier > 0 then
				self.camera_radius = 10 + math.random(10, 30)
			else
				self.camera_radius = 10 + math.sin(event.row)
			end
		end
		
		self.tunnel_radius = self.tunnel_radius + 0.002
		
		local base_fov = 85
		if event.pattern == 18 then
			self.camera.fov = base_fov - event.row*0.5
		elseif event.pattern == 19 then
			if event.order_position == 28 and event.row == 0 then
				self.camera.fov = base_fov
			end
			
			self.camera.fov = self.camera.fov + 0.4
		elseif event.pattern < 18 then
			self.camera.fov = base_fov
		end
		
		-- Rayo
		if event.pattern == 20 or event.pattern == 22 or event.pattern == 24 then
			self.lightning = event.row * 0.07
		elseif event.pattern == 25 or event.pattern == 26  or (event.pattern >= 28 and event.pattern <= 32) then
			self.lightning = self.lightning + 0.07
		else
			if self.lightning > 0 then
				self.lightning = self.alpha
			end
			--self.lightning = 0
		end
		
		if self.lightning > 0 then
			self.lightning = math.min(self.tunnel_radius * 0.4, self.lightning)
		end
	
	-- listen to 'bass' instrument only
	elseif event.instrument == 0 then
		-- notas mas graves y cuadrados mas gordos
		
		local p = {
			x = math.random(), --* #self.points,
			y = 0, --math.random() * self.w * 0.1,
			s = (event.note - 60)/4 + 5 --0 - event.note
		}
		if #self.points > 1 then
			local prev = self.points[#self.points - 1]
			--p.y = prev.y + prev.s * 0.5
			p.z = prev.z + prev.s * 0.5
		else
			p.z = self.start_z ---self.h * 0.5
		end
		
		table.insert(self.points, p)		
		self.alpha = self.alpha_max
	end
end
