-- Based on https://developmentarc.gitbooks.io/react-indepth/content/life_cycle/update/using_should_component_update.html

function TableUtils.shallowEqual(left, right)
	if left == right then
		return true
	end
	if type(left) ~= "table" or type(right) ~= "table" then
		return false
	end
	local leftKeys = TableUtils.keys(left)
	local rightKeys = TableUtils.keys(right)
	if #leftKeys ~= #rightKeys then
		return false
	end
	return TableUtils.all(
		left,
		function(value, key)
			return value == right[key]
		end
	)
end

function TableUtils.serialize(input, serializer)
	serializer = serializer or function(value)
			return tostring(value)
		end
	assert(type(input) == "table")
	assert(type(serializer) == "function")
	return "{" ..
		table.concat(
			TableUtils.map(
				input,
				function(element, i)
					return tostring(i) .. "=" .. serializer(element)
				end
			),
			","
		) ..
			"}"
end

function TableUtils.append(...)
	local result = {}
	for i = 1, select("#", ...) do
		local x = select(i, ...)
		if type(x) == "table" then
			for _, y in ipairs(x) do
				table.insert(result, y)
			end
		else
			table.insert(result, x)
		end
	end

	return result
end

function TableUtils.sort(input, comparator)
	assert(tea.table(input), input)

	local FunctionUtils = require(script.Parent.FunctionUtils)
	assert(comparator == nil or FunctionUtils.isCallable(comparator), "comparator must be callable or nil")

	comparator = comparator or function(a, b)
			return a < b
		end

	table.sort(
		input,
		function(a, b)
			local result = comparator(a, b)

			if type(result) ~= "boolean" and result ~= nil then
				error("sort comparator must return a boolean or nil")
			end

			return result
		end
	)

	return input
end

return TableUtils
