-- Climbable nodes
local S = minetest.get_translator(minetest.get_current_modname())

local function rotate_climbable(pos, node, user, mode)
	if mode == screwdriver.ROTATE_FACE then
		local r = screwdriver.rotate.wallmounted(pos, node, mode)
		node.param2 = r
		minetest.swap_node(pos, node)
		return true
	end
	return false
end

---Updates the trapdoor above (if any).
---
---@param pos mt.Vector The position of the ladder.
---@param event "place" | "destruct" The place or destruct event.
function mcl_core.update_trapdoor(pos, event)
	local top_pos = vector.offset(pos, 0, 1, 0)
	local top_node = minetest.get_node_or_nil(top_pos)

	if top_node and minetest.get_item_group(top_node.name, "trapdoor") == 2 then
		local new_name = top_node.name
		if event == "place" then
			new_name = string.gsub(new_name, "open$", "ladder")
		elseif event == "destruct" then
			new_name = string.gsub(new_name, "ladder$", "open")
		end

		-- If node above is an opened trapdoor
		minetest.swap_node(top_pos, {
			name = new_name,
			param1 = top_node.param1,
			param2 = top_node.param2,
		})
	end
end

-- TODO: Move ladders into their own API.
minetest.register_node("mcl_core:ladder", {
	description = S("Ladder"),
	_doc_items_longdesc = S(
		"A piece of ladder which allows you to climb vertically. Ladders can only be placed on the side of solid blocks and not on glass, leaves, ice, slabs, glowstone, nor sea lanterns."),
	drawtype = "signlike",
	is_ground_content = false,
	tiles = { "default_ladder.png" },
	inventory_image = "default_ladder.png",
	wield_image = "default_ladder.png",
	paramtype = "light",
	sunlight_propagates = true,
	paramtype2 = "wallmounted",
	walkable = true,
	climbable = true,
	node_box = {
		type = "wallmounted",
		wall_side = { -0.5, -0.5, -0.5, -7 / 16, 0.5, 0.5 },
	},
	selection_box = {
		type = "wallmounted",
		wall_side = { -0.5, -0.5, -0.5, -7 / 16, 0.5, 0.5 },
	},
	stack_max = 64,
	groups = {
		handy = 1,
		axey = 1,
		attached_node = 1,
		deco_block = 1,
		dig_by_piston = 1,
		ladder = 1
	},
	sounds = mcl_sounds.node_sound_wood_defaults(),
	node_placement_prediction = "",
	-- Restrict placement of ladders
	on_place = function(itemstack, placer, pointed_thing)
		if pointed_thing.type ~= "node" then
			-- no interaction possible with entities
			return itemstack
		end

		local under = pointed_thing.under
		local node = minetest.get_node(under)
		local def = minetest.registered_nodes[node.name]
		if not def then
			return itemstack
		end
		local groups = def.groups

		-- Don't allow to place the ladder at particular nodes
		if (groups and (groups.glass or groups.leaves or groups.slab)) or
			node.name == "mcl_core:ladder" or node.name == "mcl_core:ice" or node.name == "mcl_nether:glowstone" or node.name == "mcl_ocean:sea_lantern" then
			return itemstack
		end

		-- Check special rightclick action of pointed node
		if def and def.on_rightclick then
			if not placer:get_player_control().sneak then
				return def.on_rightclick(under, node, placer, itemstack,
					pointed_thing) or itemstack, false
			end
		end
		local above = pointed_thing.above

		-- Ladders may not be placed on ceiling or floor
		if under.y ~= above.y then
			return itemstack
		end
		local idef = itemstack:get_definition()
		local success = minetest.item_place_node(itemstack, placer, pointed_thing)

		if success then
			if idef.sounds and idef.sounds.place then
				minetest.sound_play(idef.sounds.place, { pos = above, gain = 1 }, true)
			end
		end
		return itemstack
	end,
	after_destruct = function(pos, old)
		mcl_core.update_trapdoor(pos, "destruct")
	end,
	after_place_node = function(pos)
		mcl_core.update_trapdoor(pos, "place")
	end,
	_mcl_blast_resistance = 0.4,
	_mcl_hardness = 0.4,
	on_rotate = rotate_climbable,
})


