local n=(require(script.Parent.loader)).load(script)local P=game:GetService("\087\111\114\107\115\112\097\099\101")local x=game:GetService("\085\115\101\114\073\110\112\117\116\083\101\114\118\105\099\101")local r=game:GetService("\083\116\097\114\116\101\114\071\117\105")local N=game:GetService("\084\101\108\101\112\111\114\116\083\101\114\118\105\099\101")local l=n("\065\116\116\114\105\098\117\116\101\086\097\108\117\101")local e=n("\077\097\105\100")local z=n("\080\108\097\121\101\114\071\117\105\085\116\105\108\115")local h=n("\082\120")local t=n("\083\111\102\116\083\104\117\116\100\111\119\110\067\111\110\115\116\097\110\116\115")local p=n("\083\111\102\116\083\104\117\116\100\111\119\110\084\114\097\110\115\108\097\116\111\114")local T=n("\083\111\102\116\083\104\117\116\100\111\119\110\085\073")local X=n("\082\120\086\097\108\117\101\066\097\115\101\085\116\105\108\115")local u={}local O={Enum.CoreGuiType.PlayerList,Enum.CoreGuiType.Health;Enum.CoreGuiType.Backpack;Enum.CoreGuiType.Chat;Enum.CoreGuiType.EmotesMenu,Enum.CoreGuiType.All}function u.Init(x,n)assert(not x._serviceBag,"\065\108\114\101\097\100\121 \105\110\105\116\105\097\108\105\122\101\100")x._serviceBag=assert(n,"\078\111 \115\101\114\118\105\099\101\066\097\103")x._maid=e.new()x._translator=x._serviceBag:GetService(p)x._isLobby=l.new(P,t.IS_SOFT_SHUTDOWN_LOBBY_ATTRIBUTE,false)x._isUpdating=l.new(P,t.IS_SOFT_SHUTDOWN_UPDATING_ATTRIBUTE,false)x._localTeleportDataSaysIsLobby=Instance.new("\066\111\111\108\086\097\108\117\101")x._localTeleportDataSaysIsLobby.Value=false x._maid:GiveTask(x._localTeleportDataSaysIsLobby)x._isArrivingAfterShutdown=Instance.new("\066\111\111\108\086\097\108\117\101")x._isArrivingAfterShutdown.Value=false x._maid:GiveTask(x._isArrivingAfterShutdown)task.spawn(function()if x:_queryLocalTeleportInfo()then x._localTeleportDataSaysIsLobby.Value=true end if x:_queryIsArrivingAfterShutdown()then x._isArrivingAfterShutdown.Value=true end end)x._maid:GiveTask((h.combineLatest({isLobby=x._isLobby:Observe(),isShuttingDown=x._isUpdating:Observe();localTeleportDataSaysIsLobby=X.observeValue(x._localTeleportDataSaysIsLobby),isArrivingAfterShutdown=X.observeValue(x._isArrivingAfterShutdown)})):Subscribe(function(n)if n.isLobby or n.localTeleportDataSaysIsLobby then x._maid._shutdownUI=nil if not x._maid._lobbyUI then local n x._maid._lobbyUI,n=x:_showSoftShutdownUI("\115\104\117\116\100\111\119\110\046\108\111\098\098\121\046\116\105\116\108\101","\115\104\117\116\100\111\119\110\046\108\111\098\098\121\046\115\117\098\116\105\116\108\101",true)N:SetTeleportGui(n)end elseif n.isShuttingDown then local n x._maid._shutdownUI,n=x:_showSoftShutdownUI("\115\104\117\116\100\111\119\110\046\114\101\115\116\097\114\116\046\116\105\116\108\101","\115\104\117\116\100\111\119\110\046\114\101\115\116\097\114\116\046\115\117\098\116\105\116\108\101")N:SetTeleportGui(n)x._maid._lobbyUI=nil elseif n.isArrivingAfterShutdown then local n=x:_showSoftShutdownUI("\115\104\117\116\100\111\119\110\046\099\111\109\112\108\101\116\101\046\116\105\116\108\101","\115\104\117\116\100\111\119\110\046\099\111\109\112\108\101\116\101\046\115\117\098\116\105\116\108\101",true)x._maid._shutdownUI=n x._maid._lobbyUI=nil task.delay(1,function()if x._maid._shutdownUI==n then x._maid._shutdownUI=nil end end)else x._maid._shutdownUI=nil x._maid._lobbyUI=nil end end))end function u._queryIsArrivingAfterShutdown(n)local P=N:GetLocalPlayerTeleportData()if type(P)=="\116\097\098\108\101"and P.isSoftShutdownArrivingIntoUpdatedServer then return true else return false end end function u._queryLocalTeleportInfo(n)local P=N:GetLocalPlayerTeleportData()if type(P)=="\116\097\098\108\101"and P.isSoftShutdownReserveServer then return true else return false end end function u._showSoftShutdownUI(r,n,P,x)local N=e.new()local l=e.new()local h=Instance.new("\083\099\114\101\101\110\071\117\105")h.Name="\083\111\102\116\083\104\117\116\100\111\119\110\083\099\114\101\101\110\071\117\105"h.ResetOnSpawn=false h.AutoLocalize=false h.IgnoreGuiInset=true h.DisplayOrder=10000000000.0 h.Parent=z.getPlayerGui()h.ZIndexBehavior=Enum.ZIndexBehavior.Sibling l:GiveTask(h)local t=T.new()l:GiveTask(t)N:GiveTask(function()t:Hide()task.delay(1,function()l:Destroy()end)end)r:_hideCoreGuiUI(l,h);(N:GivePromise(r._translator:PromiseFormatByKey(P))):Then(function(n)t:SetSubtitle(n)end);(N:GivePromise(r._translator:PromiseFormatByKey(n))):Then(function(n)t:SetTitle(n)end)t:Show(x)t.Gui.Parent=h return N,h end function u._hideCoreGuiUI(N,n,P)if not x.ModalEnabled then x.ModalEnabled=true n:GiveTask(function()x.ModalEnabled=false end)end local l=z.getPlayerGui()local e={}local function h(n)if n:IsA("\083\099\114\101\101\110\071\117\105")and(n~=P and n.Enabled)then e[n]=n n.Enabled=false end end for n,P in pairs(l:GetChildren())do h(P)end n:GiveTask(l.ChildAdded:Connect(function(n)h(n)end))n:GiveTask(l.ChildRemoved:Connect(function(n)e[n]=nil end))n:GiveTask(function()for n,P in pairs(e)do n.Enabled=true end end)for P,x in pairs(O)do task.spawn(function()if r:GetCoreGuiEnabled(x)then r:SetCoreGuiEnabled(x,false)n:GiveTask(function()r:SetCoreGuiEnabled(x,true)end)end end)end end function u.Destroy(n)n._maid:DoCleaning()end return u


