local S = ...

local function rotate_and_place(itemstack, placer, pointed_thing)
	local p0 = pointed_thing.under
	local p1 = pointed_thing.above
	local param2 = 0

	if placer then
		local placer_pos = placer:get_pos()
		if placer_pos then
			local diff = vector.subtract(p1, placer_pos)
			param2 = core.dir_to_facedir(diff)
			-- The player places a node on the side face of the node they are standing on
			if p0.y == p1.y and math.abs(diff.x) <= 0.5 and math.abs(diff.z) <= 0.5 and diff.y < 0 then
				-- Reverse node direction
				param2 = (param2 + 2) % 4
			end
		end

		local finepos = core.pointed_thing_to_face_pos(placer, pointed_thing)
		local fpos = finepos.y % 1

		if p0.y - 1 == p1.y or (fpos > 0 and fpos < 0.5)
				or (fpos < -0.5 and fpos > -0.999999999) then
			param2 = param2 + 20
			if param2 == 21 then
				param2 = 23
			elseif param2 == 23 then
				param2 = 21
			end
		end
	end
	return core.item_place(itemstack, placer, pointed_thing, param2)
end

local function register_inverted_lbm(subnode_name, node_name, ...)
	local arg = {...}
	return core.register_lbm({
		label = "Update inverted slabs from " .. node_name,
		name = ":" .. arg[1] .. "_inverted_slab_replace",
		nodenames = arg,
		run_at_every_load = true,
		action = function(pos, node, dtime_s)
			local n = {}
			n.name = subnode_name
			n.param2 = node.param2 + 20
			core.set_node(pos, n)
		end
	})
end

local function register_wall_lbm(subnode_name, node_name, ...)
	local arg = {...}
	return core.register_lbm({
		label = "Update walls from " .. node_name,
		name = ":" .. arg[1] .. "_wall_replace",
		nodenames = arg,
		run_at_every_load = true,
		action = function(pos, node, dtime_s)
			local n = {name = subnode_name, param2 = 0}
			if node.param2 == 0 then
				n.param2 = 8
			elseif node.param2 == 1 then
				n.param2 = 16
			elseif node.param2 == 2 then
				n.param2 = 4
			elseif node.param2 == 3 then
				n.param2 = 12
			end
			core.set_node(pos, n)
		end
	})
end

subnodes.register_kind("stairs:slab", {
	node_override = {
		drawtype = "nodebox",
		paramtype = "light",
		paramtype2 = "facedir",
		node_box = {
			type = "fixed",
			fixed = {-0.5, -0.5, -0.5, 0.5, 0, 0.5},
		},

		on_place = function(itemstack, placer, pointed_thing)
			local rc = voxelgarden.call_on_rightclick(itemstack, placer, pointed_thing)
			if rc then return rc end

			local under = core.get_node(pointed_thing.under)
			local wield_item = itemstack:get_name()
			local player_name = placer and placer:get_player_name() or ""

			if under and core.get_item_group(under.name, "stairs:slab") ~= 0 then
				-- Place slab using under node orientation
				local dir = core.dir_to_facedir(vector.subtract(
					pointed_thing.above, pointed_thing.under), true)

				local p2 = under.param2

				-- Placing a slab on an upside down slab should make it right-side up
				if p2 >= 20 and dir == 8 then
					p2 = p2 - 20
				-- Same for the opposite case: slab below normal slab
				elseif p2 <= 3 and dir == 4 then
					p2 = p2 + 20
				end

				-- Else attempt to place node with proper param2
				core.item_place_node(ItemStack(wield_item), placer, pointed_thing, p2)
				if not core.is_creative_enabled(player_name) then
					itemstack:take_item()
				end
				return itemstack
			else
				return rotate_and_place(itemstack, placer, pointed_thing)
			end
		end,
	},
	volume_factor = 1/2,

	get_readable_name = function(base_description)
		return S("@1 Slab", base_description)
	end,

	get_crafts = function(n, m)
		return {
			output = n .. " 6",
			recipe = {
				{m, m, m}
			}
		}, { -- Use 2 slabs to craft a full node again (1:1)
			output = m,
			recipe = {
				{n},
				{n}
			}
		}
	end,

	after_register = function(subnode_name, node_name)
		local _, old_name, old_name2 = subnodes.make_name_subname(node_name, "stairsplus:slab")
		core.register_alias(old_name, subnode_name)
		core.register_alias(old_name2, subnode_name)
		register_inverted_lbm(subnode_name, node_name, old_name .. "_inverted", old_name2 .. "_inverted")
		voxelgarden.register_item_conversion(old_name .. "_inverted", subnode_name)
		voxelgarden.register_item_conversion(old_name2 .. "_inverted", subnode_name)

		local _, wall_name, wall_name2 = subnodes.make_name_subname(node_name, "stairsplus:wall")
		register_wall_lbm(subnode_name, node_name, wall_name, wall_name2)
		voxelgarden.register_item_conversion(wall_name, subnode_name)
		voxelgarden.register_item_conversion(wall_name2, subnode_name)
	end
})
