local Q=(require(script.Parent.makeEnum)).makeEnum local n=(require(script.Parent.getTime)).getTime local u={Kind=Q("\081\117\105\099\107\115\097\118\101\046\069\114\114\111\114\046\075\105\110\100",{"\068\097\116\097\083\116\111\114\101\069\114\114\111\114";"\067\111\117\108\100\078\111\116\065\099\113\117\105\114\101\076\111\099\107";"\076\111\099\107\067\111\110\115\105\115\116\101\110\099\121\086\105\111\108\097\116\105\111\110";"\083\099\104\101\109\097\086\097\108\105\100\097\116\105\111\110\070\097\105\108\101\100"})}u.__index=u function u.new(Q,y)Q=Q or{}return setmetatable({error=tostring(Q.error)or"\091\084\104\105\115 \101\114\114\111\114 \104\097\115 \110\111 \101\114\114\111\114 \116\101\120\116\046\093",trace=Q.trace,context=Q.context,kind=Q.kind;parent=y,createdTick=n(),createdTrace=debug.traceback()},u)end function u.is(Q)if type(Q)=="\116\097\098\108\101"then local n=getmetatable(Q)if type(n)=="\116\097\098\108\101"then return rawget(Q,"\101\114\114\111\114")~=nil and type(rawget(n,"\101\120\116\101\110\100"))=="\102\117\110\099\116\105\111\110"end end return false end function u.isKind(Q,n)assert(n~=nil,"\065\114\103\117\109\101\110\116 \035\050 \116\111 \081\117\105\099\107\115\097\118\101\046\069\114\114\111\114\046\105\115\075\105\110\100 \109\117\115\116 \110\111\116 \098\101 \110\105\108")return u.is(Q)and Q.kind==n end function u.extend(n,Q)Q=Q or{}Q.kind=Q.kind or n.kind return u.new(Q,n)end function u.getErrorChain(Q)local n={Q}while n[#n].parent do table.insert(n,n[#n].parent)end return n end function u.__tostring(Q)local n={string.format("-- \081\117\105\099\107\115\097\118\101\046\069\114\114\111\114\040\037\115\041 --",Q.kind or"\063")}for Q,u in ipairs(Q:getErrorChain())do table.insert(n,table.concat({u.trace or u.error;u.context},"\n"))end return table.concat(n,"\n")end return u
local makeEnum = require(script.Parent.makeEnum).makeEnum
local getTime = require(script.Parent.getTime).getTime

local Error = {
	Kind = makeEnum("Quicksave.Error.Kind", {
		"DataStoreError",
		"CouldNotAcquireLock",
		"LockConsistencyViolation",
		"SchemaValidationFailed"
	}),
}
Error.__index = Error

function Error.new(options, parent)
	options = options or {}
	return setmetatable({
		error = tostring(options.error) or "[This error has no error text.]",
		trace = options.trace,
		context = options.context,
		kind = options.kind,
		parent = parent,
		createdTick = getTime(),
		createdTrace = debug.traceback(),
	}, Error)
end

function Error.is(anything)
	if type(anything) == "table" then
		local metatable = getmetatable(anything)

		if type(metatable) == "table" then
			return rawget(anything, "error") ~= nil and type(rawget(metatable, "extend")) == "function"
		end
	end

	return false
end

function Error.isKind(anything, kind)
	assert(kind ~= nil, "Argument #2 to Quicksave.Error.isKind must not be nil")

	return Error.is(anything) and anything.kind == kind
end

function Error:extend(options)
	options = options or {}

	options.kind = options.kind or self.kind

	return Error.new(options, self)
end

function Error:getErrorChain()
	local runtimeErrors = { self }

	while runtimeErrors[#runtimeErrors].parent do
		table.insert(runtimeErrors, runtimeErrors[#runtimeErrors].parent)
	end

	return runtimeErrors
end

function Error:__tostring()
	local errorStrings = {
		string.format("-- Quicksave.Error(%s) --", self.kind or "?"),
	}

	for _, runtimeError in ipairs(self:getErrorChain()) do
		table.insert(errorStrings, table.concat({
			runtimeError.trace or runtimeError.error,
			runtimeError.context,
		}, "\n"))
	end

	return table.concat(errorStrings, "\n")
end

return Error