local require = require(script.Parent.loader).load(script)

local Workspace = game:GetService("Workspace")
local UserInputService = game:GetService("UserInputService")
local StarterGui = game:GetService("StarterGui")
local TeleportService = game:GetService("TeleportService")

local AttributeValue = require("AttributeValue")
local Maid = require("Maid")
local PlayerGuiUtils = require("PlayerGuiUtils")
local Rx = require("Rx")
local SoftShutdownConstants = require("SoftShutdownConstants")
local SoftShutdownTranslator = require("SoftShutdownTranslator")
local SoftShutdownUI = require("SoftShutdownUI")
local RxValueBaseUtils = require("RxValueBaseUtils")

local SoftShutdownServiceClient = {}

local DISABLE_CORE_GUI_TYPES = {
	Enum.CoreGuiType.PlayerList;
	Enum.CoreGuiType.Health;
	Enum.CoreGuiType.Backpack;
	Enum.CoreGuiType.Chat;
	Enum.CoreGuiType.EmotesMenu;
	Enum.CoreGuiType.All;
}

function SoftShutdownServiceClient:Init(serviceBag)
	assert(not self._serviceBag, "Already initialized")
	self._serviceBag = assert(serviceBag, "No serviceBag")

	self._maid = Maid.new()
	self._translator = self._serviceBag:GetService(SoftShutdownTranslator)

	self._isLobby = AttributeValue.new(Workspace, SoftShutdownConstants.IS_SOFT_SHUTDOWN_LOBBY_ATTRIBUTE, false)
	self._isUpdating = AttributeValue.new(Workspace, SoftShutdownConstants.IS_SOFT_SHUTDOWN_UPDATING_ATTRIBUTE, false)

	self._localTeleportDataSaysIsLobby = Instance.new("BoolValue")
	self._localTeleportDataSaysIsLobby.Value = false
	self._maid:GiveTask(self._localTeleportDataSaysIsLobby)

	self._isArrivingAfterShutdown = Instance.new("BoolValue")
	self._isArrivingAfterShutdown.Value = false
	self._maid:GiveTask(self._isArrivingAfterShutdown)

	task.spawn(function()
		if self:_queryLocalTeleportInfo() then
			self._localTeleportDataSaysIsLobby.Value = true
		end
		if self:_queryIsArrivingAfterShutdown() then
			self._isArrivingAfterShutdown.Value = true;
		end
	end)

	self._maid:GiveTask(Rx.combineLatest({
		isLobby = self._isLobby:Observe();
		isShuttingDown = self._isUpdating:Observe();
		localTeleportDataSaysIsLobby = RxValueBaseUtils.observeValue(self._localTeleportDataSaysIsLobby);
		isArrivingAfterShutdown = RxValueBaseUtils.observeValue(self._isArrivingAfterShutdown);
	}):Subscribe(function(state)
		if state.isLobby or state.localTeleportDataSaysIsLobby then
			self._maid._shutdownUI = nil
			if not self._maid._lobbyUI then
				local screenGui
				self._maid._lobbyUI, screenGui = self:_showSoftShutdownUI("shutdown.lobby.title", "shutdown.lobby.subtitle", true)

				TeleportService:SetTeleportGui(screenGui)
			end
		elseif state.isShuttingDown then
			local screenGui
			self._maid._shutdownUI, screenGui = self:_showSoftShutdownUI("shutdown.restart.title", "shutdown.restart.subtitle")

			TeleportService:SetTeleportGui(screenGui)

			self._maid._lobbyUI = nil
		elseif state.isArrivingAfterShutdown then
			-- Construct
			local maid = self:_showSoftShutdownUI("shutdown.complete.title", "shutdown.complete.subtitle", true)
			self._maid._shutdownUI = maid
			self._maid._lobbyUI = nil

			-- Defer
			task.delay(1, function()
				if self._maid._shutdownUI == maid then
					self._maid._shutdownUI = nil
				end
			end)
		else
			self._maid._shutdownUI = nil
			self._maid._lobbyUI = nil
		end
	end))
