local S = minetest.get_translator("hades_trash")
local F = minetest.formspec_escape

-- Width and height of trash inventory
local TRASH_INV_WIDTH = 2
local TRASH_INV_HEIGHT = 3

-- Trash can collects items every this many seconds
local TRASH_COLLECT_TIMER = 8.0

local get_trash_param2 = function(inv)
	for i=1, inv:get_size("main") do
	end
end

local trash_formspec =
	"formspec_version[6]"..
	"size[12.75,10.9]"..
	"button[5.25,0.475;2.2,0.7;empty;"..F(S("Empty Trash")).."]"..
	"list[current_name;main;5.25,1.5;"..TRASH_INV_WIDTH..","..TRASH_INV_HEIGHT..";]"..
	"list[current_player;main;0.475,6;10,4;]"..
	"listring[]"..
	"background9[0,0;8,9;hades_trash_trash_can_inventory.png;true;18,17,-22,-17]"

--Node registration
local def = {
	groups = {snappy=1,choppy=2,oddly_breakable_by_hand=2,trash_can=1},
	tiles = {"hades_trash_trash_can_plastic_top.png", "hades_trash_trash_can_plastic_top.png", "hades_trash_trash_can_plastic.png"},
	description = S("Trash Can"),
	_tt_help = S("Lets you get rid of unwanted items"),
	drawtype="nodebox",
	paramtype = "light",
	is_ground_content = false,
	node_box = {
		type = "fixed",
		fixed = {
			{-0.3125,-0.5, 0.3125,  0.3125, 0.5,   0.375},
			{ 0.3125,-0.5,-0.375,   0.375,  0.5,   0.375},
			{-0.3125,-0.5,-0.375,   0.3125, 0.5,  -0.3125},
			{-0.375, -0.5,-0.375,  -0.3125, 0.5,   0.375},
			{-0.3125,-0.5,-0.3125,  0.3125,-0.4375,0.3125},
                }
        },
        on_construct = function(pos)
		local meta = minetest.get_meta(pos)
		meta:set_string("formspec", trash_formspec)
                meta:set_string("infotext", S("Trash Can"))
		local inv = meta:get_inventory()
		inv:set_size("main", TRASH_INV_WIDTH*TRASH_INV_HEIGHT)

		local timer = minetest.get_node_timer(pos)
		timer:start(TRASH_COLLECT_TIMER)
	end,
	on_timer = function(pos)
		-- Automatically move dropped items inside the trash can into
		-- its inventory, provided there is enough space.
		local meta = minetest.get_meta(pos)
		local inv = meta:get_inventory()
		-- Checked area should be the same as the trash can
		-- nodebox, but a bit higher so that items ON the trash can
		-- will be picked up as well.
		local minpos = vector.add(pos, vector.new(-0.375, -0.4375, -0.375))
		local maxpos = vector.add(pos, vector.new(0.375, 0.9, 0.375))
		local added_item = false
		for obj in minetest.objects_in_area(minpos, maxpos) do
			local ent = obj:get_luaentity()
			if ent and ent.name == "__builtin:item" then
				local item = ItemStack(ent.itemstring or "")
				if inv:room_for_item("main", item) then
					minetest.log("info", "[hades_trash] Trash can at "..minetest.pos_to_string(pos).." picks up "..item:to_string())
					inv:add_item("main", item)
					added_item = true
					obj:remove()
				end
			end
		end
		if added_item then
			local node = minetest.get_node(pos)
			if node.name == "hades_trash:trash_can_plastic" then
				minetest.swap_node(pos, {name="hades_trash:trash_can_plastic_trash", param2 = 8})
			end
		end

		local timer = minetest.get_node_timer(pos)
		timer:start(TRASH_COLLECT_TIMER)
	end,

	-- Intentionally no 'can_dig' function. If you dig this node, items in trash are gone.

        on_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
		minetest.log("action",  "[hades_trash] "..player:get_player_name()..
			" moves stuff in trash can at "..minetest.pos_to_string(pos))
	end,
        on_metadata_inventory_put = function(pos, listname, index, stack, player)
		minetest.log("action", "[hades_trash] ".. player:get_player_name()..
			" puts stuff to trash can at "..minetest.pos_to_string(pos))

		local node = minetest.get_node(pos)
		if node.name == "hades_trash:trash_can_plastic" then
			minetest.swap_node(pos, {name="hades_trash:trash_can_plastic_trash", param2 = 8})
		end
	end,
        on_metadata_inventory_take = function(pos, listname, index, stack, player)
		minetest.log("action", "[hades_trash] "..player:get_player_name()..
			" takes stuff from trash can at "..minetest.pos_to_string(pos))

		local meta = minetest.get_meta(pos)
		local inv = meta:get_inventory()
		if inv:is_empty("main") then
			local node = minetest.get_node(pos)
			if node.name == "hades_trash:trash_can_plastic_trash" then
				minetest.swap_node(pos, {name="hades_trash:trash_can_plastic", param2 = 0})
			end
		end
        end,
	on_receive_fields = function(pos, formname, fields, sender)
		if fields.empty then
			-- Empty the trash can
			local meta = minetest.get_meta(pos)
			local inv = meta:get_inventory()
			local has_items = not inv:is_empty("main")
			if has_items then
				inv:set_list("main", {})
				local player_name = sender:get_player_name()
				minetest.sound_play("hades_trash_empty", {to_player=player_name, gain = 1.0}, true)
				minetest.log("action", "[hades_trash] " ..player_name ..
					" empties the trash can at "..minetest.pos_to_string(pos))
			end
			local node = minetest.get_node(pos)
			if node.name == "hades_trash:trash_can_plastic_trash" then
				minetest.swap_node(pos, {name="hades_trash:trash_can_plastic", param2 = 0})
			end
		end
        end,
	sounds = hades_sounds.node_sound_defaults(),
}

