
pmb_util.itemdrop = {}
pmb_util.itemdrop_nodes = {}

function pmb_util.register_tool_cap(name, param)
    pmb_util.itemdrop[name] = table.copy(param)
    return param
end

function pmb_util.get_tool_caps(name)
    return pmb_util.itemdrop[name]
end

function pmb_util.register_node_drop(name, param)
    pmb_util.itemdrop_nodes[name] = table.copy(param)
    return param
end

function pmb_util.get_node_drop(name)
    if pmb_util.itemdrop_nodes[name] then
        return pmb_util.itemdrop_nodes[name]
    end
    return nil
end

local function drop(pos, items)
    for _, item in ipairs(items) do
        pos = vector.offset(
            pos,
            math.random()-0.5,
            math.random()-0.5,
            math.random()-0.5
        )
        minetest.add_item(pos, item)
    end
end

minetest.register_tool("pmb_util:dig_anything", {
    description = "",
    inventory_image = "white.png",
    tool_capabilities = pmb_util.register_tool_cap("pmb_util:dig_anything", {
        full_punch_interval = 1,
        groupcaps = {
            oddly_breakable_by_hand = {
                times = { 0.1, 0.1, 0.1, 0.1 },
            },
            cracky = {
                times = { 0.1, 0.1, 0.1, 0.1 },
            },
        },
    }),
    groups = { not_in_creative_inventory = 1, unobtainable = 1 },
})

local function test_tcaps(icaps, node)
    local can_drop = true
    for group, def in pairs(icaps.groupcaps) do
        if icaps and icaps[group] then def = icaps[group] end
        local gval = minetest.get_item_group(node.name, group)
        if gval > 0 then
            can_drop = false
            if ((not def.max_drop_level)
            or (def.max_drop_level and def.max_drop_level >= gval)) then
                can_drop = true
                break
            end
        end
    end
    return can_drop
end

function minetest.handle_node_drops(pos, drops, digger)
    local node = minetest.get_node(pos)
    -- local node_def = minetest.registered_nodes[node.name]

    if digger and digger.get_player_name and digger:get_player_name() == "" then
        digger = nil
    end

    local tool
    local tname
    if digger then
        tool = digger:get_wielded_item()
        tname = tool:get_name()
    else
        tname = "pmb_util:dig_anything"
        tool = ItemStack(tname)
    end

    local icaps = pmb_util.get_tool_caps(tname)
    if not icaps then
        tname = "__hand"
        -- minetest.log("no tool caps for "..tname)
    end

    local can_drop = true
    local hand_caps = pmb_util.get_tool_caps("__hand")

    local icap_drop = nil

    if icaps then
        can_drop = test_tcaps(icaps, node)
        -- minetest.log("got icaps")
    end
    if not can_drop and hand_caps then
        can_drop = test_tcaps(hand_caps, node)
        icap_drop = (icaps and icaps._on_get_drops and icaps._on_get_drops(tool, node, drops)) or nil
        -- minetest.log("can't drop")
    end

    if (not can_drop) and (icap_drop == nil) then
        drops = {}
    elseif icap_drop ~= nil then
        drops = icap_drop
    end

    local inv = digger and digger:get_inventory()
    if not inv then
        drop(pos, drops)
        -- minetest.log("no inventory, dropping on ground")
        return
    end

    if minetest.settings:get_bool("drop_item") then
        drop(pos, drops)
        -- minetest.log("can drop")
    elseif inv then
        for _, item in ipairs(drops) do
            drops[_] = inv:add_item("main", item)
        end
        drop(pos, drops)
        -- minetest.log("given to player")
    else
        drop(pos, drops)
        -- minetest.log("gave up and dropped")
    end
end
