-- Return either empty string or one line per indexed result,
-- so additional empty line can separate from `Number of returns` which follows.


function printReceivedResults(
	label: string,
	expected: any,
	indexedResults: Array<IndexedResult>,
	isOnlyCall: boolean,
	iExpectedCall: number?
)
	if #indexedResults == 0 then
		return ""
	end

	if isOnlyCall and (iExpectedCall == 1 or iExpectedCall == nil) then
		return label .. printResult(indexedResults[1][2], expected) .. "\n"
	end

	local printAligned = getRightAlignedPrinter(label)

	-- ROBLOX TODO: the following (label:find(':') or 1) can be changed to label:find(':') if
	-- roblox-cli eventually won't complain?
	local colonIndex = label:find(":") or 1

	return String.trim(label:sub(1, colonIndex - 1) .. label:sub(colonIndex + 1, #label))
		.. "\n"
		.. Array.reduce(indexedResults, function(printed: string, indexedResult: IndexedResult)
			local i = indexedResult[1]
			local result = indexedResult[2]
			return printed .. printAligned(tostring(i), i == iExpectedCall) .. printResult(result, expected) .. "\n"
		end, "")
end

local function createToBeCalledMatcher(matcherName: string): SyncExpectationResult
	return function(this: MatcherState, received: any, expected: any)
		local expectedArgument = ""
		local options: MatcherHintOptions = {
			isNot = this.isNot,
			promise = this.promise,
		}

		ensureNoExpected(expected, matcherName, options)
		ensureMockOrSpy(received, matcherName, expectedArgument, options)

		local receivedIsSpy = isSpy(received)
		local receivedName
		if receivedIsSpy then
			receivedName = "spy"
		else
			receivedName = received.getMockName()
		end

		local count
		if receivedIsSpy then
			count = received.calls.count()
		else
			count = #received.mock.calls
		end

		local calls
		if receivedIsSpy then
			calls = Array.map(received.calls.all(), function(x: any)
				return x.args
			end)
		else
			calls = received.mock.calls
		end

		local pass = count > 0
		local message
		if pass then
			message = function()
				return matcherHint(matcherName, receivedName, expectedArgument, options)
					.. "\n\n"
					.. ("Expected number of calls: %s\n"):format(printExpected(0))
					.. ("Received number of calls: %s\n\n"):format(printReceived(count))
					.. Array.join(
						Array.reduce(calls, function(lines: Array<string>, args: any, i: number)
							if #lines < PRINT_LIMIT then
								table.insert(lines, ("%s: %s"):format(tostring(i), printReceivedArgs(args)))
							end

							return lines
						end, {}),
						"\n"
					)
			end
		else
			message = function()
				return matcherHint(matcherName, receivedName, expectedArgument, options)
					.. "\n\n"
					.. ("Expected number of calls: >= %s\n"):format(printExpected(1))
					.. ("Received number of calls:    %s"):format(printReceived(count))
			end
		end

		return { message = message, pass = pass }
	end
end

local function createToReturnMatcher(matcherName: string): SyncExpectationResult
	return function(this: MatcherState, received: any, expected: any)
		local expectedArgument = ""
		local options: JestMatcherUtils.MatcherHintOptions = {
			isNot = this.isNot,
			promise = this.promise,
		}

		ensureNoExpected(expected, matcherName, options)
		ensureMock(received, matcherName, expectedArgument, options)

		local receivedName = received.getMockName()

		-- Count return values that correspond only to calls that returned
		local count = Array.reduce(received.mock.results, function(n: number, result: any)
			if result.type == "return" then
				return n + 1
			else
				return n
			end
		end, 0)

		local pass = count > 0
		local message
		if pass then
			message = function()
				local retval = matcherHint(matcherName, receivedName, expectedArgument, options)
					.. "\n\n"
					.. ("Expected number of returns: %s\n"):format(printExpected(0))
					.. ("Received number of returns: %s\n\n"):format(printReceived(count))
					.. Array.join(
						Array.reduce(received.mock.results, function(lines: Array<string>, result: any, i: number)
							if result.type == "return" and #lines < PRINT_LIMIT then
								table.insert(lines, ("%s: %s"):format(tostring(i), printReceived(result.value)))
							end

							return lines
						end, {}),
						"\n"
					)

				if #received.mock.calls ~= count then
					retval = retval .. "\n\nReceived number of calls:   " .. printReceived(#received.mock.calls)
				end

				return retval
			end
		else
			message = function()
				local retval = matcherHint(matcherName, receivedName, expectedArgument, options)
					.. "\n\n"
					.. ("Expected number of returns: >= %s\n"):format(printExpected(1))
					.. ("Received number of returns:    %s"):format(printReceived(count))
				if #received.mock.calls ~= count then
					retval = retval
						.. ("\nReceived number of calls:      %s"):format(printReceived(#received.mock.calls))
				end

				return retval
			end
		end

		return { message = message, pass = pass }
	end
end

local function createToBeCalledTimesMatcher(matcherName: string): SyncExpectationResult
	return function(this: MatcherState, received: any, expected: number)
		local expectedArgument = "expected"
		local options: JestMatcherUtils.MatcherHintOptions = {
			isNot = this.isNot,
			promise = this.promise,
		}

		ensureExpectedIsNonNegativeInteger(expected, matcherName, options)
		ensureMockOrSpy(received, matcherName, expectedArgument, options)

		local receivedIsSpy = isSpy(received)
		local receivedName
		if receivedIsSpy then
			receivedName = "spy"
		else
			receivedName = received.getMockName()
		end

		local count
		if receivedIsSpy then
			count = received.calls.count()
		else
			count = #received.mock.calls
		end

		local pass = count == expected

		local message
		if pass then
			message = function()
				return matcherHint(matcherName, receivedName, expectedArgument, options)
					.. "\n\n"
					.. ("Expected number of calls: never %s"):format(printExpected(expected))
			end
		else
			message = function()
				return matcherHint(matcherName, receivedName, expectedArgument, options)
					.. "\n\n"
					.. ("Expected number of calls: %s\n"):format(printExpected(expected))
					.. ("Received number of calls: %s"):format(printReceived(count))
			end
		end

		return { message = message, pass = pass }
	end
end

local function createToReturnTimesMatcher(matcherName: string): SyncExpectationResult
	return function(this: MatcherState, received: any, expected: number)
		local expectedArgument = "expected"
		local options: JestMatcherUtils.MatcherHintOptions = {
			isNot = this.isNot,
			promise = this.promise,
		}

		ensureExpectedIsNonNegativeInteger(expected, matcherName, options)
		ensureMock(received, matcherName, expectedArgument, options)

		local receivedName = received.getMockName()

		-- Count return values that correspond only to calls that returned
		local count = Array.reduce(received.mock.results, function(n: number, result: any)
			if result.type == "return" then
				return n + 1
			else
				return n
			end
		end, 0)

		local pass = count == expected

		local message
		if pass then
			message = function()
				local retval = matcherHint(matcherName, receivedName, expectedArgument, options)
					.. "\n\n"
					.. ("Expected number of returns: never %s"):format(printExpected(expected))

				if #received.mock.calls ~= count then
					retval = retval
						.. ("\n\nReceived number of calls:         %s"):format(printReceived(#received.mock.calls))
				end

				return retval
			end
		else
			message = function()
				local retval = matcherHint(matcherName, receivedName, expectedArgument, options)
					.. "\n\n"
					.. ("Expected number of returns: %s\n"):format(printExpected(expected))
					.. ("Received number of returns: %s"):format(printReceived(count))

				if #received.mock.calls ~= count then
					retval = retval .. ("\nReceived number of calls:   %s"):format(printReceived(#received.mock.calls))
				end

				return retval
			end
		end

		return { message = message, pass = pass }
	end
end

local function createToBeCalledWithMatcher(matcherName: string): SyncExpectationResult
	return function(this: MatcherState, received: any, ...)
		local expected = { ... }
		local expectedLength = select("#", ...)
		for i = 1, expectedLength do
			-- ROBLOX deviation: We add this if statement to deal with our internal symbol
			-- that represents nil
			if expected[i] == nil then
				expected[i] = Symbol.for_("$$nil")
			end
		end
		local expectedArgument = "...expected"
		local options: JestMatcherUtils.MatcherHintOptions = {
			isNot = this.isNot,
			promise = this.promise,
		}

		ensureMockOrSpy(received, matcherName, expectedArgument, options)

		local receivedIsSpy = isSpy(received)
		local receivedName
		if receivedIsSpy then
			receivedName = "spy"
		else
			receivedName = received.getMockName()
		end

		local calls
		if receivedIsSpy then
			calls = Array.map(received.calls.all(), function(x: any)
				return x.args
			end)
		else
			calls = received.mock.calls
		end

		local pass = Array.some(calls, function(call)
			return isEqualCall(expected, call)
		end)

		local message
		if pass then
			message = function()
				-- Some examples of calls that are equal to expected value.
				local indexedCalls: Array<IndexedCall> = {}
				local i = 1
				while i <= #calls and #indexedCalls < PRINT_LIMIT do
					if isEqualCall(expected, calls[i]) then
						table.insert(indexedCalls, { i, calls[i] })
					end
					i = i + 1
				end

				local retval = matcherHint(matcherName, receivedName, expectedArgument, options)
					.. "\n\n"
					.. ("Expected: never %s\n"):format(printExpectedArgs(expected))

				if not (#calls == 1 and stringify(calls[1]) == stringify(expected)) then
					retval = retval .. printReceivedCallsNegative(expected, indexedCalls, #calls == 1)
				end

				retval = retval .. ("\nNumber of calls: %s"):format(printReceived(#calls))
				return retval
			end
		else
			message = function()
				-- Some examples of calls that are not equal to expected value.
				local indexedCalls: Array<IndexedCall> = {}
				local i = 1
				while i <= #calls and #indexedCalls < PRINT_LIMIT do
					table.insert(indexedCalls, { i, calls[i] })
					i = i + 1
				end
				return matcherHint(matcherName, receivedName, expectedArgument, options)
					.. "\n\n"
					.. printExpectedReceivedCallsPositive(expected, indexedCalls, isExpand(this.expand), #calls == 1)
					.. ("\nNumber of calls: %s"):format(printReceived(#calls))
			end
		end

		return { message = message, pass = pass }
	end
end

local function createToReturnWithMatcher(matcherName: string): SyncExpectationResult
	return function(this: MatcherState, received: any, expected: any)
		local expectedArgument = "expected"
		local options: JestMatcherUtils.MatcherHintOptions = {
			isNot = this.isNot,
			promise = this.promise,
		}
		ensureMock(received, matcherName, expectedArgument, options)

		local receivedName = received.getMockName()
		local receivedMock = received.mock
		local calls = receivedMock.calls
		local results = receivedMock.results

		local pass = Array.some(results, function(result: any)
			return isEqualReturn(expected, result)
		end)

		local message
		if pass then
			message = function()
				-- Some examples of results that are equal to expected value.
				local indexedResults: Array<IndexedResult> = {}
				local i = 1
				while i <= #results and #indexedResults < PRINT_LIMIT do
					if isEqualReturn(expected, results[i]) then
						table.insert(indexedResults, { i, results[i] })
					end
					i = i + 1
				end

				local retval = matcherHint(matcherName, receivedName, expectedArgument, options)
					.. "\n\n"
					.. ("Expected: never %s\n"):format(printExpected(expected))

				if
					not (
						#results == 1
						and results[1].type == "return"
						and stringify(results[1].value) == stringify(expected)
					)
				then
					retval = retval .. printReceivedResults("Received:       ", expected, indexedResults, #results == 1)
				end

				retval = retval .. printNumberOfReturns(countReturns(results), #calls)

				return retval
			end
		else
			message = function()
				-- Some examples of results that are not equal to expected value.
				local indexedResults: Array<IndexedResult> = {}
				local i = 1
				while i <= #results and #indexedResults < PRINT_LIMIT do
					table.insert(indexedResults, { i, results[i] })
					i = i + 1
				end

				return matcherHint(matcherName, receivedName, expectedArgument, options)
					.. "\n\n"
					.. ("Expected: %s\n"):format(printExpected(expected))
					.. printReceivedResults("Received: ", expected, indexedResults, #results == 1)
					.. printNumberOfReturns(countReturns(results), #calls)
			end
		end

		return { message = message, pass = pass }
	end
end

local function createLastCalledWithMatcher(matcherName: string): SyncExpectationResult
	return function(this: MatcherState, received: any, ...)
		local expected: Array<any> = { ... }
		local expectedLength = select("#", ...)
		for i = 1, expectedLength do
			-- ROBLOX deviation: We add this if statement to deal with our internal symbol
			-- that represents nil
			if expected[i] == nil then
				expected[i] = Symbol.for_("$$nil")
			end
		end
		local expectedArgument = "...expected"
		local options: JestMatcherUtils.MatcherHintOptions = {
			isNot = this.isNot,
			promise = this.promise,
		}

		ensureMockOrSpy(received, matcherName, expectedArgument, options)

		local receivedIsSpy = isSpy(received)
		local receivedName
		if receivedIsSpy then
			receivedName = "spy"
		else
			receivedName = received.getMockName()
		end

		local calls
		if receivedIsSpy then
			calls = Array.map(received.calls.all(), function(x: any)
				return x.args
			end)
		else
			calls = received.mock.calls
		end

		local iLast = #calls

		local pass = iLast >= 1 and isEqualCall(expected, calls[iLast])

		local message
		if pass then
			message = function()
				local indexedCalls: Array<IndexedCall> = {}
				if iLast > 1 then
					-- Display preceding call as context.
					table.insert(indexedCalls, { iLast - 1, calls[iLast - 1] })
				end

				table.insert(indexedCalls, { iLast, calls[iLast] })

				local retval = matcherHint(matcherName, receivedName, expectedArgument, options)
					.. "\n\n"
					.. ("Expected: never %s\n"):format(printExpectedArgs(expected))

				if not (#calls == 1 and stringify(calls[1]) == stringify(expected)) then
					retval = retval .. printReceivedCallsNegative(expected, indexedCalls, #calls == 1, iLast)
				end

				retval = retval .. ("\nNumber of calls: %s"):format(printReceived(#calls))

				return retval
			end
		else
			message = function()
				local indexedCalls: Array<IndexedCall> = {}
				if iLast >= 1 then
					if iLast > 1 then
						local i = iLast - 1
						-- Is there a preceding call that is equal to expected args?
						while i >= 1 and not isEqualCall(expected, calls[i]) do
							i = i - 1
						end
						if i < 1 then
							i = iLast - 1 -- otherwise, preceding call
						end

						table.insert(indexedCalls, { i, calls[i] })
					end

					table.insert(indexedCalls, { iLast, calls[iLast] })
				end

				return matcherHint(matcherName, receivedName, expectedArgument, options)
					.. "\n\n"
					.. printExpectedReceivedCallsPositive(
						expected,
						indexedCalls,
						isExpand(this.expand),
						#calls == 1,
						iLast
					)
					.. ("\nNumber of calls: %s"):format(printReceived(#calls))
			end
		end

		return { message = message, pass = pass }
	end
end

local function createLastReturnedMatcher(matcherName: string): SyncExpectationResult
	return function(this: MatcherState, received: any, expected: any)
		local expectedArgument = "expected"
		local options: JestMatcherUtils.MatcherHintOptions = {
			isNot = this.isNot,
			promise = this.promise,
		}

		ensureMock(received, matcherName, expectedArgument, options)

		local receivedName = received.getMockName()

		local receivedMock = received.mock
		local calls = receivedMock.calls
		local results = receivedMock.results
		local iLast = #results

		local pass = iLast >= 1 and isEqualReturn(expected, results[iLast])

		local message
		if pass then
			message = function()
				local indexedResults: Array<IndexedResult> = {}

				if iLast > 1 then
					-- Display preceding result as context.
					table.insert(indexedResults, { iLast - 1, results[iLast - 1] })
				end
				table.insert(indexedResults, { iLast, results[iLast] })

				local retval = matcherHint(matcherName, receivedName, expectedArgument, options)
					.. "\n\n"
					.. ("Expected: never %s\n"):format(printExpected(expected))

				if
					not (
						#results == 1
						and results[1].type == "return"
						and stringify(results[1].value) == stringify(expected)
					)
				then
					retval = retval
						.. printReceivedResults("Received:       ", expected, indexedResults, #results == 1, iLast)
				end

				retval = retval .. printNumberOfReturns(countReturns(results), #calls)

				return retval
			end
		else
			message = function()
				local indexedResults: Array<IndexedResult> = {}

				if iLast >= 1 then
					if iLast > 1 then
						local i = iLast - 1
						-- Is there a preceding result that is equal to expected value?
						while i >= 1 and not isEqualReturn(expected, results[i]) do
							i = i - 1
						end

						if i < 1 then
							i = iLast - 1 -- otherwise, preceding result
						end

						table.insert(indexedResults, { i, results[i] })
					end

					table.insert(indexedResults, { iLast, results[iLast] })
				end

				return matcherHint(matcherName, receivedName, expectedArgument, options)
					.. "\n\n"
					.. ("Expected: %s\n"):format(printExpected(expected))
					.. printReceivedResults("Received: ", expected, indexedResults, #results == 1, iLast)
					.. printNumberOfReturns(countReturns(results), #calls)
			end
		end

		return { message = message, pass = pass }
	end
end

local function createNthCalledWithMatcher(matcherName: string): SyncExpectationResult
	return function(this: MatcherState, received: any, nth: number, ...)
		local expected = { ... }
		local expectedLength = select("#", ...)
		for i = 1, expectedLength do
			-- ROBLOX deviation: We add this if statement to deal with our internal symbol
			-- that represents nil
			if expected[i] == nil then
				expected[i] = Symbol.for_("$$nil")
			end
		end
		local expectedArgument = "n"
		local options: JestMatcherUtils.MatcherHintOptions = {
			expectedColor = function(arg)
				return arg
			end,
			isNot = this.isNot,
			promise = this.promise,
			secondArgument = "...expected",
		}

		ensureMockOrSpy(received, matcherName, expectedArgument, options)

		if not Number.isSafeInteger(nth) or nth < 1 then
			-- ROBLOX deviation: we don't use the Error polyfill because we encounter an error with TestEZ
			error(
				Error(
					matcherErrorMessage(
						matcherHint(matcherName, nil, expectedArgument, options),
						("%s must be a positive integer"):format(expectedArgument),
						printWithType(expectedArgument, nth, stringify)
					)
				)
			)
		end

		local receivedIsSpy = isSpy(received)
		local receivedName
		if receivedIsSpy then
			receivedName = "spy"
		else
			receivedName = received.getMockName()
		end

		local calls
		if receivedIsSpy then
			calls = Array.map(received.calls.all(), function(x: any)
				return x.args
			end)
		else
			calls = received.mock.calls
		end
		local length = #calls
		local iNth = nth

		local pass = iNth <= length and isEqualCall(expected, calls[iNth])

		local message
		if pass then
			message = function()
				-- Display preceding and following calls,
				-- in case assertions fails because index is off by one.
				local indexedCalls: Array<IndexedCall> = {}

				if iNth - 1 >= 1 then
					table.insert(indexedCalls, { iNth - 1, calls[iNth - 1] })
				end
				table.insert(indexedCalls, { iNth, calls[iNth] })

				if iNth + 1 <= length then
					table.insert(indexedCalls, { iNth + 1, calls[iNth + 1] })
				end

				local retval = matcherHint(matcherName, receivedName, expectedArgument, options)
					.. "\n\n"
					.. ("n: %s\n"):format(tostring(nth))
					.. ("Expected: never %s\n"):format(printExpectedArgs(expected))

				if not (#calls == 1 and stringify(calls[1]) == stringify(expected)) then
					retval = retval .. printReceivedCallsNegative(expected, indexedCalls, #calls == 1, iNth)
				end

				retval = retval .. ("\nNumber of calls: %s"):format(printReceived(#calls))

				return retval
			end
		else
			message = function()
				-- Display preceding and following calls:
				-- * nearest call that is equal to expected args
				-- * otherwise, adjacent call
				-- in case assertions fails because of index, especially off by one.
				local indexedCalls: Array<IndexedCall> = {}

				if iNth <= length then
					if iNth - 1 >= 1 then
						local i = iNth - 1
						-- Is there a preceding call that is equal to expected args?
						while i >= 1 and not isEqualCall(expected, calls[i]) do
							i = i - 1
						end

						if i < 1 then
							i = iNth - 1 -- otherwise, adjacent call
						end

						table.insert(indexedCalls, { i, calls[i] })
					end
					table.insert(indexedCalls, { iNth, calls[iNth] })

					if iNth + 1 <= length then
						local i = iNth + 1
						-- Is there a following call that is equal to expected args?
						while i <= length and not isEqualCall(expected, calls[i]) do
							i = i + 1
						end

						if i >= length then
							i = iNth + 1 -- otherwise, adjacent call
						end

						table.insert(indexedCalls, { i, calls[i] })
					end
				elseif length > 1 then
					-- Is there a call that is equal to expected args?
					local i = length - 1
					-- Is there a call that is equal to expected args?
					while i >= 1 and not isEqualCall(expected, calls[i]) do
						i = i - 1
					end

					if i < 1 then
						i = length - 1
					end

					table.insert(indexedCalls, { i, calls[i] })
				end

				return matcherHint(matcherName, receivedName, expectedArgument, options)
					.. "\n\n"
					.. ("n: %s\n"):format(tostring(nth))
					.. printExpectedReceivedCallsPositive(
						expected,
						indexedCalls,
						isExpand(this.expand),
						#calls == 1,
						iNth
					)
					.. ("\nNumber of calls: %s"):format(printReceived(#calls))
			end
		end

		return { message = message, pass = pass }
	end
end

local function createNthReturnedWithMatcher(matcherName: string): SyncExpectationResult
	return function(this: MatcherState, received: any, nth: number, expected: any)
		local expectedArgument = "n"
		local options: JestMatcherUtils.MatcherHintOptions = {
			expectedColor = function(arg)
				return arg
			end,
			isNot = this.isNot,
			promise = this.promise,
			secondArgument = "expected",
		}

		ensureMock(received, matcherName, expectedArgument, options)

		if not Number.isSafeInteger(nth) or nth < 1 then
			-- ROBLOX deviation: we don't use the Error polyfill because we encounter an error with TestEZ
			error(
				Error(
					matcherErrorMessage(
						matcherHint(matcherName, nil, expectedArgument, options),
						("%s must be a positive integer"):format(expectedArgument),
						printWithType(expectedArgument, nth, stringify)
					)
				)
			)
		end

		local receivedName = received.getMockName()
		local receivedMock = received.mock
		local calls = receivedMock.calls
		local results = receivedMock.results
		local length = #results
		local iNth = nth

		local pass = iNth <= length and isEqualReturn(expected, results[iNth])

		local message
		if pass then
			message = function()
				-- Display preceding and following results,
				-- in case assertions fails because index is off by one.
				local indexedResults: Array<IndexedResult> = {}
				if iNth - 1 >= 1 then
					table.insert(indexedResults, { iNth - 1, results[iNth - 1] })
				end
				table.insert(indexedResults, { iNth, results[iNth] })
				if iNth + 1 <= length then
					table.insert(indexedResults, { iNth + 1, results[iNth + 1] })
				end

				local retval = matcherHint(matcherName, receivedName, expectedArgument, options)
					.. "\n\n"
					.. ("n: %s\n"):format(tostring(nth))
					.. ("Expected: never %s\n"):format(printExpected(expected))

				if
					not (
						#results == 1
						and results[1].type == "return"
						and stringify(results[1].value) == stringify(expected)
					)
				then
					retval = retval
						.. printReceivedResults("Received:       ", expected, indexedResults, #results == 1, iNth)
				end
				retval = retval .. printNumberOfReturns(countReturns(results), #calls)

				return retval
			end
		else
			message = function()
				-- Display preceding and following results:
				-- * nearest result that is equal to expected value
				-- * otherwise, adjacent result
				-- in case assertions fails because of index, especially off by one.
				local indexedResults: Array<IndexedResult> = {}

				if iNth <= length then
					if iNth - 1 >= 1 then
						local i = iNth - 1
						-- Is there a preceding result that is equal to expected value?
						while i >= 1 and not isEqualReturn(expected, results[i]) do
							i = i - 1
						end

						if i < 1 then
							i = iNth - 1
						end

						table.insert(indexedResults, { i, results[i] })
					end

					table.insert(indexedResults, { iNth, results[iNth] })
					if iNth + 1 <= length then
						local i = iNth + 1
						-- Is there a following result that is equal to expected value?
						while i <= length and not isEqualReturn(expected, results[i]) do
							i = i + 1
						end

						if i > length then
							i = iNth + 1
						end

						table.insert(indexedResults, { i, results[i] })
					end
				elseif length > 0 then
					-- The number of received calls is fewer than the expected number.
					local i = length
					-- Is there a result that is equal to expected value?
					while i >= 1 and not isEqualReturn(expected, results[i]) do
						i = i - 1
					end

					if i < 1 then
						i = length - 1 -- otherwise, last result
					end

					table.insert(indexedResults, { i, results[i] })
				end

				return matcherHint(matcherName, receivedName, expectedArgument, options)
					.. "\n\n"
					.. ("n: %s\n"):format(tostring(nth))
					.. ("Expected: %s\n"):format(printExpected(expected))
					.. printReceivedResults("Received: ", expected, indexedResults, #results == 1, iNth)
					.. printNumberOfReturns(countReturns(results), #calls)
			end
		end

		return { message = message, pass = pass }
	end
end