PyuTest.deal_damage = function(target, damage, reason)
	local hp = target:get_hp()

	if hp > 0 then
		target:set_hp(hp - damage, reason)
	end
end

local function custom_damage(table)
	return {
		type = "set_hp",
		_pyutest = table or {
			type = "unknown"
		}
	}
end

PyuTest.DAMAGE_TYPES = {
	explosion = function (range)
		return custom_damage{
			type = "explosion",
			range = range
		}
	end,
	fireworks = function ()
		return custom_damage{
			type = "fireworks",
		}
	end,
	burning = function ()
		return custom_damage{
			type = "burning"
		}
	end,
	projectile = function (projectile, shooter)
		local name
		local entity = shooter:get_luaentity()
		if entity ~= nil then
			name = entity:get_properties().nametag
		else
			name = shooter:get_player_name()
		end

		return custom_damage{
			type = "projectile",
			projectile = projectile,
			owner = name
		}
	end,
	magic = function ()
		return custom_damage{
			type = "magic",
		}
	end,
	freezing = function ()
		return custom_damage{
			type = "freezing",
		}
	end,
	lightning = function ()
		return custom_damage{
			type = "lightning"
		}
	end,
	starvation = function ()
		return custom_damage{
			type = "starvation"
		}
	end,
	shot = function (name)
		return custom_damage{
			type = "shot",
			objname = name,
		}
	end
}

PyuTest.mt_damage_to_pyutest_damage = function(reason)
	return reason._pyutest or reason
end

core.register_on_dieplayer(function(player, reason)
	local playername = player:get_player_name()

	local message = string.format("%s died", playername)
	if reason.type == "fall" then
		message = string.format("%s fell from a high place", playername)
	elseif reason.type == "drown" then
		message = string.format("%s drowned", playername)
	elseif reason.type == "respawn" then
		return
	elseif reason.type == "punch" then
		local entity = reason.object:get_luaentity()
		if entity ~= nil then
			local name = reason.object:get_properties().nametag
			if name == "" then
				name = "an unnamed monster!"
			end
			message = string.format("%s was slain by %s", playername, name)
		elseif reason.object:is_player() then
			local name = reason.object:get_player_name()
			message = string.format("%s was slain by %s", playername, name)
		end
	elseif reason.type == "set_hp" then
		local newreason = PyuTest.mt_damage_to_pyutest_damage(reason)

		if newreason.type == "explosion" then
			message = string.format("%s blew up", playername)
		elseif newreason.type == "fireworks" then
			message = string.format("%s went off with a bang", playername)
		elseif newreason.type == "burning" then
			message = string.format("%s burned to death", playername)
		elseif newreason.type == "projectile" then
			local p = newreason.owner or newreason.projectile
			if p ~= nil then
				message = string.format("%s was shot by %s", playername, p)
			else
				message = string.format("%s was shot by something", playername)
			end
		elseif newreason.type == "magic" then
			message = string.format("%s was killed by magic", playername)
		elseif newreason.type == "freezing" then
			message = string.format("%s froze to death", playername)
		elseif newreason.type == "lightning" then
			message = string.format("%s was struck by lightning", playername)
		elseif newreason.type == "starvation" then
			message = string.format("%s starved to death", playername)
		elseif newreason.type == "shot" then
			message = string.format("%s was shot by %s", newreason.objname)
		end
	elseif reason.type == "node_damage" then
		local desc = core.registered_nodes[reason.node].description or "a block"
		message = string.format("%s was killed by %s", playername, desc)
	end

	core.chat_send_all(message)
end)
