-- HINWEIS: Dies ist eine modifizierte Version mit Deutsch als primärer Quellsprache.
-- Der Übersetzungsmechanismus bleibt für andere Sprachen erhalten.

local minetest = minetest

local mailbox = {}
_G.mailbox = mailbox

-- Das Übersetzungssystem bleibt aktiv!
local S = minetest.get_translator("mailbox")
local FS = function(...) return minetest.formspec_escape(S(...)) end

local formspec_bg = ""
local get_hotbar_bg = function() return "" end
if minetest.global_exists("default") then
	formspec_bg = default.gui_bg .. default.gui_bg_img .. default.gui_slots
	get_hotbar_bg = default.get_hotbar_bg
end

local function noop() end

mailbox.UNRENT_FAIL_REASONS = {
	ERR_NOT_EMPTY = S("Der Briefkasten ist nicht leer."),
	ERR_NO_PRIVILEGE = S("Du darfst diesen Briefkasten nicht kündigen."),
}

local function can_manage(pos, player)
	local meta = minetest.get_meta(pos)
	local owner = meta:get_string("owner")
	local pname = player:get_player_name()
	if owner ~= ""
		and owner ~= pname
		and not minetest.check_player_privs(pname, { protection_bypass = true }) then
		return false
	end
	return true
end

local function can_set_owner(player)
	local pname = player:get_player_name()
	return minetest.check_player_privs(pname, { protection_bypass = true })
end

function mailbox.set_owner(pos, pname)
	local node = minetest.get_node(pos)
	local meta = minetest.get_meta(pos)
	meta:set_string("owner", pname)
	if pname == "" then
		meta:set_string("infotext", S("Freier Briefkasten – Rechtsklick zum Beanspruchen"))
		node.name = "mailbox:mailbox_free"
		minetest.swap_node(pos, node)
	else
		meta:set_string("infotext", S("Briefkasten von @1", pname))
		if node.name == "mailbox:mailbox_free" then
			node.name = "mailbox:mailbox"
			minetest.swap_node(pos, node)
		end
	end
end

function mailbox.rent_mailbox(pos, player)
	return mailbox.set_owner(pos, player:get_player_name())
end

function mailbox.unrent(pos, player, force, drop_pos)
	local meta = minetest.get_meta(pos)
	if not can_manage(pos, player) then
		return false, "ERR_NO_PRIVILEGE"
	end

	local inv = meta:get_inventory()
	if not force then
		if not inv:is_empty("mailbox") then
			return false, "ERR_NOT_EMPTY"
		end
	end

	drop_pos = drop_pos or pos
	for _, stack in pairs(inv:get_list("mailbox")) do
		minetest.add_item(drop_pos, stack)
	end

	inv:set_list("mailbox", {})
	mailbox.set_owner(pos, "")

	return true
end

local on_construct = function(pos)
	local meta = minetest.get_meta(pos)
	local inv = meta:get_inventory()
	inv:set_size("mailbox", 8 * 4)
	inv:set_size("drop", 1)
end

local after_place_node = function(pos, player)
	local pname = player:get_player_name()
	mailbox.set_owner(pos, pname)
end

local show_formspec = function(pos, owner, pname, pl_can_manage)
	-- HINZUGEFÜGT: Prüfen, um welchen Briefkasten-Typ es sich handelt
	local node = minetest.get_node(pos)
	local label_text

	if node.name == "mailbox:letterbox" then
		label_text = "Sende deine Bücher/Briefe\nan @1"
	else
		label_text = "Sende deine Waren\nan @1"
	end

	local spos = pos.x .. "," .. pos.y .. "," .. pos.z
	local formspec = "size[8,5.5]" .. formspec_bg .. default.get_hotbar_bg(0, 1.5) ..
		-- HINZUGEFÜGT: Die neue Variable für den Text wird hier verwendet
		"label[0,0;" .. FS(label_text, owner) .. ":]" ..
		"list[nodemeta:" .. spos .. ";drop;3.5,0;1,1;]" ..
		"list[current_player;main;0,1.5;8,1;]" ..
		"list[current_player;main;0,2.75;8,3;8]" ..
		"listring[nodemeta:" .. spos .. ";drop]" ..
		"listring[current_player;main]"

	if pl_can_manage then
		formspec = formspec .. "button_exit[6,0;2,1;manage;" .. FS("Verwalten") .. "]"
	end
	minetest.show_formspec(pname, "mailbox:mailbox_" .. spos, formspec)
