-- LUALOCALS < ---------------------------------------------------------
local math, minetest, piredo_player, tonumber, vector
    = math, minetest, piredo_player, tonumber, vector
local math_acos, math_cos, math_pi, math_random, math_sin
    = math.acos, math.cos, math.pi, math.random, math.sin
-- LUALOCALS > ---------------------------------------------------------

local modname = minetest.get_current_modname()

local function sndgain()
	return tonumber(minetest.settings:get("piranesi_amb_atmosphere")) or 1
end

local function play(pname, pos, ppos)
	local dist = vector.distance(pos, ppos)
	return minetest.sound_play(modname .. "_air",
		{
			to_player = pname,
			pos = pos,
			gain = 0.0002 * dist * sndgain(),
			pitch = 0.8 + math_random() * 0.4
		})
end

local pdata = piredo_player.create_player_data()

piredo_player.register_playerstep(function(player, dtime, pname)
		local data = pdata(pname)

		if piredo_player.is_endcredits() then
			if data.sndid then
				minetest.sound_fade(data.sndid, 1, 0)
				data.sndid = nil
			end
			return
		end

		if not data.sndid then
			data.sndid = minetest.sound_play(modname .. "_noise", {
					to_player = player:get_player_name(),
					loop = true,
					gain = 0.00005 * sndgain()
				})
			data.vel = 0
		else
			local v = vector.length(player:get_velocity())
			if data.sndvel ~= v then
				minetest.sound_fade(data.sndid,
					(data.sndvel or 0) > v and 0.002 or 0.005,
					0.00005 + 0.0002 * v * sndgain())
				data.sndvel = v
			end
		end

		data.wait = (data.wait or 0) - dtime
		while data.wait <= 0 do
			data.wait = data.wait + math_random() / 4
			local pos = player:get_pos()
			pos.y = pos.y + player:get_properties().eye_height

			local l = math_acos(2 * math_random() - 1) - math_pi / 2
			local t = math_pi * 2 * math_random()
			local target = {
				x = pos.x + math_cos(l) * math_sin(t) * 8,
				y = pos.y + math_sin(l) * 8,
				z = pos.z + math_cos(l) * math_cos(t) * 8
			}

			for pt in minetest.raycast(pos, target, false, true) do
				if pt.type == "node" then
					return play(pname, pt.intersection_point or pt.above, pos)
				end
			end
			play(pname, target, pos)
		end
	end)
