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

		local finedir = core.facedir_to_dir(param2)
		local rotate = false
		if finedir.z == 1 then -- z+
			rotate = finepos.z > 0.5
		elseif finedir.z == -1 then -- z-
			rotate = finepos.z < 0.5
		elseif finedir.x == 1 then -- x+
			rotate = finepos.x > 0.5
		elseif finedir.x == -1 then -- x-
			rotate = finepos.x < 0.5
		end

		if rotate then
			local mod4 = param2 % 4
			if mod4 == 0 or mod4 == 1 then
				param2 = (mod4 + 2) % 24
			elseif mod4 == 2 or mod4 == 3 then
				param2 = (mod4 - 2) % 24
			end
		end

		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 == 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 top panels from " .. node_name,
		name = ":" .. arg[1] .. "_top_panel_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
			if n.param2 == 21 then
				n.param2 = 23
			elseif n.param2 == 23 then
				n.param2 = 21
			end
			core.set_node(pos, n)
		end
	})
end

local function register_vertical_lbm(subnode_name, node_name, ...)
	local arg = {...}
	return core.register_lbm({
		label = "Update vertical panels from " .. node_name,
		name = ":" .. arg[1] .. "_vertical_panel_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 = 12
			elseif node.param2 == 1 then
				n.param2 = 9
			elseif node.param2 == 2 then
				n.param2 = 5
			elseif node.param2 == 3 then
				n.param2 = 14
			end
			core.set_node(pos, n)
		end
	})
end

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

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

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

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

	after_register = function(subnode_name, node_name)
		local _, old_basename, old_basename2 = subnodes.make_name_subname(node_name, "stairsplus:panel")
		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")
		register_inverted_lbm(subnode_name, node_name, old_basename2 .. "_top")
		register_vertical_lbm(subnode_name, node_name, old_basename .. "_vertical")
		register_vertical_lbm(subnode_name, node_name, old_basename2 .. "_vertical")
		voxelgarden.register_item_conversion(old_basename .. "_top", subnode_name)
		voxelgarden.register_item_conversion(old_basename2 .. "_top", subnode_name)
		voxelgarden.register_item_conversion(old_basename .. "_vertical", subnode_name)
		voxelgarden.register_item_conversion(old_basename2 .. "_vertical", subnode_name)
	end,
})