end

local show_manage_formspec = function(pos, pname, selected)
	local spos = pos.x .. "," .. pos.y .. "," .. pos.z
	local formspec = "size[8,9.5]" .. formspec_bg .. get_hotbar_bg(0, 5.5) ..
		"checkbox[0,0;books_only;" .. FS("Nur Bücher und Briefe erlauben") .. ";" .. selected .. "]" ..
		"list[nodemeta:" .. spos .. ";mailbox;0,1;8,4;]" ..
		"list[current_player;main;0,5.5;8,1;]" ..
		"list[current_player;main;0,6.75;8,3;8]" ..
		"listring[nodemeta:" .. spos .. ";mailbox]" ..
		"listring[current_player;main]" ..
		"button_exit[5,0;2,1;unrent;" .. FS("Kündigen") .. "]" ..
		"button_exit[7,0;1,1;exit;X]"
	minetest.show_formspec(pname, "mailbox:mailbox_" .. spos, formspec)
end

local show_change_owner_formspec = function(pos, pname)
	local spos = pos.x .. "," .. pos.y .. "," .. pos.z
	local formspec = "field[new_owner;" .. FS("Neuer Besitzer:") .. ";]"
	minetest.show_formspec(pname, "mailbox:mailbox_" .. spos, formspec)
end

local on_rightclick = function(pos, node, player, itemstack, pointed_thing)
	if not player:is_player() then return end

	local nodename = node.name
	if itemstack:get_name() == "mailbox:unrenter" then
		local drop_pos = pointed_thing.above
		mailbox.unrent(pos, player, true, drop_pos)
		return itemstack
	end

	local pname = player:get_player_name()
	local meta = minetest.get_meta(pos)
	local owner = meta:get_string("owner")
	if owner == pname then
		-- Owner formspec
		local selected = nodename == "mailbox:letterbox" and "true" or "false"
		show_manage_formspec(pos, pname, selected)
	else
		-- Mailer formspec
		show_formspec(pos, owner, pname, can_manage(pos, player))
	end
end

local on_punch = function(pos, node, player, pointed_thing)
	if not player:is_player() then
		return minetest.node_punch(pos, node, player, pointed_thing)
	end

	local wielded = player:get_wielded_item()
	if wielded:get_name() ~= "mailbox:unrenter" then
		return minetest.node_punch(pos, node, player, pointed_thing)
	end

	local pname = player:get_player_name()
	if not can_set_owner(player) then
		minetest.chat_send_player(pname, S("Du kannst den Besitzer anderer Briefkästen nicht ändern."))
		return
	end

	show_change_owner_formspec(pos, pname)
end

local free_on_rightclick = function(pos, _, player, itemstack)
	if not player:is_player() then return end
	if itemstack:get_name() == "mailbox:unrenter" then return end

	mailbox.rent_mailbox(pos, player)
end

local can_dig = function(pos, player)
	if not can_manage(pos, player) then
		return false
	end

	local meta = minetest.get_meta(pos)
	local inv = meta:get_inventory()
	return inv:is_empty("mailbox")
end

local allowed_books = {
	["default:book_written"] = true,
    ["letters:letter_written"] = true,
	["mcl_books:written_book"] = true,
}

