--%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

-- functions declared

--%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%




-- clears a player's inv
-- input: player objref
function bb_player.clear_inv(player)  return end



-- checks for air in node under player
-- input: player objref
function bb_player.check_for_air_under(player) return end
    


-- returns the number of a kind of item in inv
-- input player objref, itenname, output count (int)
function bb_player.get_count_in_inv(player,item) return end

-- resurrects all players and clears the board of deadplayer markers
function bb_player.resurrect_all_players() return end


-- functions to be run before a player dies:
-- bb_player.register_on_dieplayer(function(p_name,cause))
-- cause can be "explosion","falling","unknown" or anything else mod-defined
-- return true to cancel death

function bb_player.register_before_dieplayer(func) return end

-- functions to be run when a player dies:
-- bb_player.register_on_dieplayer(function(p_name,cause))
-- cause can be "explosion","falling","unknown" or anything else mod-defined

function bb_player.register_on_dieplayer(func) return end



-- kills a player who is alive
-- input ObjRef
function bb_player.kill_player(player) return end

function bb_player.loop_theme(song,len,p_name) return end





--%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

-- functions defined

--%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%








-- clears a player's inv
-- input: player objref
function bb_player.clear_inv(player)

    local inv = player:get_inventory()
    local list = inv:get_list("main")
    for k, v in pairs(list) do
        inv:remove_item("main", v)
    end
    
end












-- checks for air in node under player
-- input: player objref
function bb_player.check_for_air_under(player)
    --return true if the player should fall out and lose the game
    
    local pos = player:get_pos()

    -- checkdistance to check for solid nodes under player in. it defines the distance players may step off a ledge without falling.
    local cdist = .2

    local check_for_floor = 30 -- distance to detect if player can fall to floor below instead of falling out.

    --player pos is at the floor of the player's hitbox, where they are standing, in the center of the x,z
    -- u_pos is the pos under that
    local u_pos = vector.add(pos, vector.new(0,-.7,0))
    --iff all checkpoints have air, then the player has stepped off

    if minetest.get_node(vector.add(u_pos,vector.new(-cdist,0,-cdist))).name == "air" and
        minetest.get_node(vector.add(u_pos,vector.new(-cdist,0,0))).name == "air" and
        minetest.get_node(vector.add(u_pos,vector.new(-cdist,0,cdist))).name == "air" and
        minetest.get_node(vector.add(u_pos,vector.new(0,0,-cdist))).name == "air" and
        minetest.get_node(vector.add(u_pos,vector.new(0,0,0))).name == "air" and
        minetest.get_node(vector.add(u_pos,vector.new(0,0,cdist))).name == "air" and
        minetest.get_node(vector.add(u_pos,vector.new(cdist,0,-cdist))).name == "air" and
        minetest.get_node(vector.add(u_pos,vector.new(cdist,0,0))).name == "air" and
        minetest.get_node(vector.add(u_pos,vector.new(cdist,0,cdist))).name == "air" then

            local floor_found = false
            for i = 0,check_for_floor do
                if minetest.get_node(vector.add(u_pos,vector.new(0,-i,0))).name ~= "air" then 
                    floor_found = true
                end
            end

            if floor_found then
                return false
            else
                return true
            end
    else
        return false
    end


end















-- returns the number of a kind of item in inv
-- input player objref, itenname, output count (int)
function bb_player.get_count_in_inv(player,item)

    local count = 0
    local inv = player:get_inventory()
    local lists = inv:get_lists()
    for listname,itemstacklist in pairs(lists) do
        for _,stack in pairs( itemstacklist ) do
            if stack:get_name() == item then
                count = count + stack:get_count()
            end
        end
    end
    return count

end



    -- resurrect all players!!!
    -- first remove any deadplayer markers

