-- ROBLOX deviation: predeclare variables

local isTemplates, normaliseTable, formatTitle, interpolateEscapedPlaceholders, isTable, colToRow, normalisePlaceholderValue, getMatchingPlaceholders, interpolatePrettyPlaceholder, interpolateTitleIndex

local function default(title: string, arrayTable: Global_ArrayTable): EachTests
	if isTemplates(title, arrayTable) then
		return Array.map(arrayTable, function(template, index)
			return {
				arguments = { template },
				title = interpolateVariables(title, template, index):gsub(
					ESCAPED_PLACEHOLDER_PREFIX_PATTERN,
					PLACEHOLDER_PREFIX
				),
			}
		end)
	end
	return Array.map(normaliseTable(arrayTable), function(row, index)
		return {
			arguments = Array.map(row, function(element)
				return element
			end),
			title = formatTitle(title, row, index),
		}
	end)
end

exports.default = default

function isTemplates(
	title: string,
	arrayTable: Global_ArrayTable
): boolean --[[ ROBLOX TODO: Unhandled node for type: TSTypePredicate ]] --[[ arrayTable is Templates ]]
	return not SUPPORTED_PLACEHOLDERS:test(interpolateEscapedPlaceholders(title))
		and not isTable(arrayTable)
		and Array.every(arrayTable, function(col)
			return col ~= nil and typeof(col) == "table"
		end)
end

function normaliseTable(table_: Global_ArrayTable): Global_Table
	return if isTable(table_) then table_ else Array.map(table_, colToRow)
end

function isTable(
	table_: Global_ArrayTable
): boolean --[[ ROBLOX TODO: Unhandled node for type: TSTypePredicate ]] --[[ table is Global.Table ]]
	return Array.every(table_, Array.isArray)
end

function colToRow(col: Global_Col): Global_Row
	return { col }
end

function formatTitle(title: string, row: Global_Row, rowIndex: number): string
	return Array.reduce(row, function(formattedTitle, value)
		local placeholder = getMatchingPlaceholders(formattedTitle)[1]
		local normalisedValue = normalisePlaceholderValue(value)
		if not Boolean.toJSBoolean(placeholder) then
			return formattedTitle
		end
		if placeholder == PRETTY_PLACEHOLDER then
			return interpolatePrettyPlaceholder(formattedTitle, normalisedValue)
		end
		return format(formattedTitle, normalisedValue)
	end, interpolateTitleIndex(interpolateEscapedPlaceholders(title), rowIndex)):gsub(
		JEST_EACH_PLACEHOLDER_ESCAPE,
		ESCAPED_PLACEHOLDER_PREFIX
	)
end

function normalisePlaceholderValue(value: any)
	if typeof(value) == "string" then
		local ref = value:gsub(PLACEHOLDER_PREFIX, JEST_EACH_PLACEHOLDER_ESCAPE)
		return ref
	else
		return value
	end
end

function getMatchingPlaceholders(title: string): Array<string>
	-- ROBLOX deviation START: js .match with /g flag and :gmatch are used in a different way
	local ref
	for match in title:gmatch(SUPPORTED_PLACEHOLDERS_PATTERN) do
		if ref == nil then
			ref = {}
		end
		table.insert(ref, match)
	end
	-- ROBLOX deviation END
	return ref or {}
end

function interpolateEscapedPlaceholders(title: string)
	local ref = title:gsub(ESCAPED_PLACEHOLDER_PREFIX_PATTERN, JEST_EACH_PLACEHOLDER_ESCAPE)
	return ref
end

function interpolateTitleIndex(title: string, index: number)
	local ref = title:gsub(INDEX_PLACEHOLDER, tostring(index), 1)
	return ref
end

function interpolatePrettyPlaceholder(title: string, value: any)
	local ref = title:gsub(PRETTY_PLACEHOLDER_PATTERN, pretty(value, { maxDepth = 1, min = true }), 1)
	return ref
end

return exports
