local function levels(tbl, m) -- table multiplying function
	local ret = {}
	for _, n in ipairs(tbl) do
		table.insert(ret, n * m)
	end
	return ret
end

local dirt_levels = { 0.75, 1.0, 1.75 }
local stone_levels = { 0.3, 0.9, 1.0, 1.3, 1.8, 3.0, 5.0 }
local wood_levels = { 0.1, 0.15, 0.25, 0.5, 0.75, 1.0 }

minetest.override_item("", {
	tool_capabilities = {
		-- this is the object_hit_delay in 0.3, SAO code addtl. caps this to
		-- either do full damage or none at all
		full_punch_interval = 0.5,
		groupcaps = {
			dig_hand = { times = { 0.5, 0 }, uses = 0 },
			dirt = { times = levels(dirt_levels, 0.75), uses = 0, maxlevel = 3 },
			stone = { times = stone_levels, uses = 0, maxlevel = 0 },
			wood = { times = levels(wood_levels, 3), uses = 0, maxlevel = 1},
		},
		damage_groups = { fleshy = 2 },
	},
})

local tool_sound = {
	breaks = { name = "default_tool_breaks", gain = 1.0 }, -- (from 0.4.15)
}

local function register_pick(material, name, speed, uses, maxlevel)
	minetest.register_tool("tools:pick_" .. string.lower(name), {
		description = name .. " Pickaxe",
		inventory_image = "tool_pick_" .. string.lower(name) .. ".png",
		tool_capabilities = {
			groupcaps = {
				stone = { times = levels(stone_levels, speed), uses = uses, maxlevel = maxlevel },
			},
		},
		sound = tool_sound,
	})
	minetest.register_craft({
		output = "tools:pick_" .. string.lower(name),
		recipe = {
			{ material, material, material },
			{ "", "default:stick", "" },
			{ "", "default:stick", "" },
		},
	})
end

local function register_axe(material, name, speed, uses)
	minetest.register_tool("tools:axe_" .. string.lower(name), {
		description = name .. " Axe",
		inventory_image = "tool_axe_" .. string.lower(name) .. ".png",
		tool_capabilities = {
			groupcaps = {
				wood = { times = levels(wood_levels, speed), uses = uses },
			},
		},
		sound = tool_sound,
	})
	minetest.register_craft({
		output = "tools:axe_" .. string.lower(name),
		recipe = {
			{ material, material, "" },
			{ material, "default:stick", "" },
			{ "", "default:stick", "" },
		},
	})
end

local function register_shovel(material, name, speed, uses)
	minetest.register_tool("tools:shovel_" .. string.lower(name), {
		description = name .. " Shovel",
		inventory_image = "tool_shovel_" .. string.lower(name) .. ".png",
		tool_capabilities = {
			groupcaps = {
				dirt = { times = levels(dirt_levels, speed * 0.4), uses = uses },
			},
		},
		sound = tool_sound,
	})
	minetest.register_craft({
		output = "tools:shovel_" .. string.lower(name),
		recipe = {
			{ material },
			{ "default:stick" },
			{ "default:stick" },
		},
	})
end

local function register_sword(material, name, damage, uses)
	minetest.register_tool("tools:sword_" .. string.lower(name), {
		description = name .. " Sword",
		inventory_image = "tool_sword_" .. string.lower(name) .. ".png",
		tool_capabilities = {
			full_punch_interval = 0.5,
			damage_groups = { fleshy = damage },
			punch_attack_uses = uses,
		},
		sound = tool_sound,
	})

	minetest.register_craft({
		output = "tools:sword_" .. string.lower(name),
		recipe = {
			{ material },
			{ material },
			{ "default:stick" },
		},
	})
end

local function register_hoe(material, name, uses)
	minetest.register_tool("tools:hoe_" .. string.lower(name), {
		description = name .. " Hoe",
		inventory_image = "tool_hoe_" .. string.lower(name) .. ".png",
		sound = tool_sound,
		on_place = function(item, player, pointed_thing)
			if pointed_thing.type == "node" then
				local node_pos = pointed_thing.under
				local node = minetest.get_node(node_pos)

				if node.name == "default:dirt" or node.name == "default:dirt_with_grass" then
					minetest.set_node(node_pos, { name = "farming:soil" })

					item:add_wear(65535 / uses)
				end
			end

			return item
		end,
	})

	minetest.register_craft({
		output = "tools:hoe_" .. string.lower(name),
		recipe = {
			{ material, material },
			{ "", "default:stick" },
			{ "", "default:stick" },
		},
	})
end

local function register_tools(material, setname, speed, uses, maxlevel)
	register_pick(material, setname, speed, uses, maxlevel)
	register_axe(material, setname, speed, uses)
	register_shovel(material, setname, speed, uses)
	register_hoe(material, setname, uses)
end

local function register_set(material, setname, speed, uses, damage, maxlevel)
	register_tools(material, setname, speed, uses, maxlevel)
	register_sword(material, setname, damage, uses)
end

-- Smaller -> Faster
-- Increase the number that is 1 being divided by to make a tool faster
-- Decrease the number that is 1 being divided by to make a tool slower
local wood_speed = 1 / 1
local stone_speed = 1 / 2
local copper_speed = 1 / 3
local gold_speed = 1 / 10
local iron_speed = 1 / 4
local steel_speed = 1 / 6


register_set("default:wood", "Wooden", wood_speed, 50, 3, 1)
register_set("default:cobble", "Stone", stone_speed, 100, 4, 2)
register_set("minerals:ingot_copper", "Copper", copper_speed, 150, 6, 3)
register_set("minerals:ingot_gold", "Golden", gold_speed, 10, 10, 1)
register_set("minerals:ingot_iron", "Iron", iron_speed, 250, 6, 3)
register_set("minerals:ingot_steel", "Steel", steel_speed, 9000, 7, 3)
