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

br_sprint = {
    sprint_time = 4,
    sprint_recovery = 3,
    stamina = 20,
    recovery_enabled = false,
}


local pl = {}


local function get_shell()
    return {
        recovering = false,
        stamina = br_sprint.stamina,
        sound = {},
    }
end

local function sound_play(player, spec)
    if pl[player].sound[spec.name] then return end
    local spec_copy = table.copy(spec)
    spec_copy.gain = (spec.fade and 0.01) or spec.gain
    pl[player].sound[spec.name] = table.copy(spec)
    pl[player].sound[spec.name].handle = minetest.sound_play(spec.name, spec_copy)
    if spec.fade then
        minetest.sound_fade(pl[player].sound[spec.name].handle, spec.fade, spec.gain)
    end
end

local function do_sprint(player, dtime)
    local pi = player_info and player_info.get(player)
    if not pi then return end
    if pi.is_sprinting then
        pl[player].stamina = pl[player].stamina - ((br_sprint.stamina / br_sprint.sprint_time) * dtime)
    else
        pl[player].stamina = pl[player].stamina + ((br_sprint.stamina / br_sprint.sprint_recovery) * dtime)
        local spec = pl[player].sound["br_wind_noise_WTFPL_Sumianvoice"]
        if spec then
            minetest.sound_fade(spec.handle, 1, 0)
            spec.time = math.min(0.2, spec.time)
        end
    end
    pl[player].stamina = math.max(math.min(pl[player].stamina, br_sprint.stamina), 0)
    if pl[player].stamina <= 1 then
        sound_play(player, {
            name = "br_d_stamina_low",
            time = 3,
            gain = 0.8,
            object = player,
        })
    elseif pl[player].sound["br_d_stamina_low"] then
        local spec = pl[player].sound["br_d_stamina_low"]
        minetest.sound_fade(spec.handle, 1, 0)
        spec.time = math.min(0.2, spec.time)
    end
    if pl[player].stamina == 0 then
        pl[player].recovering = true
        pl[player].recover_start = true
    elseif pl[player].stamina == br_sprint.stamina then
        pl[player].recovering = false
    end
end


minetest.register_on_joinplayer(function(player, last_login)
    pl[player] = get_shell()
end)


minetest.register_globalstep(function(dtime)
    for i, player in pairs(minetest.get_connected_players()) do
    end
end)


function br_sprint.to_walk(player)
    playerphysics.remove_physics_factor(player, "speed", "player_sprint")
end

function br_sprint.on_step(dtime)
    for _, player in pairs(minetest.get_connected_players()) do
        if not pl[player] then pl[player] = get_shell() end
        for k, spec in pairs(pl[player].sound) do
            if spec.time > 0 then
                spec.time = spec.time - dtime
            else
                pl[player].sound[k] = nil
            end
        end

        local pi = player_info.get(player)
        local sprint_intention = (pi and (pi.ctrl.aux1 and pi.ctrl.up))

        if sprint_intention and not minetest.is_creative_enabled(player:get_player_name()) then
            if pl[player].state ~= "sprint" and pl[player].stamina > 1 then
                playerphysics.add_physics_factor(player, "speed", "player_sprint", 1.8)
                pi.is_sprinting = true
                pmb_util.unset_fov(player, "player_sprint")
                pmb_util.set_fov(player, {
                    tag = "player_sprint",
                    fov = 1.13,
                    is_multiplier = true,
                    transition_time = 0.2 })
            elseif pl[player].state ~= "tired_sprint" then
                playerphysics.add_physics_factor(player, "speed", "player_sprint", 1.3)
                pi.is_sprinting = true
                pmb_util.unset_fov(player, "player_sprint")
                pmb_util.set_fov(player, {
                    tag = "player_sprint",
                    fov = 1.06,
                    is_multiplier = true,
                    transition_time = 0.1 })
            end
        else
            br_sprint.to_walk(player)
            pi.is_sprinting = false
            pmb_util.unset_fov(player, "player_sprint")
        end
        do_sprint(player, dtime)
    end
end

minetest.register_on_dieplayer(br_sprint.to_walk)
minetest.register_on_joinplayer(br_sprint.to_walk)

minetest.register_globalstep(br_sprint.on_step)
