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 finepos = vector.apply(
			core.pointed_thing_to_face_pos(placer, pointed_thing),
			function(a) return a % 1 end
		)

		if finepos.y == 0.5 then -- floor/ceiling
			local mod4 = 0
			if finepos.x > 0.5 and finepos.z < 0.5 then
				mod4 = 0
			elseif finepos.x < 0.5 and finepos.z < 0.5 then
				mod4 = 1
			elseif finepos.x < 0.5 and finepos.z > 0.5 then
				mod4 = 2
			elseif finepos.x > 0.5 and finepos.z > 0.5 then
				mod4 = 3
			end
			param2 = (math.floor(param2 / 4) + mod4) % 24

			if p0.y - 1 == p1.y or (finepos.y > 0 and finepos.y < 0.5)
					or (finepos.y < -0.5 and finepos.y > -0.999999999) then
				param2 = param2 + 20
				if param2 == 23 then
					param2 = 22
				elseif param2 == 22 then
					param2 = 23
				elseif param2 == 21 then
					param2 = 20
				elseif param2 == 20 then
					param2 = 21
				end
			end
		elseif finepos.x == 0.5 then -- X wall
			local sub = (p0 - p1).x -- 1 if X+, -1 if X-
			if finepos.y > 0.5 and finepos.z < 0.5 then
				param2 = sub == 1 and 1 or 0
			elseif finepos.y < 0.5 and finepos.z < 0.5 then
				param2 = sub == 1 and 20 or 21
			elseif finepos.y < 0.5 and finepos.z > 0.5 then
				param2 = sub == 1 and 18 or 7
			elseif finepos.y > 0.5 and finepos.z > 0.5 then
				param2 = sub == 1 and 5 or 14
			end
		elseif finepos.z == 0.5 then -- Z wall
			local sub = (p0 - p1).z -- 1 if Z+, -1 if Z-
			if finepos.y > 0.5 and finepos.x < 0.5 then
				param2 = sub == 1 and 16 or 2
			elseif finepos.y < 0.5 and finepos.x < 0.5 then
				param2 = sub == 1 and 20 or 18
			elseif finepos.y < 0.5 and finepos.x > 0.5 then
				param2 = sub == 1 and 12 or 22
			elseif finepos.y > 0.5 and finepos.x > 0.5 then
				param2 = sub == 1 and 0 or 14
			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 top microblocks from " .. node_name,
		name = ":" .. arg[1] .. "_top_micro_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

subnodes.register_kind("stairsplus:micro", {
	node_override = {
		drawtype = "nodebox",
		paramtype = "light",
		paramtype2 = "facedir",
		sunlight_propagates = true,
		node_box = {
			type = "fixed",
			fixed = {-0.5, -0.5, 0, 0, 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

			return rotate_and_place(itemstack, placer, pointed_thing)
		end,
	},
	volume_factor = 1/8,

	get_crafts = function(n, m)
		return {
			output = n .. " 8",
			recipe = {
				{"group:stick"},
				{m}
			}
		},
		{
			output = m,
			recipe = {
				{n, n, n},
				{n, n, n},
				{n, n, n}
			}
		}
	end,

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

	after_register = function(subnode_name, node_name)
		local _, old_basename, old_basename2 = subnodes.make_name_subname(node_name, "stairsplus:micro")
		core.register_alias(old_basename .. "_bottom", subnode_name)
		core.register_alias(old_basename2 .. "_bottom", subnode_name)
		register_inverted_lbm(subnode_name, node_name, old_basename .. "_top", old_basename2 .. "_top")
		voxelgarden.register_item_conversion(old_basename .. "_top", subnode_name)
		voxelgarden.register_item_conversion(old_basename2 .. "_top", subnode_name)
	end,
})
