local fn = {}

fn.match = function(a,b,exact)
	if exact == nil then exact = true end
	if exact then return ItemStack(a):to_string() == ItemStack(b):to_string() else
		a,b = ItemStack(a), ItemStack(b)
		if a:get_name()	~= b:get_name() then return false, b end
		if a:get_count() <= b:get_count() then
			return true, ItemStack {
				name = a:get_name();
				count = b:get_count() - a:get_count();
			}
		end
	end
end

-- it is extremely unfortunate this function needs to exist.
-- minetest needs to export its matching capabilities already
fn.groupmatch = function(identity,item,exact)
	if exact == nil then exact = true end
	local count
	if type(identity) == 'table' then
		count = identity.count
		identity = identity.name
	else
		if sorcery.lib.str.beginswith(identity, 'group:') then
			identity,count = sorcery.lib.tbl.split(identity,'%s+',true)
			if count
				then count = tonumber(count)
				else count = 1
			end
		else
			local is = ItemStack(identity)
			identity,count = is:get_name(), is:get_count()
		end
	end

	local stack = ItemStack(item)
	if sorcery.lib.str.beginswith(identity, 'group:') then
		local groups = sorcery.lib.str.explode(string.sub(identity,7), ',')
		for _,g in pairs(groups) do
			local rn,rv = sorcery.lib.tbl.split(g,'=')
			local gv = minetest.get_item_group(stack:get_name(), rn)
			if rv then
				if gv ~= tonumber(rv) then return false, stack end
			else
				if (not gv) or gv == 0 then return false, stack end
			end
		end

		if stack:get_count() < count then return false, stack end

		if exact then
			if stack:get_count() ~= count then
				return false, stack end
			return true, ItemStack(nil)
		else
			stack:take_item(count)
			return true, stack
		end
	else return fn.match(identity,item,exact) end
end

-- local try = function(a,b,e)
-- 	print('::: match',e==false and 'inexact' or 'exact',dump(a))
-- 	print('\t against',dump(b))
-- 	local res, leftover = fn.groupmatch(a,b,e)
-- 	print('result',res)
-- 	if leftover and leftover:get_count() > 0 then
-- 		print('leftover items:',leftover:to_string())
-- 	end
-- 	print("\n")
-- end

return fn
