local J={}local function s(J,s)error(("\066\097\100 \105\110\100\101\120 \037\113"):format(tostring(s)),2)end local q={__index=s;__newindex=s}function J.readonly(J)return setmetatable(J,q)end function J.count(J)local s=0 for J,q in pairs(J)do s=s+1 end return s end function J.getOrCreateValue(J,s,q,d)assert(typeof(J)=="\073\110\115\116\097\110\099\101","\066\097\100 \097\114\103\117\109\101\110\116 \'\112\097\114\101\110\116\'")assert(type(s)=="\115\116\114\105\110\103","\066\097\100 \097\114\103\117\109\101\110\116 \'\105\110\115\116\097\110\099\101\084\121\112\101\'")assert(type(q)=="\115\116\114\105\110\103","\066\097\100 \097\114\103\117\109\101\110\116 \'\110\097\109\101\'")local Y=J:FindFirstChild(q)if Y then if not Y:IsA(s)then warn(("\091\085\116\105\108\115\046\103\101\116\079\114\067\114\101\097\116\101\086\097\108\117\101\093 - \086\097\108\117\101 \111\102 \116\121\112\101 \037\113 \111\102 \110\097\109\101 \037\113 \105\115 \111\102 \116\121\112\101 \037\113 \105\110 \037\115 \105\110\115\116\101\097\100"):format(s,q,Y.ClassName,Y:GetFullName()))end return Y else local Y=Instance.new(s)Y.Name=q Y.Value=d Y.Parent=J return Y end end function J.getValue(J,s,q,d)assert(typeof(J)=="\073\110\115\116\097\110\099\101","\066\097\100 \097\114\103\117\109\101\110\116 \'\112\097\114\101\110\116\'")assert(type(s)=="\115\116\114\105\110\103","\066\097\100 \097\114\103\117\109\101\110\116 \'\105\110\115\116\097\110\099\101\084\121\112\101\'")assert(type(q)=="\115\116\114\105\110\103","\066\097\100 \097\114\103\117\109\101\110\116 \'\110\097\109\101\'")local Y=J:FindFirstChild(q)if Y then if Y:IsA(s)then return Y.Value else warn(("\091\085\116\105\108\115\046\103\101\116\086\097\108\117\101\093 - \086\097\108\117\101 \111\102 \116\121\112\101 \037\113 \111\102 \110\097\109\101 \037\113 \105\115 \111\102 \116\121\112\101 \037\113 \105\110 \037\115 \105\110\115\116\101\097\100"):format(s,q,Y.ClassName,Y:GetFullName()))return nil end else return d end end function J.setValue(J,s,q,d)assert(typeof(J)=="\073\110\115\116\097\110\099\101","\066\097\100 \097\114\103\117\109\101\110\116 \'\112\097\114\101\110\116\'")assert(type(s)=="\115\116\114\105\110\103","\066\097\100 \097\114\103\117\109\101\110\116 \'\105\110\115\116\097\110\099\101\084\121\112\101\'")assert(type(q)=="\115\116\114\105\110\103","\066\097\100 \097\114\103\117\109\101\110\116 \'\110\097\109\101\'")local Y=J:FindFirstChild(q)if Y then if not Y:IsA(s)then warn(("\091\085\116\105\108\115\046\115\101\116\086\097\108\117\101\093 - \086\097\108\117\101 \111\102 \116\121\112\101 \037\113 \111\102 \110\097\109\101 \037\113 \105\115 \111\102 \116\121\112\101 \037\113 \105\110 \037\115 \105\110\115\116\101\097\100"):format(s,q,Y.ClassName,Y:GetFullName()))end Y.Value=d else local Y=Instance.new(s)Y.Name=q Y.Value=d Y.Parent=J end end function J.getOrCreateFolder(J,s)local q=J:FindFirstChild(s)if q then return q else local q=Instance.new("\070\111\108\100\101\114")q.Name=s q.Parent=J return q end end return J
--[=[
	@private
	@class Utils
]=]

local Utils = {}

local function errorOnIndex(_, index)
	error(("Bad index %q"):format(tostring(index)), 2)
end

local READ_ONLY_METATABLE = {
	__index = errorOnIndex,
	__newindex = errorOnIndex,
}

function Utils.readonly(_table)
	return setmetatable(_table, READ_ONLY_METATABLE)
end

function Utils.count(_table)
	local count = 0
	for _, _ in pairs(_table) do
		count = count + 1
	end
	return count
end

function Utils.getOrCreateValue(parent, instanceType, name, defaultValue)
	assert(typeof(parent) == "Instance", "Bad argument 'parent'")
	assert(type(instanceType) == "string", "Bad argument 'instanceType'")
	assert(type(name) == "string", "Bad argument 'name'")

	local foundChild = parent:FindFirstChild(name)
	if foundChild then
		if not foundChild:IsA(instanceType) then
			warn(
				("[Utils.getOrCreateValue] - Value of type %q of name %q is of type %q in %s instead"):format(
					instanceType,
					name,
					foundChild.ClassName,
					foundChild:GetFullName()
				)
			)
		end

		return foundChild
	else
		local newChild = Instance.new(instanceType)
		newChild.Name = name
		newChild.Value = defaultValue
		newChild.Parent = parent

		return newChild
	end
end

function Utils.getValue(parent, instanceType, name, default)
	assert(typeof(parent) == "Instance", "Bad argument 'parent'")
	assert(type(instanceType) == "string", "Bad argument 'instanceType'")
	assert(type(name) == "string", "Bad argument 'name'")

	local foundChild = parent:FindFirstChild(name)
	if foundChild then
		if foundChild:IsA(instanceType) then
			return foundChild.Value
		else
			warn(
				("[Utils.getValue] - Value of type %q of name %q is of type %q in %s instead"):format(
					instanceType,
					name,
					foundChild.ClassName,
					foundChild:GetFullName()
				)
			)
			return nil
		end
	else
		return default
	end
end

function Utils.setValue(parent, instanceType, name, value)
	assert(typeof(parent) == "Instance", "Bad argument 'parent'")
	assert(type(instanceType) == "string", "Bad argument 'instanceType'")
	assert(type(name) == "string", "Bad argument 'name'")

	local foundChild = parent:FindFirstChild(name)
	if foundChild then
		if not foundChild:IsA(instanceType) then
			warn(
				("[Utils.setValue] - Value of type %q of name %q is of type %q in %s instead"):format(
					instanceType,
					name,
					foundChild.ClassName,
					foundChild:GetFullName()
				)
			)
		end

		foundChild.Value = value
	else
		local newChild = Instance.new(instanceType)
		newChild.Name = name
		newChild.Value = value
		newChild.Parent = parent
	end
end

function Utils.getOrCreateFolder(parent, folderName)
	local found = parent:FindFirstChild(folderName)
	if found then
		return found
	else
		local folder = Instance.new("Folder")
		folder.Name = folderName
		folder.Parent = parent
		return folder
	end
end

return Utils
