local function get_item_list(itemstack)
	local meta = itemstack:get_meta()
	local str = meta:get("edit_bag")
	local item_list = {}
	if str then item_list = minetest.deserialize(str) end
	for i, str in pairs(item_list) do
		item_list[i] = ItemStack(str)
	end
	return item_list
end

local function put_item_list(itemstack, item_list)
	local meta = itemstack:get_meta()
	local str_list = {}
	local description = ""
	local description_len = 0
	for i, item in pairs(item_list) do
		str_list[i] = item:to_string()
		if str_list[i] ~= "" then
			if description_len < 3 then
				description = description ..
					"\n" .. item:get_count() ..
					" " .. item:get_short_description()
				description_len = description_len + 1
			elseif description_len == 3 then
				description = description .. "\n..."
				description_len = description_len + 1
			end
		end
	end
	description = minetest.registered_items["edit:bag"].short_description ..
		minetest.colorize("yellow", description)
	local str = minetest.serialize(str_list)
	meta:set_string("edit_bag", str)
	meta:set_string("description", description)
end

local function on_inv_change(player)
	local bag = player:get_wielded_item()
	if bag:get_name() ~= "edit:bag" then return end
	if not bag then return end
	local name = player:get_player_name()
	local inv_ref = minetest.get_inventory({type = "detached", name = "edit_bag_" .. name})
	put_item_list(bag, inv_ref:get_list("main"))
	player:set_wielded_item(bag)
end

minetest.register_on_joinplayer(function(player)
	local inv_ref = minetest.create_detached_inventory("edit_bag_" .. player:get_player_name(), {
		on_move = function(inv, from_list, from_index, to_list, to_index, count, player) on_inv_change(player) end,
		on_put = function(inv, listname, index, stack, player) on_inv_change(player) end,
		on_take = function(inv, listname, index, stack, player) on_inv_change(player) end,
	})
	inv_ref:set_size("main", 16)
end)

minetest.register_on_leaveplayer(function(player)
	minetest.remove_detached_inventory("edit_bag_" .. player:get_player_name())
end)

local function on_place(itemstack, player, pointed_thing)
	if pointed_thing.type ~= "node" then return end
	local item_list = get_item_list(itemstack)
	local total_count = 0
	for i, item_stack in ipairs(item_list) do
		total_count = total_count + item_stack:get_count()
	end
	local selected_index = math.round((total_count - 1) * math.random()) + 1
	local selected_item

	local current_index = 0
	for i, item_stack in ipairs(item_list) do
		local count = item_stack:get_count()
		if count > 0 then
			current_index = current_index + count
			if current_index >= selected_index then
				selected_item = item_stack
				break
			end
		end
	end

	local pos = edit.pointed_thing_to_pos(pointed_thing)
	if selected_item and pos then
		edit.place_item_like_player(player, {name = selected_item}, pos)
	end
end

local function on_use(itemstack, user, pointed_thing)
	local meta = itemstack:get_meta()
	local str = meta:get("edit_bag")
	local name = user:get_player_name()
	local item_list = {}
	if str then item_list = minetest.deserialize(str) end
	for i, str in pairs(item_list) do
		item_list[i] = ItemStack(str)
	end
	local inv_ref = minetest.get_inventory({type = "detached", name = "edit_bag_" .. name})
	inv_ref:set_list("main", item_list)
	local formspec = "formspec_version[4]size[10.2,10]" ..
		"label[0.2,0.9;Bag contents:]" ..
		"button_exit[9,0.2;1,1;quit;X]" ..
		"list[detached:edit_bag_" .. name .. ";main;0.2,1.4;8,2;]" ..
		"label[0.2,4.5;Inventory:]" ..
		"list[current_player;main;0.2,5;8,4;]"
	minetest.show_formspec(name, "edit:bag", formspec)
end

minetest.register_tool("edit:bag", {
	description = "Edit Bag",
	short_description = "Edit Bag",
	tiles = {"edit_bag.png"},
	inventory_image = "edit_bag.png",
	groups = {not_in_creative_inventory = 1},
	range = 10,
	on_place = on_place,
	on_secondary_use = on_place,
	on_use = on_use,
})
