-- ROBLOX TODO: continue to implement prettyFormat plugins

local prettyFormatPlugins = PrettyFormat.plugins
local PLUGINS = {
	prettyFormatPlugins.AsymmetricMatcher,
	-- ROBLOX deviation: Roblox Instance matchers
	prettyFormatPlugins.RobloxInstance,
}

type MatcherHintColor = (string) -> string -- subset of Chalk type

export type MatcherHintOptions = {
	comment: string?,
	-- ROBLOX TODO? should be MatcherHintColor like in upstream, but requires modeling Chalk differently
	expectedColor: MatcherHintColor?,
	isDirectExpectCall: boolean?,
	isNot: boolean?,
	promise: string?,
	-- ROBLOX TODO? should be MatcherHintColor like in upstream, but requires modeling Chalk differently
	receivedColor: string?,
	secondArgument: string?,
	-- ROBLOX TODO? should be MatcherHintColor like in upstream, but requires modeling Chalk differently
	secondArgumentColor: MatcherHintColor?,
}

export type DiffOptions = ImportDiffOptions

local EXPECTED_COLOR = chalk.green
local RECEIVED_COLOR = chalk.red
local INVERTED_COLOR = chalk.inverse
local BOLD_WEIGHT = chalk.bold
local DIM_COLOR = chalk.dim

local MULTILINE_REGEXP = "\n"
local SPACE_SYMBOL = utf8.char(183) -- middle dot

local NUMBERS = {
	"zero",
	"one",
	"two",
	"three",
	"four",
	"five",
	"six",
	"seven",
	"eight",
	"nine",
	"ten",
	"eleven",
	"twelve",
	"thirteen",
}

local SUGGEST_TO_CONTAIN_EQUAL =
	"Looks like you wanted to test for object/array equality with the stricter `toContain` matcher. You probably need to use `toContainEqual` instead."

local replaceTrailingSpaces, getCommonAndChangedSubstrings, isLineDiffable, shouldPrintDiff, replaceMatchedToAsymmetricMatcher, isAsymmetricMatcher
local matcherErrorMessage, matcherHint

local function stringify(object: any, maxDepth: number?): string
	-- ROBLOX deviation: Added this if logic to deal with handling nil values in Lua tables
	if object == Symbol.for_("$$nil") then
		object = nil
	end
	maxDepth = maxDepth or 10

	local MAX_LENGTH = 10000
	local result

	local ok = pcall(function()
		result = prettyFormat(object, {
			maxDepth = maxDepth,
			min = true,
			plugins = PLUGINS,
		})
	end)

	if not ok then
		result = prettyFormat(object, {
			callToJSON = false,
			maxDepth = maxDepth,
			min = true,
			plugins = PLUGINS,
		})
	end

	if #result >= MAX_LENGTH and maxDepth > 1 then
		--[[
			ROBLOX TODO: Remove the "if maxDepth" check once it can pass through
			Luau cleanly
		]]
		if maxDepth then
			return stringify(object, math.floor(maxDepth / 2))
		end
	end
	return result
end

local function highlightTrailingWhitespace(text: string): string
	return text:gsub("%s+$", function(s)
		return INVERTED_COLOR(s)
	end)
end
