--[[
				// ControllerStateManager.lua

				// Handles controller state changes
]]
local CoreGui = Game:GetService("CoreGui")
local GuiRoot = CoreGui:FindFirstChild("RobloxGui")
local Modules = GuiRoot:FindFirstChild("Modules")
local PlatformService = game:GetService('PlatformService')
local UserInputService = game:GetService('UserInputService')

local EventHub = require(Modules:FindFirstChild('EventHub'))
local NoActionOverlay = require(Modules:FindFirstChild('NoActionOverlay'))
local ScreenManager = require(Modules:FindFirstChild('ScreenManager'))
local Strings = require(Modules:FindFirstChild('LocalizedStrings'))
local UserData = require(Modules:FindFirstChild('UserData'))
local Utility = require(Modules:FindFirstChild('Utility'))

local ControllerStateManager = {}

local LostUserGamepadCn = nil
local LostActiveUserCn = nil
local GainedUserGamepadCn = nil
local GainedActiveUserCn = nil
local DisconnectCn = nil

local currentOverlay = nil

local DATAMODEL_TYPE = {
	APP_SHELL = 0;
	GAME = 1;
}

local function closeOverlay(dataModelType)
	if dataModelType == DATAMODEL_TYPE.GAME then
		UserInputService.OverrideMouseIconEnabled = false
		UserInputService.OverrideMouseIconBehavior = Enum.OverrideMouseIconBehavior.None

		currentOverlay:Hide()
		currentOverlay = nil
	else
		ScreenManager:CloseCurrent()
	end
end

local function showErrorOverlay(titleName, bodyName, userDisplayName, dataModelType)
	-- create error
	local err = { Title = Strings:LocalizedString(titleName),
		Msg = string.format(Strings:LocalizedString(bodyName), userDisplayName) }
	local noActionOverlay = NoActionOverlay(err)
	if dataModelType == DATAMODEL_TYPE.GAME then
		UserInputService.OverrideMouseIconEnabled = true
		UserInputService.OverrideMouseIconBehavior = Enum.OverrideMouseIconBehavior.ForceHide

		currentOverlay = noActionOverlay
		noActionOverlay:Show()
	else
		ScreenManager:OpenScreen(noActionOverlay, false)
	end
end

local function onLostActiveUser(userDisplayName, dataModelType)
	showErrorOverlay("ActiveUserLostConnectionTitle", "ActiveUserLostConnectionPhrase", userDisplayName, dataModelType)
end

local function onGainedActiveUser(dataModelType)
	closeOverlay(dataModelType)
end

local function onLostUserGamepad(userDisplayName, dataModelType)
	showErrorOverlay("ControllerLostConnectionTitle", "ControllerLostConnectionPhrase", userDisplayName, dataModelType)
end

local function onGainedUserGamepad(dataModelType)
	closeOverlay(dataModelType)
end

local function disconnectEvents()
	LostActiveUserCn = Utility.DisconnectEvent(LostActiveUserCn)
	GainedActiveUserCn = Utility.DisconnectEvent(GainedActiveUserCn)

	LostUserGamepadCn = Utility.DisconnectEvent(LostUserGamepadCn)
	GainedUserGamepadCn = Utility.DisconnectEvent(GainedUserGamepadCn)
end

function ControllerStateManager:Initialize()
	local dataModelType = PlatformService.DatamodelType

	disconnectEvents()
	LostUserGamepadCn = PlatformService.LostUserGamepad:connect(function(userDisplayName)
		onLostUserGamepad(userDisplayName, dataModelType)
	end)
	GainedUserGamepadCn = PlatformService.GainedUserGamepad:connect(function(userDisplayName)
		onGainedUserGamepad(dataModelType)
	end)

	LostActiveUserCn = PlatformService.LostActiveUser:connect(function(userDisplayName)
		onLostActiveUser(userDisplayName, dataModelType)
	end)
	GainedActiveUserCn = PlatformService.GainedActiveUser:connect(function(userDisplayName)
		onGainedActiveUser(dataModelType)
	end)

	-- disconnect based on DataModel type
	if dataModelType == DATAMODEL_TYPE.GAME then
		DisconnectCn = PlatformService.ViewChanged:connect(function(viewType)
			if viewType == 0 then
				disconnectEvents()
			end
		end)
	else
		DisconnectCn = PlatformService.UserAccountChanged:connect(function(reauthenticationReason)
			disconnectEvents()
		end)
	end
end

function ControllerStateManager:CheckUserConnected()
	local isGamepadConnected = UserInputService:GetGamepadConnected(Enum.UserInputType.Gamepad1)
	local dataModelType = PlatformService.DatamodelType
	if not isGamepadConnected then
		local userInfo = PlatformService:GetPlatformUserInfo()
		local userDisplayName = userInfo["Gamertag"] or ""
		onLostUserGamepad(userDisplayName, dataModelType)
	end
end

return ControllerStateManager
