local mod_name = minetest.get_current_modname()
local mod_path = minetest.get_modpath(mod_name)
local S = minetest.get_translator(mod_name)

aom_music.total_chance = 0
aom_music.registered_music = {}
aom_music.player_meta = {}
local pl = aom_music.player_meta

local has_aom_settings = (minetest.get_modpath("aom_settings") ~= nil)

if has_aom_settings then
    aom_settings.register_setting("music_volume", 0.3, "Volume")
    aom_settings.register_setting("music_notify_track", true, "Show track name")
    aom_settings.register_setting("music_interval_min", 120, "Min time before next track")
    aom_settings.register_setting("music_interval_max", 900, "Max time before next track")
    aom_settings.register_setting("music_on_join_chance", 0.05, "Chance to play immediately on join")
end

function aom_music.get_igm_settings(player)
    if has_aom_settings then
        local pi = pl[player]
        pi.music_volume = aom_settings.get_setting(player, "music_volume")
        pi.music_interval_min = aom_settings.get_setting(player, "music_interval_min")
        pi.music_interval_max = aom_settings.get_setting(player, "music_interval_max")
    end
end

function aom_music.check_player(player)
    if not pl[player] then
        pl[player] = {
            current = nil,
            music_volume = 0,
            music_interval_min = 60,
            music_interval_max = 600,
            music_on_join_chance = 0.05,
            time_to_end = 0,
            time_to_next = 9,
        }
        aom_music.get_igm_settings(player)
        aom_music.get_next_time(player)
        if has_aom_settings and (math.random() < aom_settings.get_setting(player, "music_on_join_chance")) then
            pl[player].time_to_next = 1
        end
    end
    return pl[player]
end

-- stop music if volume set to 0
aom_settings.register_on_change_setting("music_volume", function(player, settingname, new_value, old_value)
    local pi = aom_music.check_player(player)
    pi.music_volume = aom_settings.get_setting(player, "music_volume")
    if new_value and pi.soundid then
        minetest.sound_fade(pi.soundid, 1, pi.music_volume)
    end
end)


function aom_music.register_music(def)
    aom_music.total_chance = (aom_music.total_chance + def.chance) or 1
    table.insert(aom_music.registered_music, def)
end


function aom_music.get_next_time(player)
    local pi = aom_music.check_player(player)
    pi.time_to_next = math.random(pi.music_interval_min, pi.music_interval_max)
end

function aom_music.get_next(player)
    local r = math.random() * aom_music.total_chance
    for i, def in ipairs(aom_music.registered_music) do
        r = r - def.chance
        if (r <= 0) and ((not def.can_play) or def.can_play(player)) then return def end
    end
    return nil
end


function aom_music.stop(player)
    local pi = aom_music.check_player(player)
    if pi.soundid then
        minetest.sound_fade(pi.soundid, 1, 0)
    end
end

function aom_music.skip(player)
    local pi = aom_music.check_player(player)
    pi.current = nil
    pi.time_to_next = 0
    if pi.soundid then
        minetest.sound_fade(pi.soundid, 1, 0)
    end
end

function aom_music.play(player)
    local pi = aom_music.check_player(player)
    if pi.current then return end
    pi.current = nil
    pi.time_to_next = 0
    if pi.soundid then
        minetest.sound_fade(pi.soundid, 1, 0)
    end
end


function aom_music.on_step(dtime)
    for i, player in ipairs(minetest.get_connected_players()) do repeat
        local pi = aom_music.check_player(player)

        if pi.current and (pi.time_to_end > 0) then
            pi.time_to_end = pi.time_to_end - dtime
            break
        end
        if pi.time_to_next > 0 then
            pi.time_to_next = pi.time_to_next - dtime
            break
        end
        -- update settings
        aom_music.get_igm_settings(player)
        aom_music.get_next_time(player)
        if pi.music_volume <= 0 then return end
        -- choose next music
        pi.current = aom_music.get_next(player)
        if (not pi.current) then break end
        pi.time_to_end = pi.current.length
        if (not aom_igm) or aom_settings.get_setting(player, "music_notify_track") then
            minetest.chat_send_player(
                player:get_player_name(),
                minetest.colorize("#9ad", "[aom_music] now playing: ")..
                ""..minetest.colorize("#49d", tostring(pi.current.name)))
        end
        local spec = pi.current.get_soundspec(player)
        spec.to_player = player:get_player_name()
        spec.gain = spec.gain * pi.music_volume

        if pi.current.on_play then
            pi.current.on_play(player)
        else
            pi.soundid = minetest.sound_play(pi.current.sound, spec)
        end
    until true end
end
minetest.register_globalstep(aom_music.on_step)



minetest.register_chatcommand("music", {
    params = "skip | stop | play",
    description = S(""),
    privs = {},
    func = function(name, param)
        local player = minetest.get_player_by_name(name)
        if param == "skip" then
            aom_music.skip(player)
        elseif param == "stop" then
            aom_music.stop(player)
            return true, S("Stopping music for now")
        elseif param == "play" then
            aom_music.play(player)
            return true
        end
        return false, S("Must be either /music stop or /music skip")
    end
})
