local mod_name = core.get_current_modname()
local S = core.get_translator(mod_name)

local node_box
if true then
	local pl = 8/16
	local pa = 4/16
	local pd = 6/16
	node_box = {
		type = "fixed",
		fixed = {
			{-pd, -pd, -pl,
			  pd,  pd,  2/16},
			{-pl, -pl,  2/16,
			  pl,  pl,  pa},
			{-pa, -pa,  pa,
			  pa,  pa,  6/16},
		},
	}
end

local function get_formspec(meta)
	local fs, size = aom_inventory.player.get_formspec(nil)
	local y = 12-size.y-2
	local always_active = (meta and ((meta:get_string("always_active") ~= "")))
	local btn_col = (always_active and "#1a3") or "#a13"
	local filter_node = meta:get_string("filter_node")
	return table.concat({
		fs,
		"container[", 12-6/2, ",", y-3.5, "]",
		aom_inventory.get_9patch(0, 0, 6, 4, aom_inventory.get_bg9patch_texture("#4a774a"), "false", "32"),
		((aom_inventory.get_itemslot_array(1.5, 0.5, 4, 1)) or ""),
		"list[context;filter;1.5,0.5;4,1;]",

		"style_type[image_button;border=false;bgcolor_hovered=#eee;bgcolor_pressed=#fff;bgimg_middle=8]",

		"style_type[image_button;",
		"bgimg=aom_inv_btn.png\\^\\[multiply:", "#333", ";",
		"bgimg_hovered=aom_inv_btn.png\\^\\[multiply:", "#333", ";",
		"bgimg_pressed=aom_inv_btn_press.png\\^\\[multiply:", "#333", "]",

		((filter_node == "") and
		table.concat({"image_button[0.45,0.45;1,1;aom_wire_gui_save.png", ";get_filter_node; ]"}) or
		table.concat({"item_image_button[0.45,0.45;1,1;", filter_node, ";get_filter_node; ]"})),
		-- "label[1.5,2;", core.colorize("#ccc", meta:get_string("filter_node")), "]",

		"style_type[image_button;",
		"bgimg=aom_inv_btn.png\\^\\[multiply:", btn_col, ";",
		"bgimg_hovered=aom_inv_btn.png\\^\\[multiply:", btn_col, ";",
		"bgimg_pressed=aom_inv_btn_press.png\\^\\[multiply:", btn_col, "]",
		"image_button[0.5,", tostring(2.5), ";1,1;aom_wire_gui_repeat.png",
		((always_active and "^[multiply:#4f7") or "^[multiply:#f57") or "",
		";toggle_always_active; ]",
		-- TL: active ("on" or "off")
		"label[1.5,3;", core.colorize("#ccc", S("Always Active: @1",
		-- TL: active / inactive ("Always Active: @1"), 
		always_active and S("on") or S("off"))), "]",

		"container_end[]",

		"listring[context;filter]",
		"listring[current_player;main]",
	})
end

local function fix_formspec(pos)
	-- set up the formspec and stuff
	local meta = core.get_meta(pos)
	local formspec = get_formspec(meta)
	if meta:get_string("formspec") == formspec then return end
	local inv = meta:get_inventory()
	inv:set_size("filter", 4)
	meta:set_string("formspec", formspec)
	return true
end

local function observe_node(pos)
	-- core.log("" .. )
	local to_pos = vector.add(pos, core.facedir_to_dir(core.get_node(pos).param2))
	local node = core.get_node_or_nil(to_pos)
	if not node then return end
	local meta = core.get_meta(pos)
	local is_new_node = (meta:get_string("last_seen_node") ~= node.name)
	meta:set_string("last_seen_node", node.name)
	local inv = meta:get_inventory()
	local always_active = (meta:get_string("always_active") ~= "")
	local filter_node = meta:get_string("filter_node")
	if filter_node == "" and inv:is_empty("filter") and
	(is_new_node or always_active) then
		-- core.log(tostring(pos) .. " observed " ..node.name)
		aom_wire.activate(pos, nil)
		return true
	end
	if (is_new_node or always_active) and (node.name == filter_node) then
		-- core.log(tostring(pos) .. " observed " ..node.name)
		aom_wire.activate(pos, nil)
		-- core.log("OBSERVER: " .. tostring(pos))
		return true
	end
	for i, itemstack in ipairs(inv:get_list("filter") or {}) do
		itemstack = ItemStack(itemstack)
		if (itemstack:get_name() == node.name) and (is_new_node or always_active) then
			-- core.log(tostring(pos) .. " observed " ..node.name)
			aom_wire.activate(pos, nil)
			return true
		end
	end
	-- core.log(tostring(pos) .. " GOT TO END " .. meta:get_string("last_seen_node"))
