-- LUALOCALS < ---------------------------------------------------------
local PcgRandom, ipairs, klots, math, minetest, pairs
    = PcgRandom, ipairs, klots, math, minetest, pairs
local math_floor, math_pow
    = math.floor, math.pow
-- LUALOCALS > ---------------------------------------------------------

local dmin = {
	{2},
	{2},
	{0, 5, 2},
	{7, 5, 2},
}
local cmaj = {
	{0},
	{0},
	{-3, 2, 0},
	{5, 2, 0}
}
local keys = {
	dmin,
	dmin,
	cmaj
}

local playbuffs = {}
local noplay = {}

local function metronome() return math_floor(minetest.get_gametime() / 2) end

local lastt
minetest.register_globalstep(function()
		local t = metronome()
		lastt = lastt or t
		if lastt == t then return end

		local keypos = math_floor(t / 16)
		local measure = math_floor(t / 4)
		local note = t % 4 + 1

		local key = PcgRandom(keypos):next(1, #keys)
		local motifs = keys[key]
		local motif = PcgRandom(measure):next(1, #motifs)
		local volume = PcgRandom(measure):next(1, 1000) *.0008 + 0.2
		local tone = motifs[motif][note]
		if tone then
			for _, player in ipairs(minetest.get_connected_players()) do
				local pname = player:get_player_name()
				if t >= (noplay[pname] or 0) then
					local pos = player:get_pos()
					if pos.y >= 128 then
						local id = minetest.sound_play("klots_music_flute",
							{
								to_player = player:get_player_name(),
								pitch = math_pow(2, tone / 12),
								gain = 0.02 * volume
							})
						local buff = playbuffs[pname]
						if not buff then
							buff = {}
							playbuffs[pname] = buff
						end
						buff[id] = true
						minetest.after(5, function() buff[id] = nil end)
					end
				end
			end
		end
	end)

klots.register_on_player_teleport(function(player)
		local pname = player:get_player_name()
		noplay[pname] = metronome() + 2
		local buff = playbuffs[pname]
		if not buff then return end
		for id in pairs(buff) do minetest.sound_stop(id) end
	end)