local allow_metadata_inventory_put = function(pos, listname, _, stack, player)
	if listname == "mailbox" then
		return can_manage(pos, player) and stack:get_count() or 0
	elseif listname == "drop" then
		local node = minetest.get_node(pos)
		if node.name == "mailbox:letterbox" and not allowed_books[stack:get_name()] then
			minetest.chat_send_player(player:get_player_name(), S("Nur Bücher und Briefe werden akzeptiert."))
			return 0
		end
		local meta = minetest.get_meta(pos)
		local inv = meta:get_inventory()
		if inv:room_for_item("mailbox", stack) then
			return stack:get_count()
		else
			minetest.chat_send_player(player:get_player_name(), S("Briefkasten voll."))
		end
	end
	return 0
end

local on_metadata_inventory_put = function(pos, listname, _, stack)
	if listname == "drop" then
		local meta = minetest.get_meta(pos)
		local inv = meta:get_inventory()
		inv:set_stack("drop", 1, inv:add_item("mailbox", stack))
	end
end

local allow_metadata_inventory_move = function(pos, from_list, _, to_list, _, count, player)
	if from_list ~= to_list then
		return 0
	elseif from_list == "mailbox" then
		return can_manage(pos, player) and count or 0
	elseif from_list == "drop" then
		return count
	end
	return 0
end

local allow_metadata_inventory_take = function(pos, listname, _, stack, player)
	if listname == "mailbox" then
		return can_manage(pos, player) and stack:get_count() or 0
	elseif listname == "drop" then
		return stack:get_count()
	end
	return 0
end

local after_dig_node = nil
local mail_pipeworks = nil
if minetest.global_exists("pipeworks") then
	mail_pipeworks = {
		insert_object = function(pos, _, stack, _)
			local meta = minetest.get_meta(pos)
			local inv = meta:get_inventory()
			return inv:add_item("mailbox", stack)
		end,
		can_insert = function(pos, _, stack, _)
			local meta = minetest.get_meta(pos)
			local inv = meta:get_inventory()
			return inv:room_for_item("mailbox", stack)
		end,
		input_inventory = "mailbox",
		connect_sides = { left = 1, right = 1, back = 1, bottom = 1, top = 1 },
	}

	local old_after_place_node = after_place_node
	after_place_node = function(...)
		old_after_place_node(...)
		pipeworks.scan_for_tube_objects(...)
	end

	after_dig_node = pipeworks.after_dig
end

minetest.register_on_player_receive_fields(function(player, formname, fields)
	if not formname:match("mailbox:mailbox_") then
		return
	end
	local pos = minetest.string_to_pos(formname:sub(17))
	local node = minetest.get_node(pos)
	local pname = player:get_player_name()
	local nodegroup = minetest.get_item_group(node.name, "mailbox")
	if fields.new_owner and nodegroup ~= 0 then
		if not can_set_owner(player) then
			minetest.chat_send_player(pname, S("Du kannst den Besitzer anderer Briefkästen nicht ändern."))
			return true
		end

		mailbox.set_owner(pos, fields.new_owner)
	elseif nodegroup ~= 1 then
		minetest.chat_send_player(pname, S("Der Block ist kein Briefkasten mehr."))
	elseif fields.unrent then
		local status, reason = mailbox.unrent(pos, player)
		if not status then
			minetest.chat_send_player(pname, mailbox.UNRENT_FAIL_REASONS[reason])
		end
		return true
	elseif fields.books_only then
		if not can_manage(pos, player) then
			minetest.chat_send_player(pname, S("Du kannst diesen Briefkasten nicht verwalten."))
			return true
		end
		node.name = node.name == "mailbox:mailbox" and "mailbox:letterbox" or "mailbox:mailbox"
		minetest.swap_node(pos, node)
	elseif fields.manage then
		if not can_manage(pos, player) then
			minetest.chat_send_player(pname, S("Du kannst diesen Briefkasten nicht verwalten."))
			return true
		end
		local selected = node.name == "mailbox:letterbox" and "true" or "false"
		show_manage_formspec(pos, pname, selected)
	end
	return true
end)