-- Definition of trash can with trash
local tdef = table.copy(def)
tdef.tiles = {"hades_trash_trash_can_plastic_trash_top.png", "hades_trash_trash_can_plastic_top.png", "hades_trash_trash_can_plastic.png"}
local node_box_with_trash = {
	{-0.3125,-0.5, 0.3125,  0.3125, 0.5,   0.375},
	{ 0.3125,-0.5,-0.375,   0.375,  0.5,   0.375},
	{-0.3125,-0.5,-0.375,   0.3125, 0.5,  -0.3125},
	{-0.375, -0.5,-0.375,  -0.3125, 0.5,   0.375},
	{-0.3125,-0.5,-0.3125,  0.3125, 0.125, 0.3125},
}
tdef.node_box = {
	type = "fixed",
	fixed = node_box_with_trash,
}
tdef.selection_box = table.copy(tdef.node_box)
tdef.collision_box = table.copy(def.node_box)
tdef.groups.not_in_creative_inventory = 1
tdef.drop = "hades_trash:trash_can_plastic"
tdef.description = S("Trash Can with Trash")
tdef._tt_help = nil

minetest.register_node("hades_trash:trash_can_plastic", def)
minetest.register_node("hades_trash:trash_can_plastic_trash", tdef)

--Crafting

minetest.register_craft({
	output = 'hades_trash:trash_can_plastic',
	recipe = {
		{'hades_materials:plastic_base', '', 'hades_materials:plastic_base'},
		{'hades_materials:plastic_base', '', 'hades_materials:plastic_base'},
		{'hades_materials:plastic_base', 'hades_materials:plastic_base', 'hades_materials:plastic_base'},
	}
})

-- In old versions, the inventory size of trash cans
-- was much larger than shown in the formspec.
-- This LBM fixes it.
minetest.register_lbm({
	name = "hades_trash:fix_inv",
	label = "Fix trash can inventory size",
	nodenames = {"hades_trash:trash_can_plastic"},
	run_at_every_load = false,
	action = function(pos, node)
		local meta = minetest.get_meta(pos)
		local inv = meta:get_inventory()
		inv:set_size("main", TRASH_INV_WIDTH*TRASH_INV_HEIGHT)

		-- Also switch to trash version of the node while we're at it
		if not inv:is_empty("main") then
			minetest.swap_node(pos, {name="hades_trash:trash_can_plastic_trash", param2 = node.param2})
		end
	end,
})

-- Restarts the trash can timer if its
-- not started yet
minetest.register_lbm({
	name = "hades_trash:restart_timer",
	label = "Restart trash can collection timer",
	nodenames = {"hades_trash:trash_can_plastic"},
	run_at_every_load = true,
	action = function(pos, node)
		local timer = minetest.get_node_timer(pos)
		if not timer:is_started() then
			timer:start(TRASH_COLLECT_TIMER)
		end
	end,
})

minetest.register_lbm({
	name = "hades_trash:update_formspec_v0_18_0",
	label = "Update trash can formspecs (v0.18.0)",
	nodenames = { "group:trash_can" },
	action = function(pos)
		local meta = minetest.get_meta(pos)
		meta:set_string("formspec", trash_formspec)
	end,
})