end

local update_causes = {place=true, dig=true, move=false, liquid=true}

core.register_node("aom_machines:node_detector", {
	description = S("Node Detector"),
	_tt_color = 3,
	_tt_long_desc = S("Can be connected to inputs using wirecutters.") .. "\n" ..
		-- TL: 1a
		S("Detects nodes in front and sends a signal if:") .. "\n" ..
		-- TL: list of conditions for 1a
		S("- no filter is set") .. "\n" ..
		-- TL: list of conditions for 1a
		S("- the node matches the filter") .. "\n" ..
		S("Will keep sending signals every second if 'always active' is true."),
	groups = { cracky = 1, oddly_breakable_by_hand = 2, solid = 1, mechanisms = 1, wire_output = 1, },
	tiles = {
		"aom_machines_detector.png^[transformR90",
		"aom_machines_detector.png^[transformR270",
		"aom_machines_detector.png",
		"aom_machines_detector.png^[transformFX",
		"aom_machines_detector_front.png",
		"aom_machines_detector_back.png",
	},
	sounds = aom_sounds.default_wood(),
	paramtype = "light",
	sunlight_propagates = true,
	paramtype2 = "facedir",
	drawtype = "nodebox",
	node_box = node_box,
	on_place = aom_util.rotate_and_place_against,
	on_construct = function(pos)
		fix_formspec(pos)
		local nt = core.get_node_timer(pos)
		if not nt:is_started() then
			nt:start(1)
		end
	end,
	on_destruct = function(pos)
		local nt = core.get_node_timer(pos)
		if nt:is_started() then nt:stop() end
		aom_inventory.drop_contents(pos)
	end,
	on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
		fix_formspec(pos)
	end,
	on_timer = function(pos, elapsed)
		aom_wire.update_meta_uid(pos)
		-- core.log(":"..core.get_meta(pos):get_string("uid")..":".."   ".."on_timer")
		local uid = aom_wire.update_meta_uid(pos)
		core.after(0.0001, function()
			if aom_wire.get_meta_uid(pos) ~= uid then
				return
			end
			observe_node(pos)
			-- aom_climate.debug_particle(pos, "#fff", 1, vector.new(0, math.random() * 8, 0), 5)
		end)
		return true
	end,
	on_receive_fields = function(pos, formname, fields, sender)
		local changes = false
		if fields["toggle_always_active"] then
			local meta = core.get_meta(pos)
			if meta:get_string("always_active") ~= "" then
				meta:set_string("always_active", "")
			else
				meta:set_string("always_active", "1")
			end
			changes = true
		elseif fields["get_filter_node"] then
			local meta = core.get_meta(pos)
			local to_pos = vector.add(pos, core.facedir_to_dir(core.get_node(pos).param2))
			local node = core.get_node_or_nil(to_pos)
			if node then
				if node.name == meta:get_string("filter_node") then
					meta:set_string("filter_node", "")
				else
					meta:set_string("filter_node", node.name)
				end
				changes = true
			end
		end
		if changes then
			fix_formspec(pos)
		end
	end,
	_aom_wire_activation_sound = {
		press = {
			name = "aom_wrench_plip",
			gain = 0.1, pitch = 1.2
		},
	},
	_on_node_update = function(pos, cause, user, data)
		local nt = core.get_node_timer(pos)
		if not nt:is_started() then
			nt:start(1)
		end
		if update_causes[cause] then
			observe_node(pos)
		end
	end,
	_has_formspec = true,
})

aom_tcraft.register_craft({
	output = "aom_machines:node_detector",
	items = {
		["aom_stone:cobble"] = 10,
		["aom_items:tin_bar"] = 1,
	},
})