function bb_player.resurrect_all_players()

    --remove all deadmarkers
    for _,obj in pairs(minetest.get_objects_inside_radius(vector.new(0,0,0), 200)) do

        local ent = obj:get_luaentity()
        if ent then
            local name = ent.name
            if name == "bb_player:dead_player" then
                obj:remove()
            end
        end
    end
    -- resurrect all players
    for _, i_player in pairs( minetest.get_connected_players()) do

        local pmeta = i_player:get_meta()
        local status = pmeta:get_string("status")
        local spawn = minetest.deserialize(pmeta:get_string("spawn"))
        local p_name = i_player:get_player_name()

        if status == "dead" then
            -- they dont get to keep their stuffz, if they had any
            bb_player.clear_inv(i_player)
            -- if they died from falling, move them to their spawn location
            -- if bb_player.check_for_air_under(i_player) then
                i_player:set_detach()
                i_player:set_pos(spawn)
            -- end
            -- give them the basic starting stuff

            local inv = i_player:get_inventory()
            local list = inv:get_list("main")
           
            inv:add_item("main", ItemStack("bb_powerup:extra_bomb")) 
            inv:add_item("main", ItemStack("bb_powerup:extra_power"))

            -- spawn some particles and give play a sound.
            minetest.add_particlespawner({
                amount = 40,
                time = 1,
                minpos = vector.add(spawn,vector.new(-.5,-.4,-.5)),
                maxpos = vector.add(spawn,vector.new(.5,1,.5)),
                minvel = vector.new(0,1,0),
                maxvel = vector.new(.01,4,.01),
                minacc = vector.new(0,0,0),
                maxacc = vector.new(.01,4,.01),
                minexptime = 1,
                maxexptime = 1,
                minsize = 3,
                maxsize = 4,
                collisiondetection = false,            
                collision_removal = false,
                object_collision = false,
                --attached = ObjectRef,
                vertical = false,
                texture = "respawn_particle.png",
                glow = 2,
            })

            minetest.sound_play({
                name = "respawn2",
                gain = 0.6,
            }, {
                pos = spawn,
                max_hear_distance = 10,  
            }, true)


            minetest.after(.2,function(p_name)
                local player = minetest.get_player_by_name(p_name)
                if not player then return end
                if bb_loop.gamestate ~= "running" then return end

                pmeta:set_string("status", "playing")
            end,p_name)
        end
    end
end




-- functions to be run before a player dies:
-- bb_player.register_on_dieplayer(function(p_name,cause,death_pos,death_dir))
-- cause can be "explosion","falling","unknown" or anything else mod-defined
-- return true to cancel death, return "force" to force death to occur regardless of other
-- cancellations

function bb_player.register_before_dieplayer(func)
    table.insert(bb_player.registered_before_dieplayers,func)
end


-- functions to be run when a player dies:
-- bb_player.register_on_dieplayer(function(p_name,cause,death_pos,death_dir))
-- cause can be "explosion","falling","unknown" or anything else mod-defined

function bb_player.register_on_dieplayer(func)
    table.insert(bb_player.registered_on_dieplayers,func)
end




-- kills a player who is alive
-- input ObjRef
function bb_player.kill_player(player,cause)

    local p_name = player:get_player_name()
    local death_pos = player:get_pos()
    local death_dir = player:get_look_horizontal()
    cause = cause or "unknown"


    local cancel_death = false
    local force_death = false
    -- perform the registered_before_dieplayer functions
    for idx,func in ipairs(bb_player.registered_before_dieplayers) do

        local ret = func(p_name,cause,death_pos,death_dir)

        if ret then
            if ret == true then
                cancel_death = true 
            elseif ret == "force" then
                force_death = true 
            end
        end
    end

    if cancel_death==true and force_death==false then return end

        
    -- perform the registered_on_dieplayer functions
    for idx,func in ipairs(bb_player.registered_on_dieplayers) do
        func(p_name,cause,death_pos,death_dir)
    end

end



function bb_player.loop_theme(song,len,p_name)

    minetest.sound_play({
        name = song,
        gain = 0.1,
    }, {
        to_player = p_name,        
        fade = 0.0,   -- default, change to a value > 0 to fade the sound in
        pitch = 1.0,  -- default
    }, true)
    minetest.after(len,function(song,len,p_name)
        local player = minetest.get_player_by_name(p_name)
        if player then
            bb_player.loop_theme(song,len,p_name)
        end
    end,song,len,p_name)

end









