-- ROBLOX deviation: omitted, no ordered tables in lua

function compareObjects(a, b, options: DiffOptions?)
	local difference
	local hasThrown = false

	local ok, _ = pcall(function()
		local formatOptions = getFormatOptions(FORMAT_OPTIONS, options)
		difference = getObjectsDifference(a, b, formatOptions, options)
		-- local aCompare = prettyFormat(a, FORMAT_OPTIONS_0)
		-- local bCompare = prettyFormat(b, FORMAT_OPTIONS_0)

		-- if aCompare == bCompare then
		-- 	difference = noDiffMessage
		-- else
		-- 	local aDisplay = prettyFormat(a, FORMAT_OPTIONS)
		-- 	local bDisplay = prettyFormat(b, FORMAT_OPTIONS)
		-- 	difference = diffLinesUnified2(
		-- 		string.split(aDisplay, '\n'),
		-- 		string.split(bDisplay, '\n'),
		-- 		string.split(aCompare, '\n'),
		-- 		string.split(bCompare, '\n'),
		-- 		options
		-- 	)
		-- end
	end)
	if not ok then
		hasThrown = true
	end

	local noDiffMessage = getCommonMessage(NO_DIFF_MESSAGE, options)
	-- If the comparison yields no results, compare again but this time
	-- without calling `toJSON`. It's also possible that toJSON might throw.
	if difference == nil or difference == noDiffMessage then
		local formatOptions = getFormatOptions(FALLBACK_FORMAT_OPTIONS, options)
		difference = getObjectsDifference(a, b, formatOptions, options)
		-- local aCompare = prettyFormat(a, FALLBACK_FORMAT_OPTIONS_0)
		-- local bCompare = prettyFormat(b, FALLBACK_FORMAT_OPTIONS_0)

		-- if aCompare == bCompare then
		-- 	difference = noDiffMessage
		-- else
		-- 	local aDisplay = prettyFormat(a, FALLBACK_FORMAT_OPTIONS)
		-- 	local bDisplay = prettyFormat(b, FALLBACK_FORMAT_OPTIONS)

		-- 	difference = diffLinesUnified2(
		-- 		string.split(aDisplay, '\n'),
		-- 		string.split(bDisplay, '\n'),
		-- 		string.split(aCompare, '\n'),
		-- 		string.split(bCompare, '\n'),
		-- 		options
		-- 	)
		-- end

		if difference ~= noDiffMessage and not hasThrown then
			difference = getCommonMessage(SIMILAR_MESSAGE, options) .. "\n\n" .. difference
		end
	end

	return difference
end

function getFormatOptions(formatOptions: PrettyFormatOptions, options: DiffOptions?): PrettyFormatOptions
	local compareKeys = normalizeDiffOptions(options).compareKeys
	return Object.assign({}, formatOptions, { compareKeys = compareKeys })
end

function getObjectsDifference(
	a: Record<string, any>,
	b: Record<string, any>,
	formatOptions: PrettyFormatOptions,
	options: DiffOptions?
): string
	local formatOptionsZeroIndent = Object.assign({}, formatOptions, { indent = 0 })
	local aCompare = prettyFormat(a, formatOptionsZeroIndent)
	local bCompare = prettyFormat(b, formatOptionsZeroIndent)
	if aCompare == bCompare then
		return getCommonMessage(NO_DIFF_MESSAGE, options)
	else
		local aDisplay = prettyFormat(a, formatOptions)
		local bDisplay = prettyFormat(b, formatOptions)
		return diffLinesUnified2(
			String.split(aDisplay, "\n"),
			String.split(bDisplay, "\n"),
			String.split(aCompare, "\n"),
			String.split(bCompare, "\n"),
			options
		)
	end
end

return {
	diffLinesRaw = diffLinesRaw,
	diffLinesUnified = diffLinesUnified,
	diffLinesUnified2 = diffLinesUnified2,

	diffStringsRaw = diffStringsRaw,
	diffStringsUnified = diffStringsUnified,

	DIFF_DELETE = DIFF_DELETE,
	DIFF_EQUAL = DIFF_EQUAL,
	DIFF_INSERT = DIFF_INSERT,
	Diff = Diff,

	diff = diff,
}