-- The serialized array is compatible with pretty-format package min option.
-- However, items have default stringify depth (instead of depth - 1)
-- so expected item looks consistent by itself and enclosed in the array.

local function printReceivedArrayContainExpectedItem(received: Array<any>, index: number): string
	local receivedMap = {}
	for i, item in ipairs(received) do
		local stringified = stringify(item)
		if i == index then
			receivedMap[i] = INVERTED_COLOR(stringified)
		else
			receivedMap[i] = RECEIVED_COLOR(stringified)
		end
	end

	return RECEIVED_COLOR("{") .. table.concat(receivedMap, RECEIVED_COLOR(", ")) .. RECEIVED_COLOR("}")
end

local function printCloseTo(receivedDiff: number, expectedDiff: number, precision: number, isNot: boolean): string
	local receivedDiffString = stringify(receivedDiff)
	local expectedDiffString

	if receivedDiffString:find("e") then
		receivedDiffString = receivedDiffString:gsub("%+0", "+")
		receivedDiffString = receivedDiffString:gsub("%-0", "-")

		expectedDiffString = Number.toExponential(expectedDiff, 0)
	else
		if 0 <= precision and precision < 20 then
			local stringFormat = "%." .. precision + 1 .. "f"
			expectedDiffString = string.format(stringFormat, expectedDiff)
		else
			expectedDiffString = stringify(expectedDiff)
		end
	end

	if isNot then
		return string.format(
			"Expected precision:  %s  %s\n" .. "Expected difference: %s< %s\n" .. "Received difference: %s  %s",
			"      ",
			stringify(precision),
			"never ",
			EXPECTED_COLOR(expectedDiffString),
			"      ",
			RECEIVED_COLOR(receivedDiffString)
		)
	else
		return string.format(
			"Expected precision:  %s  %s\n" .. "Expected difference: %s< %s\n" .. "Received difference: %s  %s",
			"",
			stringify(precision),
			"",
			EXPECTED_COLOR(expectedDiffString),
			"",
			RECEIVED_COLOR(receivedDiffString)
		)
	end
end

local function printExpectedConstructorName(label: string, expected): string
	return printConstructorName(label, expected, false, true) .. "\n"
end

local function printExpectedConstructorNameNot(label: string, expected): string
	return printConstructorName(label, expected, true, true) .. "\n"
end

local function printReceivedConstructorName(label: string, received): string
	return printConstructorName(label, received, false, false) .. "\n"
end