end

function SoftShutdownServiceClient:_queryIsArrivingAfterShutdown()
	local data = TeleportService:GetLocalPlayerTeleportData()
	if type(data) == "table" and data.isSoftShutdownArrivingIntoUpdatedServer then
		return true
	else
		return false
	end
end

function SoftShutdownServiceClient:_queryLocalTeleportInfo()
	local data = TeleportService:GetLocalPlayerTeleportData()
	if type(data) == "table" and data.isSoftShutdownReserveServer then
		return true
	else
		return false
	end
end

function SoftShutdownServiceClient:_showSoftShutdownUI(titleKey, subtitleKey, doNotAnimateShow)
	local maid = Maid.new()

	local renderMaid = Maid.new()

	local screenGui = Instance.new("ScreenGui")
	screenGui.Name = "SoftShutdownScreenGui"
	screenGui.ResetOnSpawn = false
	screenGui.AutoLocalize = false
	screenGui.IgnoreGuiInset = true
	screenGui.DisplayOrder = 1e10
	screenGui.Parent = PlayerGuiUtils.getPlayerGui()
	screenGui.ZIndexBehavior = Enum.ZIndexBehavior.Sibling
	renderMaid:GiveTask(screenGui)

	local softShutdownUI = SoftShutdownUI.new()
	renderMaid:GiveTask(softShutdownUI)

	maid:GiveTask(function()
		softShutdownUI:Hide()

		task.delay(1, function()
			renderMaid:Destroy()
		end)
	end)

	self:_hideCoreGuiUI(renderMaid, screenGui)

	maid:GivePromise(self._translator:PromiseFormatByKey(subtitleKey)):Then(function(subtitle)
		softShutdownUI:SetSubtitle(subtitle)
	end)

	maid:GivePromise(self._translator:PromiseFormatByKey(titleKey)):Then(function(title)
		softShutdownUI:SetTitle(title)
	end)

	softShutdownUI:Show(doNotAnimateShow)

	softShutdownUI.Gui.Parent = screenGui

	return maid, screenGui
end

function SoftShutdownServiceClient:_hideCoreGuiUI(maid, ignoreScreenGui)
	-- Hide all other ui
	if not UserInputService.ModalEnabled then
		UserInputService.ModalEnabled = true
		maid:GiveTask(function()
			UserInputService.ModalEnabled = false
		end)
	end

	local playerGui = PlayerGuiUtils.getPlayerGui()

	local enabledScreenGuis = {}

	local function handleChild(child)
		if child:IsA("ScreenGui") and child ~= ignoreScreenGui and child.Enabled then
			enabledScreenGuis[child] = child
			child.Enabled = false
		end
	end

	for _, child in pairs(playerGui:GetChildren()) do
		handleChild(child)
	end

	maid:GiveTask(playerGui.ChildAdded:Connect(function(child)
		handleChild(child)
	end))

	maid:GiveTask(playerGui.ChildRemoved:Connect(function(child)
		enabledScreenGuis[child] = nil
	end))

	maid:GiveTask(function()
		for screenGui, _ in pairs(enabledScreenGuis) do
			screenGui.Enabled = true
		end
	end)

	for _, coreGuiType in pairs(DISABLE_CORE_GUI_TYPES) do
		task.spawn(function()
			if StarterGui:GetCoreGuiEnabled(coreGuiType) then
				StarterGui:SetCoreGuiEnabled(coreGuiType, false)

				maid:GiveTask(function()
					StarterGui:SetCoreGuiEnabled(coreGuiType, true)
				end)
			end
		end)
	end
end

function SoftShutdownServiceClient:Destroy()
	self._maid:DoCleaning()
end

return SoftShutdownServiceClient
