if minetest.settings:get_bool("lzr_particles_splash", true) ~= true then
	minetest.log("action", "[lzr_splash] Splash particles are disabled")
	return
end

local playerstates = {}

local GRAVITY = 9.81
local STEP_EFFECT_UPDATE = 0.1
local STEP_THRESHOLD = 0.1

local WATER_PARTICLES = 10
local SAND_PARTICLES = 2
local SEABED_PARTICLES = 1
local LEAVES_PARTICLES = 1

local splash = function(pos, particlenode, amount)
	minetest.add_particlespawner({
		amount = amount,
		time = 0.05,
		exptime = {
			min = 1,
			max = 1.5,
		},
		pos = {
			min = vector.offset(pos, -0.15, 0.025, -0.15),
			max = vector.offset(pos, 0.15, 0.05, 0.15),
		},
		vel = {
			min = vector.new(-2, 2, -2),
			max = vector.new(2, 4, 2),
		},
		bounce = 0.5,
		drag = vector.new(5, 0, 5),
		acc = vector.new(0, -GRAVITY, 0),
		collisiondetection = true,
		node = particlenode,
	})
end

-- Takes a node and checks if splash particle are allowed to
-- spawn here. Returns true if this is the case.
local function can_splash_into(node)
	local def = minetest.registered_nodes[node.name]
	if not def then
		return false
	-- We can splash into all non-walkable non-water nodes
	elseif not def.walkable and minetest.get_item_group(node.name, "water") == 0 then
		return true
	else
		return false
	end
end

local function step_effect(player)
	local pos = player:get_pos()
	local feet_y = pos.y
	pos.y = math.ceil(pos.y)
	local nodei = minetest.get_node(pos)
	local below = vector.offset(pos, 0, -1, 0)
	local nodeb = minetest.get_node(below)
	local offset = vector.zero()
	local splashy_nodes = {
		{ "water", WATER_PARTICLES },
		{ "sand", SAND_PARTICLES },
		{ "seabed", SEABED_PARTICLES },
		{ "leaves", LEAVES_PARTICLES },
	}

	for s=1, #splashy_nodes do
		local id = splashy_nodes[s][1]
		local pcount = splashy_nodes[s][2]
		local group = id
		if minetest.get_item_group(nodei.name, group) ~= 0 then
			local above = vector.offset(pos, 0, 1, 0)
			local nodea = minetest.get_node(above)
			if can_splash_into(nodea) then
				local offset
				if minetest.get_item_group(nodei.name, "slab") == 1 then
					offset = vector.new(0, 0.125, 0)
				else
					offset = vector.new(0, 0.5, 0)
				end
				splash(vector.add(pos, offset), nodei, pcount)
			end
		elseif minetest.get_item_group(nodeb.name, group) ~= 0 then
			if can_splash_into(nodei) then
				local offset
				if minetest.get_item_group(nodeb.name, "slab") == 1 then
					offset = vector.new(0, -0.9375, 0)
				else
					offset = vector.new(0, -0.5, 0)
				end
				splash(vector.add(pos, offset), nodeb, pcount)
			end
		end
	end
end

minetest.register_globalstep(function(dtime)
	local players = minetest.get_connected_players()
	for p=1, #players do
		local player = players[p]
		local pname = player:get_player_name()
		if not playerstates[pname] then
			playerstates[pname] = {
				step_effect_timer = 0,
				last_pos = player:get_pos(),
			}
		else
			local state = playerstates[pname]
			state.step_effect_timer = state.step_effect_timer + dtime
			if state.step_effect_timer >= STEP_EFFECT_UPDATE then
				state.step_effect_timer = 0
				if vector.distance(player:get_pos(), state.last_pos) >= STEP_THRESHOLD then
					step_effect(player)
				end
				state.last_pos = player:get_pos()
			end
		end
	end
end)

minetest.register_on_leaveplayer(function(player)
	playerstates[player:get_player_name()] = nil
end)
