local y={}y.__index=y function y.IsActive(y)local c=y._is_user_mock==true and y._profile_store._mock_loaded_profiles or y._profile_store._loaded_profiles return c[y._profile_key]==y end function y.GetMetaTag(c,y)local T=c.MetaData if T==nil then return nil end return c.MetaData.MetaTags[y]end function y.SetMetaTag(T,y,c)if type(y)~="\115\116\114\105\110\103"then error("\091\080\114\111\102\105\108\101\083\101\114\118\105\099\101\093\058 \116\097\103\095\110\097\109\101 \109\117\115\116 \098\101 \097 \115\116\114\105\110\103")elseif string.len(y)==0 then error("\091\080\114\111\102\105\108\101\083\101\114\118\105\099\101\093\058 \073\110\118\097\108\105\100 \116\097\103\095\110\097\109\101")end if T._view_mode==true then error("\091\080\114\111\102\105\108\101\083\101\114\118\105\099\101\093\058 \067\097\110\'\116 \115\101\116 \109\101\116\097 \116\097\103 \105\110 \118\105\101\119 \109\111\100\101")end if T:IsActive()==false then error("\091\080\114\111\102\105\108\101\083\101\114\118\105\099\101\093\058 \080\082\079\070\073\076\069 \069\088\080\073\082\069\068 - \077\101\116\097 \116\097\103\115 \099\097\110\'\116 \098\101 \115\101\116")end T.MetaData.MetaTags[y]=c end function y.Reconcile(y)ReconcileTable(y.Data,y._profile_store._profile_template)end function y.ListenToRelease(c,y)if type(y)~="\102\117\110\099\116\105\111\110"then error("\091\080\114\111\102\105\108\101\083\101\114\118\105\099\101\093\058 \079\110\108\121 \097 \102\117\110\099\116\105\111\110 \099\097\110 \098\101 \115\101\116 \097\115 \108\105\115\116\101\110\101\114 \105\110 \080\114\111\102\105\108\101\058\076\105\115\116\101\110\084\111\082\101\108\101\097\115\101\040\041")end if c._view_mode==true then error("\091\080\114\111\102\105\108\101\083\101\114\118\105\099\101\093\058 \067\097\110\'\116 \108\105\115\116\101\110 \116\111 \080\114\111\102\105\108\101 \114\101\108\101\097\115\101 \105\110 \118\105\101\119 \109\111\100\101")end if c:IsActive()==false then local T local F local E=c.MetaData.ActiveSession if E~=nil then T=E[1]F=E[2]end y(T,F)return{Disconnect=function() end}else table.insert(c._release_listeners,y)return Madwork.NewArrayScriptConnection(c._release_listeners,y)end end function y.Save(y)if y._view_mode==true then error("\091\080\114\111\102\105\108\101\083\101\114\118\105\099\101\093\058 \067\097\110\'\116 \115\097\118\101 \080\114\111\102\105\108\101 \105\110 \118\105\101\119 \109\111\100\101")end if y:IsActive()==false then error("\091\080\114\111\102\105\108\101\083\101\114\118\105\099\101\093\058 \080\082\079\070\073\076\069 \069\088\080\073\082\069\068 - \067\097\110\'\116 \115\097\118\101 \080\114\111\102\105\108\101")end RemoveProfileFromAutoSave(y)AddProfileToAutoSave(y);(coroutine.wrap(SaveProfileAsync))(y)end function y.Release(y)if y._view_mode==true then error("\091\080\114\111\102\105\108\101\083\101\114\118\105\099\101\093\058 \067\097\110\'\116 \114\101\108\101\097\115\101 \080\114\111\102\105\108\101 \105\110 \118\105\101\119 \109\111\100\101")end if y:IsActive()==true then(coroutine.wrap(SaveProfileAsync))(y,true)end end
-- Profile object:

local Profile = {
	--[[
		Data = {}, -- [table] -- Loaded once after ProfileStore:LoadProfileAsync() finishes
		MetaData = {}, -- [table] -- Updated with every auto-save
		GlobalUpdates = GlobalUpdates, -- [GlobalUpdates]
		
		_profile_store = ProfileStore, -- [ProfileStore]
		_profile_key = "", -- [string]
		
		_release_listeners = {listener, ...} / nil, -- [table / nil]
		
		_view_mode = true / nil, -- [bool / nil]
		
		_load_timestamp = os.clock(),
		
		_is_user_mock = false, -- ProfileStore.Mock
	--]]
}
Profile.__index = Profile

function Profile:IsActive() --> [bool]
	local loaded_profiles = self._is_user_mock == true and self._profile_store._mock_loaded_profiles
		or self._profile_store._loaded_profiles
	return loaded_profiles[self._profile_key] == self
end

function Profile:GetMetaTag(tag_name) --> value
	local meta_data = self.MetaData
	if meta_data == nil then
		return nil
		-- error("[ProfileService]: This Profile hasn't been loaded before - MetaData not available")
	end
	return self.MetaData.MetaTags[tag_name]
end

function Profile:SetMetaTag(tag_name, value)
	if type(tag_name) ~= "string" then
		error("[ProfileService]: tag_name must be a string")
	elseif string.len(tag_name) == 0 then
		error("[ProfileService]: Invalid tag_name")
	end
	if self._view_mode == true then
		error("[ProfileService]: Can't set meta tag in view mode")
	end
	if self:IsActive() == false then
		error("[ProfileService]: PROFILE EXPIRED - Meta tags can't be set")
	end
	self.MetaData.MetaTags[tag_name] = value
end

function Profile:Reconcile()
	ReconcileTable(self.Data, self._profile_store._profile_template)
end

function Profile:ListenToRelease(listener) --> [ScriptConnection] (place_id / nil, game_job_id / nil)
	if type(listener) ~= "function" then
		error("[ProfileService]: Only a function can be set as listener in Profile:ListenToRelease()")
	end
	if self._view_mode == true then
		error("[ProfileService]: Can't listen to Profile release in view mode")
	end
	if self:IsActive() == false then
		-- Call release listener immediately if profile is expired
		local place_id
		local game_job_id
		local active_session = self.MetaData.ActiveSession
		if active_session ~= nil then
			place_id = active_session[1]
			game_job_id = active_session[2]
		end
		listener(place_id, game_job_id)
		return {
			Disconnect = function() end,
		}
	else
		table.insert(self._release_listeners, listener)
		return Madwork.NewArrayScriptConnection(self._release_listeners, listener)
	end
end

function Profile:Save()
	if self._view_mode == true then
		error("[ProfileService]: Can't save Profile in view mode")
	end
	if self:IsActive() == false then
		error("[ProfileService]: PROFILE EXPIRED - Can't save Profile")
	end
	-- We don't want auto save to trigger too soon after manual saving - this will reset the auto save timer:
	RemoveProfileFromAutoSave(self)
	AddProfileToAutoSave(self)
	-- Call save function in a new thread:
	coroutine.wrap(SaveProfileAsync)(self)
end

function Profile:Release()
	if self._view_mode == true then
		error("[ProfileService]: Can't release Profile in view mode")
	end
	if self:IsActive() == true then
		coroutine.wrap(SaveProfileAsync)(self, true) -- Call save function in a new thread with release_from_session = true
	end
end
