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

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