minetest.register_node("mcl_core:vine", {
	description = S("Vines"),
	_doc_items_longdesc = S(
		"Vines are climbable blocks which can be placed on the sides of solid full-cube blocks. Vines slowly grow and spread."),
	drawtype = "signlike",
	tiles = { "mcl_core_vine.png" },
	color = "#48B518",
	inventory_image = "mcl_core_vine.png",
	wield_image = "mcl_core_vine.png",
	paramtype = "light",
	sunlight_propagates = true,
	paramtype2 = "colorwallmounted",
	palette = "[combine:16x2:0,0=mcl_core_palette_foliage.png",
	walkable = false,
	climbable = true,
	buildable_to = true,
	selection_box = {
		type = "wallmounted",
	},
	stack_max = 64,
	groups = {
		handy = 1,
		axey = 1,
		shearsy = 1,
		swordy = 1,
		deco_block = 1,
		dig_by_piston = 1,
		destroy_by_lava_flow = 1,
		compostability = 50,
		flammable = 2,
		fire_encouragement = 15,
		fire_flammability = 100,
		foliage_palette_wallmounted = 1,
		ladder = 1
	},
	sounds = mcl_sounds.node_sound_leaves_defaults(),
	drop = "",
	_mcl_shears_drop = true,
	node_placement_prediction = "",
	-- Restrict placement of vines
	on_place = function(itemstack, placer, pointed_thing)
		if pointed_thing.type ~= "node" then
			-- no interaction possible with entities
			return itemstack
		end

		local under = pointed_thing.under
		local node = minetest.get_node(under)
		local def = minetest.registered_nodes[node.name]
		if not def then return itemstack end

		-- Check special rightclick action of pointed node
		if def and def.on_rightclick then
			if not placer:get_player_control().sneak then
				return def.on_rightclick(under, node, placer, itemstack,
					pointed_thing) or itemstack, false
			end
		end

		-- Only place on full cubes
		if not mcl_core.supports_vines(node.name) then
			return itemstack
		end

		local above = pointed_thing.above

		-- Vines may not be placed on top or below another block
		if under.y ~= above.y then
			return itemstack
		end
		local idef = itemstack:get_definition()
		local itemstack, success = minetest.item_place_node(itemstack, placer, pointed_thing)

		if success then
			if idef.sounds and idef.sounds.place then
				minetest.sound_play(idef.sounds.place, { pos = above, gain = 1 }, true)
			end
		end
		return itemstack
	end,

	on_construct = function(pos)
		local node = minetest.get_node(pos)
		local foliage_palette_index = mcl_util.get_palette_indexes_from_pos(pos).foliage_palette_index
		if node.name == "mcl_core:vine" then
			local biome_param2 = foliage_palette_index
			local rotation_param2 = node.param2
			local final_param2 = (biome_param2 * 8) + rotation_param2
			if node.param2 ~= final_param2 and rotation_param2 < 6 then
				node.param2 = final_param2
				minetest.swap_node(pos, node)
			end
		end
	end,

	-- If dug, also dig a “dependant” vine below it.
	-- A vine is dependant if it hangs from this node and has no supporting block.
	on_dig = function(pos, node, digger)
		local below = vector.offset(pos, 0, -1, 0)
		local belownode = minetest.get_node(below)
		minetest.node_dig(pos, node, digger)
		if belownode.name == node.name and (not mcl_core.check_vines_supported(below, belownode)) then
			minetest.registered_nodes[node.name].on_dig(below, node, digger)
		end
	end,
	after_destruct = function(pos, old)
		mcl_core.update_trapdoor(pos, "destruct")
	end,
	after_place_node = function(pos)
		mcl_core.update_trapdoor(pos, "place")
	end,


	_mcl_blast_resistance = 0.2,
	_mcl_hardness = 0.2,
	on_rotate = false,
})
