local function u(u,Y,M)return string.format("\091\083\116\111\114\101\058\"\037\115\"\059\037\115\075\101\121\058\"\037\115\"\093",u,Y~=nil and string.format("\083\099\111\112\101\058\"\037\115\"\059",Y)or"",M)end local function Y(u,Y)if CustomWriteQueue[u]~=nil then CustomWriteQueue[u][Y]=nil if next(CustomWriteQueue[u])==nil then CustomWriteQueue[u]=nil end end end local function M(u,M)if CustomWriteQueue[u]~=nil then if CustomWriteQueue[u][M]~=nil then local G=CustomWriteQueue[u][M]local r=G.Queue if G.CleanupJob==nil then G.CleanupJob=RunService.Heartbeat:Connect(function()if os.clock()-G.LastWrite>SETTINGS.RobloxWriteCooldown and#r==0 then G.CleanupJob:Disconnect()Y(u,M)end end)end elseif next(CustomWriteQueue[u])==nil then CustomWriteQueue[u]=nil end end end local function G(u,Y,M)if CustomWriteQueue[Y]==nil then CustomWriteQueue[Y]={}end if CustomWriteQueue[Y][M]==nil then CustomWriteQueue[Y][M]={LastWrite=0,Queue={},CleanupJob=nil}end local G=CustomWriteQueue[Y][M]local r=G.Queue if G.CleanupJob~=nil then G.CleanupJob:Disconnect()G.CleanupJob=nil end if os.clock()-G.LastWrite>SETTINGS.RobloxWriteCooldown and#r==0 then G.LastWrite=os.clock()return u()else table.insert(r,u)while true do if os.clock()-G.LastWrite>SETTINGS.RobloxWriteCooldown and r[1]==u then table.remove(r,1)G.LastWrite=os.clock()return u()end Madwork.HeartbeatWait()end end end local function r(u,Y)local M=CustomWriteQueue[u]if M~=nil then M=M[Y]return M==nil or#M.Queue==0 end return true end local function x()while IsLiveCheckActive==true do Madwork.HeartbeatWait()end end local function j(u)while u._is_pending==true do Madwork.HeartbeatWait()end end local function k(Y,M,G,r)warn("\091\080\114\111\102\105\108\101\083\101\114\118\105\099\101\093\058 \068\097\116\097\083\116\111\114\101 \065\080\073 \101\114\114\111\114 "..(u(M,G,r)..(" - \""..(tostring(Y).."\""))))table.insert(IssueQueue,os.clock())ProfileService.IssueSignal:Fire(tostring(Y),M,r)end local function y(Y,M,G)warn("\091\080\114\111\102\105\108\101\083\101\114\118\105\099\101\093\058 \082\101\115\111\108\118\101\100 \112\114\111\102\105\108\101 \099\111\114\114\117\112\116\105\111\110 "..u(Y,M,G))ProfileService.CorruptionSignal:Fire(Y,G)end local function o(u,Y,M,G)local r=u[Y]if r==nil then r={}u[Y]=r end local x=G(r[M])if x==nil then return nil else r[M]=DeepCopyTable(x)return DeepCopyTable(r[M])end end local function f(u)return u[1]==PlaceId and u[2]==JobId end


local function IdentifyProfile(store_name, store_scope, key)
	return string.format(
		"[Store:\"%s\";%sKey:\"%s\"]",
		store_name,
		store_scope ~= nil and string.format("Scope:\"%s\";", store_scope) or "",
		key
	)
end

local function CustomWriteQueueCleanup(store, key)
	if CustomWriteQueue[store] ~= nil then
		CustomWriteQueue[store][key] = nil
		if next(CustomWriteQueue[store]) == nil then
			CustomWriteQueue[store] = nil
		end
	end
end

local function CustomWriteQueueMarkForCleanup(store, key)
	if CustomWriteQueue[store] ~= nil then
		if CustomWriteQueue[store][key] ~= nil then

			local queue_data = CustomWriteQueue[store][key]
			local queue = queue_data.Queue

			if queue_data.CleanupJob == nil then

				queue_data.CleanupJob = RunService.Heartbeat:Connect(function()
					if os.clock() - queue_data.LastWrite > SETTINGS.RobloxWriteCooldown and #queue == 0 then
						queue_data.CleanupJob:Disconnect()
						CustomWriteQueueCleanup(store, key)
					end
				end)

			end

		elseif next(CustomWriteQueue[store]) == nil then
			CustomWriteQueue[store] = nil
		end
	end
end

local function CustomWriteQueueAsync(callback, store, key) --> ... -- Passed return from callback

	if CustomWriteQueue[store] == nil then
		CustomWriteQueue[store] = {}
	end
	if CustomWriteQueue[store][key] == nil then
		CustomWriteQueue[store][key] = {LastWrite = 0, Queue = {}, CleanupJob = nil}
	end

	local queue_data = CustomWriteQueue[store][key]
	local queue = queue_data.Queue

	-- Cleanup job:

	if queue_data.CleanupJob ~= nil then
		queue_data.CleanupJob:Disconnect()
		queue_data.CleanupJob = nil
	end

	-- Queue logic:

	if os.clock() - queue_data.LastWrite > SETTINGS.RobloxWriteCooldown and #queue == 0 then
		queue_data.LastWrite = os.clock()
		return callback()
	else
		table.insert(queue, callback)
		while true do
			if os.clock() - queue_data.LastWrite > SETTINGS.RobloxWriteCooldown and queue[1] == callback then
				table.remove(queue, 1)
				queue_data.LastWrite = os.clock()
				return callback()
			end
			Madwork.HeartbeatWait()
		end
	end

end

local function IsCustomWriteQueueEmptyFor(store, key) --> is_empty [bool]
	local lookup = CustomWriteQueue[store]
	if lookup ~= nil then
		lookup = lookup[key]
		return lookup == nil or #lookup.Queue == 0
	end
	return true
end

local function WaitForLiveAccessCheck() -- This function was created to prevent the ProfileService module yielding execution when required
	while IsLiveCheckActive == true do
		Madwork.HeartbeatWait()
	end
end

local function WaitForPendingProfileStore(profile_store)
	while profile_store._is_pending == true do
		Madwork.HeartbeatWait()
	end
end

local function RegisterIssue(error_message, store_name, store_scope, profile_key) -- Called when a DataStore API call errors
	warn("[ProfileService]: DataStore API error " .. IdentifyProfile(store_name, store_scope, profile_key) .. " - \"" .. tostring(error_message) .. "\"")
	table.insert(IssueQueue, os.clock()) -- Adding issue time to queue
	ProfileService.IssueSignal:Fire(tostring(error_message), store_name, profile_key)
end

local function RegisterCorruption(store_name, store_scope, profile_key) -- Called when a corrupted profile is loaded
	warn("[ProfileService]: Resolved profile corruption " .. IdentifyProfile(store_name, store_scope, profile_key))
	ProfileService.CorruptionSignal:Fire(store_name, profile_key)
end

local function MockUpdateAsync(mock_data_store, profile_store_name, key, transform_function)
	local profile_store = mock_data_store[profile_store_name]
	if profile_store == nil then
		profile_store = {}
		mock_data_store[profile_store_name] = profile_store
	end
	local transform = transform_function(profile_store[key])
	if transform == nil then
		return nil
	else
		profile_store[key] = DeepCopyTable(transform)
		return DeepCopyTable(profile_store[key])
	end
end

local function IsThisSession(session_tag)
	return session_tag[1] == PlaceId and session_tag[2] == JobId
end