minetest.register_node("mailbox:mailbox", {
	description = S("Briefkasten"),
	tiles = {
		"mailbox_mailbox_top.png", "mailbox_mailbox_bottom.png",
		"mailbox_mailbox_side.png", "mailbox_mailbox_side.png",
		"mailbox_mailbox.png", "mailbox_mailbox.png",
	},
	groups = {
		mailbox = 1,
		cracky = 3,
		oddly_breakable_by_hand = 1,
		tubedevice = 1,
		tubedevice_receiver = 1
	},
	on_rotate = minetest.global_exists("screwdriver") and screwdriver.rotate_simple or nil,
	sounds = xcompat.sounds.node_sound_stone_defaults(),
	paramtype2 = "facedir",
	on_construct = on_construct,
	after_place_node = after_place_node,
	after_dig_node = after_dig_node,
	on_rightclick = on_rightclick,
	on_punch = on_punch,
	can_dig = can_dig,
	on_metadata_inventory_put = on_metadata_inventory_put,
	allow_metadata_inventory_put = allow_metadata_inventory_put,
	allow_metadata_inventory_take = allow_metadata_inventory_take,
	allow_metadata_inventory_move = allow_metadata_inventory_move,
	tube = mail_pipeworks,
	on_blast = noop,
})

minetest.register_node("mailbox:mailbox_free", {
	description = S("Briefkasten zur Miete"),
	tiles = {
		"mailbox_mailbox_free_top.png", "mailbox_mailbox_free_bottom.png",
		"mailbox_mailbox_free_side.png", "mailbox_mailbox_free_side.png",
		"mailbox_mailbox_free.png", "mailbox_mailbox_free.png",
	},
	groups = {
		mailbox = 2,
		cracky = 3,
		oddly_breakable_by_hand = 1,
		tubedevice = 1,
		tubedevice_receiver = 1
	},
	on_rotate = minetest.global_exists("screwdriver") and screwdriver.rotate_simple or nil,
	sounds = xcompat.sounds.node_sound_stone_defaults(),
	paramtype2 = "facedir",
	drop = "mailbox:mailbox",
	on_construct = on_construct,
	on_rightclick = free_on_rightclick,
})

minetest.register_node("mailbox:letterbox", {
	tiles = {
		"mailbox_letterbox_top.png", "mailbox_letterbox_bottom.png",
		"mailbox_letterbox_side.png", "mailbox_letterbox_side.png",
		"mailbox_letterbox.png", "mailbox_letterbox.png",
	},
	groups = {
		mailbox = 1,
		cracky = 3,
		oddly_breakable_by_hand = 1,
		not_in_creative_inventory = 1,
		tubedevice = 1,
		tubedevice_receiver = 1
	},
	on_rotate = minetest.global_exists("screwdriver") and screwdriver.rotate_simple or nil,
	sounds = xcompat.sounds.node_sound_stone_defaults(),
	paramtype2 = "facedir",
	drop = "mailbox:mailbox",
	on_construct = on_construct,
	after_place_node = after_place_node,
	after_dig_node = after_dig_node,
	on_rightclick = on_rightclick,
	on_punch = on_punch,
	can_dig = can_dig,
	on_metadata_inventory_put = on_metadata_inventory_put,
	allow_metadata_inventory_put = allow_metadata_inventory_put,
	allow_metadata_inventory_take = allow_metadata_inventory_take,
	allow_metadata_inventory_move = allow_metadata_inventory_move,
	tube = mail_pipeworks,
})

minetest.register_tool("mailbox:unrenter", {
	short_description = S("Briefkastenbesitzer ändern"),
	description = table.concat({
		S("Briefkastenbesitzer ändern"),
		S("Schlagen: Besitzer ändern"),
		S("Rechtsklick: Besitzer entfernen")
	}, "\n"),
	inventory_image = "mailbox_unrent.png",
})

local materials = xcompat.materials
minetest.register_craft({
	output = "mailbox:mailbox",
	recipe = {
		{ materials.steel_ingot, materials.steel_ingot, materials.steel_ingot },
		{ materials.book,		  materials.chest,		  materials.book },
		{ materials.steel_ingot, materials.steel_ingot, materials.steel_ingot }
	}
})
