

pmb_hammer.player = {}
local pl = pmb_hammer.player

function pmb_hammer.get_player_defaults()
    return {
        node = nil,
    }
end

function pmb_hammer.set_paint_node(player, node_name)
    if not minetest.is_player(player) then return itemstack end
    pl[player].node = node_name
end

function pmb_hammer.get_paint_node_from_pointed(itemstack, player, pointed_thing)
    if not minetest.is_player(player) then return itemstack end
    if (not pointed_thing) or (pointed_thing.type ~= "node") then return end
    local node = minetest.get_node(pointed_thing.under)
    pl[player].node = node.name
    pl[player].param2 = node.param2
end

local function find_item_index_in_inv(inv, stack_name)
    local found_item = false
    for i = 1, inv:get_size("main") do
        local stack = inv:get_stack("main", i)
        if stack_name == stack:get_name() and stack:get_count() > 0 then
            return i
        end
    end
end

local function use_item_index_in_inventory(inv, stack_index)
    local stack = inv:get_stack("main", stack_index)
    stack:take_item(1)
    inv:set_stack("main", stack_index, stack)
    return true
end

local FULLWEAR = 65536
local function wear_tool(itemstack, group)
    local caps = itemstack:get_tool_capabilities().groupcaps
    if caps[group].uses == 0 then return itemstack end
    local wear = FULLWEAR / (caps[group].uses)
    itemstack:add_wear(wear)
    return itemstack
end

local function do_node_sound(pos, node)
    local sound = minetest.registered_nodes[node.name].sounds.dug
    minetest.sound_play(sound.name, {
        gain = sound.gain,
        pos = pos,
    })
end

function pmb_hammer.paint_node(itemstack, player, pointed_thing)
    if (not pointed_thing) or (pointed_thing.type ~= "node") then return end
    if not pl[player].node then return end
    -- make sure you have a stack
    local inv = player:get_inventory()
    local stack_index = find_item_index_in_inv(inv, pl[player].node)
    if not stack_index then return end

    -- figure out if the node you're pointing at can actually be painted
    local tool_caps = itemstack:get_tool_capabilities().groupcaps
    local node = minetest.get_node(pointed_thing.under)
    if node.name == pl[player].node then return end
    local node_caps = minetest.registered_nodes[node.name].groups
    local can_paint = false
    local group
    -- check to make sure you could dig this
    for groupname, groupcap in pairs(tool_caps) do
        if node_caps[groupname]
        and (groupcap.maxlevel
        and groupcap.maxlevel >= node_caps[groupname]) then
            can_paint = true
            group = groupname
            break
        end
    end
    if not can_paint then return end
    if use_item_index_in_inventory(inv, stack_index) then
        local stacks = minetest.get_node_drops(node, itemstack)
        for i, stack in pairs(stacks) do
            stack = inv:add_item("main", stack)
            if stack:get_count() > 0 then
                minetest.add_item(player:get_pos(), stack)
            end
        end
        if group then itemstack = wear_tool(itemstack, group) end
        node.name = pl[player].node
        node.param2 = pl[player].param2
        minetest.set_node(pointed_thing.under, node)
        do_node_sound(pointed_thing.under, node)
    end
    return itemstack
end

function pmb_hammer.init_player(player, last_login)
    pl[player] = pmb_hammer.get_player_defaults()
    pmb_hammer.set_paint_node(player, "pmb_soil:dirt")
end
minetest.register_on_joinplayer(pmb_hammer.init_player)
