function rnd(mi, ma)
	return math.random(1000)/1000*(ma-mi) + mi
end


function rndVec(t)
	return VecScale(VecNormalize(Vec(rnd(-1, 1), rnd(-1, 1), rnd(-1, 1))), t)
end


function init()
	fireworks = FindLocations("firework")

	--time between fireworks
	fireworkTimer = 0

	largeExplosionSnd = {}
	for i=0, 6 do
		largeExplosionSnd[i] = LoadSound("fireworks/firework-l"..i..".ogg")
	end
	mediumExplosionSnd = {}
	for i=0, 4 do
		mediumExplosionSnd[i] = LoadSound("fireworks/firework-m"..i..".ogg")
	end
end


pyro = {}
newPyro = {}


function addPyro(type, pos)
	local p = {}
	p.type = type
	p.pos = pos
	if type=="small" then
		p.vel = Vec(rnd(-5, 5), rnd(30, 40), rnd(-5, 5))
	elseif type =="medium" then
		p.vel = Vec(rnd(-10, 10), rnd(40, 50), rnd(-10, 10))
	elseif type == "large" then
		p.vel = Vec(rnd(-15, 15), rnd(50, 60), rnd(-15, 15))
	elseif type == "trail" then
		p.vel = Vec(rnd(-10, 10), rnd(40, 50), rnd(-10, 10))
	elseif type == "multi" then
		p.vel = Vec(-rnd(-5, 5), rnd(40, 60), rnd(-5, 5))
	elseif type == "secondary" then
		p.vel = rndVec(rnd(8, 16))
	end
	local r = math.random(1, 4)
	if p.type == "secondary" or p.type == "trail" then
		r = 4
	end
	if r == 1 then
		p.r = 1.0
		p.g = rnd(0.3, 0.5)
		p.b = rnd(0.3, 0.5)
	elseif r == 2 then
		p.r = rnd(0.3, 0.5)
		p.g = 1.0
		p.b = rnd(0.3, 0.5)
	elseif r == 3 then
		p.r = rnd(0.3, 0.5)
		p.g = rnd(0.3, 0.5)
		p.b = 1.0
	else
		p.r = 1.0
		p.g = 1.0
		p.b = rnd(0.8, 1.0)
	end
	p.age = 0
	p.lifeTime = math.sqrt(VecLength(p.vel)) * 0.5
	if type == "trail" then
		p.lifeTime = p.lifeTime * 2.0
	end
	p.done = false
	newPyro[#newPyro+1] = p
end


function light(p, t)
	local l = 1
	if p.type == "secondary" then
		l = 0.2
	end
	if p.type == "small" then
		l = 0.5
	end
	if p.type == "large" then
		l = 2
	end
	PointLight(p.pos, p.r, p.g, p.b, l*200*t)
end


function sound(p)
	local large = false
	local vol = 1
	if p.type == "large" or p.type == "medium" then
		large = true
	end
	if p.type == "secondary" then
		return
	end
	if large then
		PlaySound(largeExplosionSnd[math.random(0,#largeExplosionSnd)], p.pos, vol*60)
	else
		PlaySound(mediumExplosionSnd[math.random(0,#mediumExplosionSnd)], p.pos, vol*60)
	end
end


function trail(p)
	ParticleType("plain")
	ParticleTile(4)
	ParticleCollide(0)
	ParticleEmissive(5, 0)
	ParticleAlpha(1, 0)
	ParticleRadius(0.4, 0)
	ParticleColor(1, 1, 1)
	ParticleDrag(0.2)
	if p.type == "trail" then
		SpawnParticle(p.pos, VecAdd(VecScale(p.vel, 0.0), rndVec(8)), rnd(1.0, 2.0))
	else
		SpawnParticle(p.pos, Vec(0,0,0), 0.1)
	end
end


function explode(p)
	ParticleType("plain")
	ParticleTile(4)
	ParticleCollide(0)
	ParticleEmissive(10, 0, "easeout")
	ParticleAlpha(1, 0)
	ParticleRadius(0.3)
	ParticleDrag(0.1)
	ParticleGravity(-10)
	ParticleStretch(2)
	ParticleColor(p.r, p.g, p.b)
	if p.type == "small" then
		for i=1, 80 do
			SpawnParticle(p.pos, rndVec(rnd(20, 30)), rnd(1.0, 1.5))
		end
	elseif p.type == "medium" then
		for i=1, 120 do
			SpawnParticle(p.pos, rndVec(rnd(30, 60)), rnd(1.5, 2.0))
		end
	elseif p.type == "large" then
		for i=1, 200 do
			SpawnParticle(p.pos, rndVec(rnd(80, 100)), rnd(2.0, 3.5))
		end
	elseif p.type == "secondary" then
		for i=1, 25 do
			SpawnParticle(p.pos, rndVec(rnd(10, 20)), rnd(1.0, 1.5))
		end
	elseif p.type == "multi" then
		for i=1, 16 do
			addPyro("secondary", p.pos)
		end
	end
end


function tickPyro(dt)
	local soundDelay = 1.0
	local lightTime = 0.7

	for i=1, #pyro do
		local p = pyro[i]
		local keep = true
		p.age = p.age + dt
		if p.age < p.lifeTime then
			p.vel = VecAdd(p.vel, VecScale(Vec(0, -10, 0), dt))
			p.pos = VecAdd(p.pos, VecScale(p.vel, dt))
			trail(p)
		else
			if not p.done then
				explode(p)
				p.done = true
			else
				if p.age < p.lifeTime+lightTime then
					local t = 1.0 - (p.age-p.lifeTime)/lightTime
					light(p, t)
				end
				if p.age > p.lifeTime+soundDelay then
					sound(p)
					keep = false
				end
			end
		end
		if keep then
			newPyro[#newPyro+1] = p
		end
	end
	pyro = newPyro
	newPyro = {}
end


function tick(dt)
	tickPyro(dt)
	if GetBool("level.demolish.fireworks") and GetFloat("level.timeleft") > 30 then       
		fireworkTimer = fireworkTimer - dt
		if fireworkTimer <= 0 then
			local i = math.random(1,#fireworks)
			local t = GetLocationTransform(fireworks[i])
			local r = math.random(1, 5)
			if r == 1 then
				addPyro("small", t.pos)
			elseif r == 2 then
				addPyro("medium", t.pos)
			elseif r == 3 then
				addPyro("large", t.pos)
			elseif r == 4 then
				addPyro("multi", t.pos)
			elseif r == 5 then
				addPyro("trail", t.pos)
			end
			fireworkTimer = math.random(5,10) / 10
		end
	end
end

