local S = minetest.get_translator(blockbomber.modname)
local cleanup_player = function(p_name, p_properties) end
local clear_items_from_arena = function(arena) end

function blockbomber.get_visual_obj(player)
    local children = player:get_children()
    for _, child in pairs(children) do
        local ent = child:get_luaentity()
        if ent and ent.name == "block_bomber_mg:character" then
            return child
        end
    end
end


arena_lib.on_load(blockbomber.modname, function(arena)
    clear_items_from_arena(arena)
    arena.match_id = blockbomber.get_new_match_id()
    -- place the arena
    local num_players = 0
    for pl_name,stats in pairs(arena.players) do
        num_players = num_players + 1
    end
    arena.map = bb_schems.get_arena_by_playercount(num_players)
    bb_schems.place_arena(arena.map.name, arena.origin)
    local msg = S("Loading Arena [@1], made by [@2]", arena.map.name, arena.map.author)
    arena_lib.send_message_in_arena(arena, "both", msg)


    -- set the players' hand inventories

    local spawns = table.copy(arena.map.spawns)
    for pl_name, stats in pairs(arena.players) do
        local player = minetest.get_player_by_name(pl_name)

        local pl_visual_staticdata = minetest.write_json({
            _arena_name = arena.name,
            _match_id = arena.match_id
        })

        local pl_visual = minetest.add_entity(player:get_pos() ,"block_bomber_mg:character", pl_visual_staticdata)
        pl_visual:set_properties({textures={"white.png^[colorize:"..blockbomber.player_colors[pl_name]..":255","player_parts.png"}})

        pl_visual:set_attach(player)

        
        -- choose a spawn location
        local pos_i = math.random(#spawns)
        local pos_p = spawns[pos_i]
        pl_visual:set_pos(pos_p)
        minetest.after(0,function(player) 
            if player then
                player:set_detach()
                player:set_pos(vector.copy(pos_p)+vector.copy(arena.origin))
            end
        end,player)
        
        table.remove(spawns, pos_i)


        
        -- set hand to only select items within 1 node
        local inv = player:get_inventory()
        inv:set_size("hand",1)
        inv:set_stack("hand",1,ItemStack("block_bomber_mg:bb_hand"))

        blockbomber.add_info_hud(pl_name)

        -- attach players to a holding ent until the arena can be loaded
        local pos = player:get_pos()
        local att = minetest.add_entity(pos, "block_bomber_mg:att")
        player:set_attach(att)
    end
end)

arena_lib.on_start(blockbomber.modname, function(arena)

    clear_items_from_arena(arena)
    for pl_name, stats in pairs(arena.players) do
        blockbomber.set_info_hud(pl_name, tostring(arena.sudden_death_time - arena.current_time))
        local player = minetest.get_player_by_name(pl_name)
        
        -- give players the initial items
        local inv = player:get_inventory()
        local list = inv:get_list("main")
        for k, v in pairs(list) do
            inv:remove_item("main", v)
        end
        inv:add_item("main", ItemStack("bb_powerup:extra_bomb")) 
        inv:add_item("main", ItemStack("bb_powerup:extra_power"))
    end

end)

arena_lib.on_celebration(blockbomber.modname, function(arena, winner)
    clear_items_from_arena(arena)
    -- update leaderboard
    if winner then
        if blockbomber.leaderboard[winner] then
            blockbomber.leaderboard[winner] = blockbomber.leaderboard[winner] + 1
        else
            blockbomber.leaderboard[winner] = 1
        end
        blockbomber.save_leaderboard()
        local player = minetest.get_player_by_name(winner)
        if player then
            local sppos = player:get_pos()
            sppos = vector.add(sppos,vector.new(0,1,0))
            minetest.add_particlespawner({
                amount = 20,
                time = .5,
                minpos = vector.add(sppos,vector.new(-.7,-.4,-.7)),
                maxpos = vector.add(sppos,vector.new(.7,.4,.7)),
                minvel = vector.new(.1,3,.1),
                maxvel = vector.new(1.5,7,1.5),
                minacc = vector.new(0,-9.8,0),
                maxacc = vector.new(0,-9.8,0),
                minexptime = 1,
                maxexptime = 1,
                minsize = 3,
                maxsize = 4,
                collisiondetection = true,            
                collision_removal = false,
                object_collision = true,
                --attached = ObjectRef,
                vertical = false,
                texture = "bb_spawn_particle.png",
                glow = 2,
            })
            minetest.add_particlespawner({
                amount = 20,
                time = .5,
                minpos = vector.add(sppos,vector.new(-.7,-.4,-.7)),
                maxpos = vector.add(sppos,vector.new(.7,.4,.7)),
                minvel = vector.new(.1,3,.1),
                maxvel = vector.new(1.5,7,1.5),
                minacc = vector.new(0,-9.8,0),
                maxacc = vector.new(0,-9.8,0),
                minexptime = 1,
                maxexptime = 1,
                minsize = 3,
                maxsize = 4,
                collisiondetection = true,            
                collision_removal = false,
                object_collision = true,
                vertical = false,
                texture = "bb_respawn_particle.png",
                glow = 2,
            })
        end

        -- for pl_name, stats in pairs(arena.players) do
        --     cleanup_player(pl_name, stats)
        -- end

    end
end)

arena_lib.on_end(blockbomber.modname, function(arena, winners, is_forced)
    for pl_name, stats in pairs(arena.players) do
        cleanup_player(pl_name, stats)
    end
end)

arena_lib.on_eliminate(blockbomber.modname, function(arena, p_name, xc_name, p_properties)
    cleanup_player(p_name, p_properties)
end)

arena_lib.on_time_tick(blockbomber.modname, function(arena)
    -- handle sudden death
    if arena.current_time > arena.sudden_death_time and not arena.sudden_death then
        arena.sudden_death = true
        for p_name, stats in pairs(arena.players_and_spectators) do
            
            -- sudden death warning
            minetest.sound_play({
                name = "alarm",
                gain = 0.1,
            }, {
                to_player = p_name,
            }, true)

            blockbomber.set_info_hud(p_name, S("Sudden Death"))
        end

    end
    if arena.sudden_death == true then
        arena.sudden_death_timer = arena.sudden_death_timer + 1
    else
        for p_name, stats in pairs(arena.players) do
            blockbomber.set_info_hud(p_name, tostring(arena.sudden_death_time - arena.current_time))
        end
    end

    -- make items jump

    local objs = minetest.get_objects_in_area(arena.pos1, arena.pos2)
    for _, obj in pairs(objs) do
        local ent = obj:get_luaentity()
        if ent then
            local o_name = ent.name
            if o_name == "__builtin:item" then
                obj:add_velocity(vector.new(0,2,0))
            end
        end
    end

    -- handle eliminating players

    -- check for alive players. If there are no alive players then end the game without winners. If there are alive players, then remove them.
    local found_alive = false
    for pl_name, stats in pairs(arena.players) do
        if stats.dead == false then
            found_alive = true
        end
    end

    if found_alive then
        for pl_name, stats in pairs(arena.players) do
            if stats.dead then
                local msg = S("@1 was removed from the arena.", pl_name)
                if stats.cause == "falling" or stats.cause == "explosion" then
                    local missage = blockbomber.messages[stats.cause][math.random(1,#blockbomber.messages[stats.cause])]
                    msg = S(missage, pl_name)
                end
            
                arena_lib.remove_player_from_arena(pl_name, 1, nil, msg)
            end
        end
    else
        -- send a death message for each player
        for pl_name, stats in pairs(arena.players) do
            
            local msg = S("@1 was removed from the arena.", pl_name)
            if stats.cause == "falling" or stats.cause == "explosion" then
                local missage = blockbomber.messages[stats.cause][math.random(1,#blockbomber.messages[stats.cause])]
                msg = S(missage, pl_name)
            end
            arena_lib.send_message_in_arena(arena, "both", minetest.colorize("#a93b3b", "<< " ..(msg)))
            
            -- end the arena
            arena_lib.load_celebration(blockbomber.modname, arena, nil)

        end
    end

end)

arena_lib.on_quit(blockbomber.modname, function(arena, p_name, is_spectator, reason, p_properties)
    cleanup_player(p_name, p_properties)
end)


cleanup_player = function(p_name, p_properties)
    local player = minetest.get_player_by_name(p_name)
    if not player then return end
    local inv = player:get_inventory()
    inv:set_stack("hand",1,ItemStack(""))
    blockbomber.remove_info_hud(p_name)
    if minetest.get_modpath("player_api") then
        if player_api.player_attached and player_api.player_attached[p_name] ~= nil then
            player_api.player_attached[p_name] = p_properties.original_attached
        end
    end

    -- remove player attachment visual

    local visual_obj = blockbomber.get_visual_obj(player)
    if visual_obj then
        visual_obj:set_detach()
        visual_obj:remove()
    end
end

clear_items_from_arena = function(arena) 
    local objs = minetest.get_objects_in_area(arena.pos1, arena.pos2)
    for k,v in ipairs(objs) do
        local ent = v:get_luaentity()
        if ent and ent.name == "__builtin:item" then
            v:remove()
        end
    end
end