-- ROBLOX MOVED: expect/utils.lua
-- ROBLOX TODO: (LUAU) Add seenReferences type annotation once Luau can
-- recognize that the seenReferences or {} is sufficient to make seenReferences
-- non-nil

local function getObjectSubset(object: any, subset: any, seenReferences_: { [Object]: boolean }?): any
	local seenReferences = if seenReferences_ then seenReferences_ else {}

	if Array.isArray(object) then
		if Array.isArray(subset) and #subset == #object then
			-- The return correct subclass of subset
			local subsetMap = {}

			for i, sub in ipairs(subset) do
				table.insert(subsetMap, getObjectSubset(object[i], sub))
			end
			return subsetMap
		end
	elseif getType(object) == "DateTime" then
		return object
	elseif isObject(object) and isObject(subset) then
		if equals(object, subset, { iterableEquality, subsetEquality }) then
			return subset
		end

		local trimmed: any = {}
		seenReferences[object] = trimmed

		for i, key in
			ipairs(Array.filter(Object.keys(object), function(key)
				return hasPropertyInObject(subset, key)
			end))
		do
			if seenReferences[object[key]] ~= nil then
				trimmed[key] = seenReferences[object[key]]
			else
				trimmed[key] = getObjectSubset(object[key], subset[key], seenReferences)
			end
		end

		if #Object.keys(trimmed) > 0 then
			return trimmed
		end
	end

	return object
end

return {
	-- jasmineUtils.lua
	equals = equals,
	isA = isA,
	isAsymmetric = isAsymmetric,

	-- utils.lua
	getObjectSubset = getObjectSubset,
	iterableEquality = iterableEquality,
	subsetEquality = subsetEquality,
	isObjectWithKeys = isObjectWithKeys,
	hasPropertyInObject = hasPropertyInObject,
}
