
aom_muskets.active_players = {}
local active_players = aom_muskets.active_players
aom_muskets.reloader = {}

local FULLWEAR = 65536

function aom_muskets.get_reload_params(itemstack)
    return aom_muskets.reloader[itemstack:get_name()]
end

function aom_muskets.register_musket_reloader(param)
    param.time = param.time or 3
    aom_muskets.reloader[param.name] = param

    aom_util.register_on_wield({
        name = param.name,
        on_change_to_item = function(player, itemstack)
            local r = aom_muskets.get_reload_params(itemstack)
            if r.auto_reload then aom_muskets.start_reload(player) end
        end,
        on_change_from_item = function(player, itemstack)
            local r = aom_muskets.get_reload_params(itemstack)
            playerphysics.remove_physics_factor(player, "speed", "aom_muskets")
        end,
        on_step = param.movement_speed and function(player, dtime, itemstack)
            local r = aom_muskets.get_reload_params(itemstack)
            if r.movement_speed and itemstack:get_wear() < FULLWEAR - 50 and playerphysics then
                local v = player:get_velocity()
                v.y = 0
                player:add_velocity(vector.multiply(v, -0.2))
                playerphysics.add_physics_factor(player, "speed", "aom_muskets", param.movement_speed)
            end
        end,
    })
end

function aom_muskets.start_reload(player)
    active_players[player] = true
end

function aom_muskets.reload_musket(itemstack, dtime, player)
    local reloader = aom_muskets.reloader[itemstack:get_name()]
    local wear_take = math.round((65536 / reloader.time) * dtime)
    local wear = itemstack:get_wear()
    local ctrl = player:get_player_control()
    local boost = 1
    local is_sprinting = false
    if core.get_modpath("player_sprint") then
        is_sprinting = player_sprint.is_sprinting(player)
    else
        is_sprinting = ctrl.aux1
    end
    if ctrl and ctrl.sneak then boost = reloader.sneak_boost end
    if ctrl and (is_sprinting) then boost = boost * reloader.sprint_boost end
    local setting = aom_settings.get_setting(player, "gameplay_musket_reload_speed", 1)
    wear = math.max(wear - (wear_take*boost*setting), 0)
    if wear <= 0 then
        if reloader.loaded ~= nil then
            itemstack:set_name(reloader.loaded)
        end
        if reloader.on_load then reloader.on_load(itemstack, player) end
    end
    itemstack:set_wear(wear)
    if reloader.on_step then itemstack = reloader.on_step(player, dtime, itemstack) end
    return itemstack
end

function aom_muskets.reload_muskets_in_inventory(player, dtime)
    local found_musket = false
    local inv = player:get_inventory()
    if not inv then return end
    for i = 1, inv:get_size("main") do
        local stack = inv:get_stack("main", i)
        local name = stack:get_name()
        if aom_muskets.reloader[name]
        and stack:get_wear() > 0 then
            if (not aom_muskets.reloader[name].require_wield)
            or (i == player:get_wield_index()) then
                stack = aom_muskets.reload_musket(stack, dtime, player)
                inv:set_stack("main", i, stack)
                found_musket = true
            elseif aom_muskets.reloader[name].require_wield and stack:get_wear() < FULLWEAR - 1 then
                stack:set_wear(FULLWEAR - 1)
                inv:set_stack("main", i, stack)
            end
        end
    end
    -- minetest.log("reloading musket")
    return found_musket
end

function aom_muskets.on_step_quick_reload(player, dtime, itemstack, params)
    local ctrl = aom_playerapi.controls.get_player_control(player)
    if ctrl and ctrl.just_pressed.place then
        local w = itemstack:get_wear()
        if w > 65536 * (1-(params.max / 14)) and w < 65536 * (1-(params.min / 14)) then
            itemstack:set_wear(65536 * 0.1)
        elseif w > 100 then
            itemstack:set_wear(65536 - 1)
        end
    end
    return itemstack
end

function aom_muskets.on_step(dtime)
    for player, n in pairs(active_players) do
        if not aom_muskets.reload_muskets_in_inventory(player, dtime) then
            active_players[player] = nil
        end
    end
end

minetest.register_globalstep(aom_muskets.on_step)

minetest.register_on_joinplayer(function(player, last_login)
    aom_muskets.start_reload(player)
    playerphysics.remove_physics_factor(player, "speed", "aom_muskets")
end)
