
local level_sound = {}
local tag_from_level = {}

local pl = {}

function br_core.register_level_sound(def)
    level_sound[def.level] = def
end

function br_core.sound_stop_level(level, player, spec)
end

local function get_natural_light(pos, time)
    if minetest.get_natural_light ~= nil then
        return minetest.get_natural_light(pos, time)
    else
        return minetest.get_node_light(pos, time)
    end
end

function br_core.sound_stop_tag(tag, player, spec)
    if (not player) or (not pl[player][tag]) then return end
    for i, sound in pairs(pl[player][tag]) do
        if spec and spec.fade and not sound.fading then
            minetest.sound_fade(sound.handle, spec.fade, 0)
            sound.time = 1
            sound.fading = true
        else
            minetest.sound_stop(sound.handle)
            table.remove(pl[player][tag], i)
        end
    end
end
function br_core.sound_get_tag(tag, player)
    return pl[player][tag] or nil
end
function br_core.sound_play(tag, player, spec)
    -- make a list of tags that play on each level
    if not tag_from_level[spec.level] then tag_from_level[spec.level] = {} end
    tag_from_level[spec.level][#tag_from_level[spec.level]+1] = tag

    if not pl[player] then pl[player] = {} end
    if not pl[player][tag] then pl[player][tag] = {} end
    local ta = pl[player][tag]
    if spec.single_sound and #ta >= 1 then br_core.sound_stop_tag(tag, player, spec) end
    local spec_copy = table.copy(spec)
    if spec.fade then
        spec_copy.gain = 0.001
        spec_copy.handle = minetest.sound_play(spec.name, spec_copy)
        minetest.sound_fade(spec_copy.handle, spec.fade, spec.gain)
    else
        spec_copy.handle = minetest.sound_play(spec.name, spec_copy)
    end
    ta[#ta+1] = spec_copy
    -- minetest.log("playing sound " .. (spec.name or "nil"))
end

local function countdown(dtime, player)
    -- go through each tag
    for tagname, sound_list in pairs(pl[player]) do
        -- go through each sound in the tag
        for k, sound in pairs(sound_list) do
            if sound.time == nil then sound.time = 1 end
            sound.time = sound.time - dtime
            if (not sound.fading) and sound.fade and sound.time < 2 then
                minetest.sound_fade(sound.handle, sound.fade, 0)
                -- minetest.log("FADING sound because "..sound.time.." < 2")
                sound.fading = true
            elseif sound.time < 0 then
                minetest.sound_stop(sound.handle)
                table.remove(sound_list, k)
                -- minetest.log("stopping sound because "..sound.time.." < 0")
            end
        end
    end
end

local timer = 0
minetest.register_globalstep(function(dtime)
    if br_core.dev_mode then return end
    if timer < 1 then timer = timer + dtime return
    else timer = 0 end
    for i, player in pairs(minetest.get_connected_players()) do
        if not pl[player] then pl[player] = {} end
        countdown(1, player)
        local pli = br_spawn.player[player:get_player_name()]
        if level_sound[pli.level] then
            level_sound[pli.level]:on_play(1, player)
        end
    end
end)


br_core.register_on_changed_level(function(player, from_level, to_level)
    if tag_from_level[from_level] then
        for i, tag in pairs(tag_from_level[from_level]) do
            br_core.sound_stop_tag(tag, player, nil)
        end
    end
end)
