local Q=require(script.Parent.Parent.Promise)local n=require(script.Parent.Parent.t)local u=require(script.Parent.Document)local y=(require(script.Parent.stackSkipAssert)).stackSkipAssert local V=(require(script.Parent.getTime)).getTime local h=7 local b={}b.__index=b function b.new(Q,u)u=u or{}y(u.schema~=nil,"\089\111\117 \109\117\115\116 \112\114\111\118\105\100\101 \097 \115\099\104\101\109\097 \105\110 \111\112\116\105\111\110\115")local V=n.strictInterface(u.schema)local h,J=V(u.defaultData)if not h then error(("\084\104\101 \100\101\102\097\117\108\116 \100\097\116\097 \121\111\117 \112\114\111\118\105\100\101\100 \102\111\114 \099\111\108\108\101\099\116\105\111\110 \037\113 \100\111\101\115 \110\111\116 \112\097\115\115 \121\111\117\114 \115\099\104\101\109\097 \114\101\113\117\105\114\101\109\101\110\116\115\046\n\n\037\115\n"):format(Q,J),2)end return setmetatable({name=Q,schema=u.schema;runSchema=V;defaultData=u.defaultData;_migrations=u.migrations or{},_activeDocuments={},_justClosedDocuments={}},b)end function b.getDocument(y,n)n=tostring(n)if y._justClosedDocuments[n]then local u=h-(V()-y._justClosedDocuments[n])if u>0 then warn(("\068\111\099\117\109\101\110\116 \037\113 \105\110 \037\113 \119\097\115 \114\101\099\101\110\116\108\121 \099\108\111\115\101\100\046 \089\111\117\114 \103\101\116\068\111\099\117\109\101\110\116 \099\097\108\108 \119\105\108\108 \098\101 \100\101\108\097\121\101\100 \098\121 \037\046\049\102 \115\101\099\111\110\100\115\046"):format(n,y.name,u));(Q.delay(u)):await()end end if y._activeDocuments[n]==nil then y._activeDocuments[n]=u.new(y,n);(y._activeDocuments[n]:readyPromise()):catch(function()y._activeDocuments[n]=nil end)end return y._activeDocuments[n]:readyPromise()end function b.getLatestMigrationVersion(Q)return#Q._migrations end function b.validateData(n,Q)return n.runSchema(Q)end function b.keyExists(n,Q)return n.schema[Q]~=nil end function b.validateKey(u,Q,n)if u:keyExists(Q)then return u.schema[Q](n)else return false,("\075\101\121 \037\113 \105\115 \110\111\116 \112\114\101\115\101\110\116 \105\110 \037\113\'\115 \115\099\104\101\109\097\046"):format(Q,u.name)end end function b._removeDocument(u,n)u._justClosedDocuments[n]=V()u._activeDocuments[n]=nil;(Q.delay(h)):andThen(function()u._justClosedDocuments[n]=nil end)end return b
local Promise = require(script.Parent.Parent.Promise)
local t = require(script.Parent.Parent.t)
local Document = require(script.Parent.Document)
local stackSkipAssert = require(script.Parent.stackSkipAssert).stackSkipAssert
local getTime = require(script.Parent.getTime).getTime

local DOCUMENT_COOLDOWN = 7

local Collection = {}
Collection.__index = Collection

function Collection.new(name, options)
	options = options or {}

	stackSkipAssert(options.schema ~= nil, "You must provide a schema in options")

	local runSchema = t.strictInterface(options.schema)

	local defaultDataOk, defaultDataError = runSchema(options.defaultData)

	if not defaultDataOk then
		error(("The default data you provided for collection %q does not pass your schema requirements.\n\n%s\n"):format(
			name,
			defaultDataError
		), 2)
	end

	return setmetatable({
		name = name;
		schema = options.schema;
		runSchema = runSchema;
		defaultData = options.defaultData;
		_migrations = options.migrations or {};
		_activeDocuments = {};
		_justClosedDocuments = {};
	}, Collection)
end

function Collection:getDocument(name)
	name = tostring(name)

	if self._justClosedDocuments[name] then
		local waitTime = DOCUMENT_COOLDOWN - (getTime() - self._justClosedDocuments[name])

		if waitTime > 0 then
			warn(("Document %q in %q was recently closed. Your getDocument call will be delayed by %.1f seconds."):format(
				name,
				self.name,
				waitTime
			))
			Promise.delay(waitTime):await() -- todo:  yields
		end
	end

	if self._activeDocuments[name] == nil then
		self._activeDocuments[name] = Document.new(self, name)

		self._activeDocuments[name]:readyPromise():catch(function()
			self._activeDocuments[name] = nil
		end)
	end

	return self._activeDocuments[name]:readyPromise()
end

function Collection:getLatestMigrationVersion()
	return #self._migrations
end

function Collection:validateData(data)
	return self.runSchema(data)
end

function Collection:keyExists(key)
	return self.schema[key] ~= nil
end

function Collection:validateKey(key, value)
	if self:keyExists(key) then
		return self.schema[key](value)
	else
		return false, ("Key %q is not present in %q's schema."):format(key, self.name)
	end
end

function Collection:_removeDocument(name)
	self._justClosedDocuments[name] = getTime()
	self._activeDocuments[name] = nil

	Promise.delay(DOCUMENT_COOLDOWN):andThen(function()
		self._justClosedDocuments[name] = nil
	end)
end

return Collection