local GamepadUIManager = {}
local InputManager = CS.InputManager
local ClientManager = CS.ClientManager.Instance
local sRootPath = Settings.AB_ROOT_PATH
local nCurUIType = AllEnum.GamepadUIType.Other
local sCurUIName
local tbHistory = {}
local mapGamepadUI = {}
local mapMouseConfig = {}
local bEnableInput = false
local bBlockUI = false
local bFirstInputEnable = false
local SetGamepadIcon = function(img, sAction)
	local sIcon
	if nCurUIType == AllEnum.GamepadUIType.PS then
		sIcon = ConfigTable.GetField("GamepadAction", sAction, "PlayStationIcon")
	elseif nCurUIType == AllEnum.GamepadUIType.Xbox then
		sIcon = ConfigTable.GetField("GamepadAction", sAction, "XboxIcon")
	elseif nCurUIType == AllEnum.GamepadUIType.Keyboard or nCurUIType == AllEnum.GamepadUIType.Mouse then
		sIcon = ConfigTable.GetField("GamepadAction", sAction, "KeyboardIcon")
	end
	if sIcon == "" then
		img.gameObject:SetActive(false)
		return
	end
	img.gameObject:SetActive(true)
	sIcon = sRootPath .. sIcon .. ".png"
	NovaAPI.SetImageSprite(img, sIcon)
	NovaAPI.SetImageNativeSize(img)
end
local RefreshCurTypeUINode = function(v)
	if not v.sAction then
		return
	end
	if v.sComponentName == "NaviButton" then
		if v.mapNode:IsNull() then
			return
		end
		local trRoot = v.mapNode.gameObject:GetComponent("Transform"):Find("AnimRoot")
		if trRoot then
			local Other = trRoot:Find("Other")
			if not Other then
				return
			end
			local General = trRoot:Find("General")
			local Xbox = trRoot:Find("Xbox")
			local PS = trRoot:Find("PS")
			local Keyboard = trRoot:Find("Keyboard")
			if General then
				if Xbox then
					Xbox.gameObject:SetActive(false)
				end
				if PS then
					PS.gameObject:SetActive(false)
				end
				if Keyboard then
					Keyboard.gameObject:SetActive(false)
				end
				General.gameObject:SetActive(nCurUIType ~= AllEnum.GamepadUIType.Other)
				Other.gameObject:SetActive(nCurUIType == AllEnum.GamepadUIType.Other)
				if nCurUIType ~= AllEnum.GamepadUIType.Other then
					local icon = General:Find("imgAction")
					if icon then
						SetGamepadIcon(icon:GetComponent("Image"), v.sAction)
					end
				end
			elseif not General and Xbox and PS and Keyboard then
				Xbox.gameObject:SetActive(nCurUIType == AllEnum.GamepadUIType.Xbox)
				PS.gameObject:SetActive(nCurUIType == AllEnum.GamepadUIType.PS)
				Keyboard.gameObject:SetActive(nCurUIType == AllEnum.GamepadUIType.Keyboard or nCurUIType == AllEnum.GamepadUIType.Mouse)
				Other.gameObject:SetActive(nCurUIType == AllEnum.GamepadUIType.Other)
				local icon
				if nCurUIType == AllEnum.GamepadUIType.Xbox then
					icon = Xbox:Find("imgAction")
				elseif nCurUIType == AllEnum.GamepadUIType.PS then
					icon = PS:Find("imgAction")
				elseif nCurUIType == AllEnum.GamepadUIType.Keyboard or nCurUIType == AllEnum.GamepadUIType.Mouse then
					icon = Keyboard:Find("imgAction")
				end
				if icon then
					SetGamepadIcon(icon:GetComponent("Image"), v.sAction)
				end
			end
		end
	elseif v.sComponentName == "GamepadScroll" then
		if v.mapNode:IsNull() then
			return
		end
		local trRoot = v.mapNode.gameObject:GetComponent("Transform"):Find("Scrollbar")
		if trRoot then
			local icon = trRoot:Find("imgAction")
			if icon then
				icon.gameObject:SetActive(nCurUIType ~= AllEnum.GamepadUIType.Other)
				if nCurUIType ~= AllEnum.GamepadUIType.Other then
					SetGamepadIcon(icon:GetComponent("Image"), v.sAction)
				end
			end
		end
	end
end
local RefreshCurTypeUI = function()
	if not sCurUIName then
		return
	end
	local tbNode = mapGamepadUI[sCurUIName]
	if (tbNode == nil or next(tbNode) == nil) and mapMouseConfig[sCurUIName] == nil then
		printWarn("GamepadUIManager：当前UI内节点刷新失败，可能该UI从来没有打开过：" .. sCurUIName)
		return
	end
	for _, v in pairs(tbNode) do
		RefreshCurTypeUINode(v)
	end
end
local ChangeUIType = function(nAfterType)
	if nAfterType == nCurUIType then
		return
	end
	local nBeforeType = nCurUIType
	nCurUIType = nAfterType
	EventManager.Hit("GamepadUIChange", sCurUIName, nBeforeType, nAfterType)
	RefreshCurTypeUI()
end
local GetUITypeByGamepad = function()
	local nType = InputManager.Instance:CheckGamepadType()
	local nAfterType = AllEnum.GamepadUIType.Other
	if nType == InputManager.GamepadType.PS then
		nAfterType = AllEnum.GamepadUIType.PS
	elseif nType == InputManager.GamepadType.XBox or nType == InputManager.GamepadType.Switch or nType == InputManager.GamepadType.Other then
		nAfterType = AllEnum.GamepadUIType.Xbox
	elseif nType == InputManager.GamepadType.None then
		nAfterType = AllEnum.GamepadUIType.Other
	end
	return nAfterType
end
local OnEvent_LastInputDeviceChange = function(_, nType)
	local bMobile = NovaAPI.IsMobilePlatform()
	local bTable = ClientManager.isTabletDevice
	local nAfterType = AllEnum.GamepadUIType.Other
	if nType == InputManager.InputDeviceType.PSGamepad then
		nAfterType = AllEnum.GamepadUIType.PS
	elseif nType == InputManager.InputDeviceType.XBoxGamepad then
		nAfterType = AllEnum.GamepadUIType.Xbox
	elseif nType == InputManager.InputDeviceType.Keyboard and (not bMobile or bTable) then
		nAfterType = AllEnum.GamepadUIType.Keyboard
	elseif nType == InputManager.InputDeviceType.Mouse and (not bMobile or bTable) then
		nAfterType = AllEnum.GamepadUIType.Mouse
	elseif nType == InputManager.InputDeviceType.Other then
		nAfterType = GetUITypeByGamepad()
	elseif nType == InputManager.InputDeviceType.None then
		nAfterType = AllEnum.GamepadUIType.Other
	end
	ChangeUIType(nAfterType)
end
local GetUITypeByInputDevice = function()
	local bMobile = NovaAPI.IsMobilePlatform()
	local nType = InputManager.Instance:CheckInputDeviceType()
	local nAfterType = AllEnum.GamepadUIType.Other
	if nType == InputManager.InputDeviceType.PSGamepad then
		nAfterType = AllEnum.GamepadUIType.PS
	elseif nType == InputManager.InputDeviceType.XBoxGamepad then
		nAfterType = AllEnum.GamepadUIType.Xbox
	elseif nType == InputManager.InputDeviceType.Keyboard and not bMobile then
		nAfterType = AllEnum.GamepadUIType.Keyboard
	elseif nType == InputManager.InputDeviceType.Mouse and not bMobile then
		nAfterType = AllEnum.GamepadUIType.Mouse
	elseif nType == InputManager.InputDeviceType.Other then
		nAfterType = GetUITypeByGamepad()
	elseif nType == InputManager.InputDeviceType.None then
		nAfterType = AllEnum.GamepadUIType.Other
	end
	return nAfterType
end
local OnEvent_OnDeviceChange = function(_, changeType)
	if changeType.value__ == 0 or changeType.value__ == 1 then
		local nAfterType = GetUITypeByInputDevice()
		ChangeUIType(nAfterType)
	end
end
local OnEvent_BlockGamepadUI = function(_, bBlock)
	bBlockUI = bBlock
	if not sCurUIName then
		return
	end
	local tbNode = mapGamepadUI[sCurUIName]
	if tbNode == nil or next(tbNode) == nil then
		return
	end
	for _, v in pairs(tbNode) do
		if v.mapNode:IsNull() == false then
			if bFirstInputEnable then
				NovaAPI.SetComponentEnable(v.mapNode, not bBlock)
			else
				NovaAPI.SetComponentEnable(v.mapNode, false)
			end
		else
			printWarn("GamepadUIManager：当前UI实例已销毁，无需屏蔽：" .. sCurUIName)
			return
		end
	end
end
local EnableNode = function(sCtrlName)
	if not sCtrlName then
		printWarn("GamepadUIManager：当前UI内节点打开失败，CtrlName为空")
		return
	end
	if NovaAPI.IsEditorPlatform() then
		printLog("GamepadUIManager：Enable UI " .. sCtrlName)
	end
	local tbNode = mapGamepadUI[sCtrlName]
	if (tbNode == nil or next(tbNode) == nil) and mapMouseConfig[sCurUIName] == nil then
		printWarn("GamepadUIManager：当前UI内节点打开失败，可能该UI从来没有打开过：" .. sCtrlName)
		return
	end
	for _, v in pairs(tbNode) do
		if v.mapNode:IsNull() then
			printError("GamepadUIManager：当前UI内节点打开失败，UI实例已销毁：" .. sCtrlName)
			return
		end
		if not bBlockUI and bFirstInputEnable then
			if v.mapNode.enabled == true then
				NovaAPI.SetComponentEnable(v.mapNode, false)
			end
			NovaAPI.SetComponentEnable(v.mapNode, true)
		else
			NovaAPI.SetComponentEnable(v.mapNode, false)
		end
	end
end
local DisableNode = function(sCtrlName)
	if not sCtrlName then
		printWarn("GamepadUIManager：当前UI内节点关闭失败，CtrlName为空")
		return
	end
	if NovaAPI.IsEditorPlatform() then
		printLog("GamepadUIManager：Disable UI " .. sCtrlName)
	end
	local tbNode = mapGamepadUI[sCtrlName]
	if (tbNode == nil or next(tbNode) == nil) and mapMouseConfig[sCurUIName] == nil then
		printWarn("GamepadUIManager：当前UI内节点关闭失败，可能该UI从来没有打开过：" .. sCtrlName)
		return
	end
	for _, v in pairs(tbNode) do
		if v.mapNode:IsNull() then
			printError("GamepadUIManager：当前UI内节点关闭失败，UI实例已销毁：" .. sCtrlName)
			return
		end
		NovaAPI.SetComponentEnable(v.mapNode, false)
	end
end
local OnEvent_FirstInputEnable = function()
	bFirstInputEnable = true
	if sCurUIName then
		EnableNode(sCurUIName)
	end
end
local OnEvent_OpenBuiltinAlert = function(_, bOpen, _okBtn, _confirmBtn, _cancelBtn)
	if not bEnableInput then
		NovaAPI.SetNaviButtonAction(_okBtn, false)
		NovaAPI.SetNaviButtonAction(_confirmBtn, false)
		NovaAPI.SetNaviButtonAction(_cancelBtn, false)
		return
	end
	if bOpen then
		local tbGamepadUINode = {
			[1] = {
				mapNode = _okBtn,
				sComponentName = "NaviButton",
				sAction = "buttonSouth"
			},
			[2] = {
				mapNode = _confirmBtn,
				sComponentName = "NaviButton",
				sAction = "buttonSouth"
			},
			[3] = {
				mapNode = _cancelBtn,
				sComponentName = "NaviButton",
				sAction = "buttonEast"
			}
		}
		GamepadUIManager.EnableGamepadUI("BuiltinUI", tbGamepadUINode)
		NovaAPI.SetNaviButtonAction(_okBtn, true)
		NovaAPI.SetNaviButtonAction(_confirmBtn, true)
		NovaAPI.SetNaviButtonAction(_cancelBtn, true)
	else
		GamepadUIManager.DisableGamepadUI("BuiltinUI")
	end
end
local function Uninit(_)
	EventManager.Remove("LuaEventName_OnDeviceChange", GamepadUIManager, OnEvent_OnDeviceChange)
	EventManager.Remove("LuaEventName_LastInputDeviceChange", GamepadUIManager, OnEvent_LastInputDeviceChange)
	EventManager.Remove("__BlockGamepadUI", GamepadUIManager, OnEvent_BlockGamepadUI)
	EventManager.Remove("FirstInputEnable", GamepadUIManager, OnEvent_FirstInputEnable)
	EventManager.Remove("__OpenBuiltinAlert", GamepadUIManager, OnEvent_OpenBuiltinAlert)
	EventManager.Remove(EventId.CSLuaManagerShutdown, GamepadUIManager, Uninit)
end
function GamepadUIManager.Init()
	nCurUIType = GetUITypeByInputDevice()
	EventManager.Add("LuaEventName_OnDeviceChange", GamepadUIManager, OnEvent_OnDeviceChange)
	EventManager.Add("LuaEventName_LastInputDeviceChange", GamepadUIManager, OnEvent_LastInputDeviceChange)
	EventManager.Add("__BlockGamepadUI", GamepadUIManager, OnEvent_BlockGamepadUI)
	EventManager.Add("FirstInputEnable", GamepadUIManager, OnEvent_FirstInputEnable)
	EventManager.Add("__OpenBuiltinAlert", GamepadUIManager, OnEvent_OpenBuiltinAlert)
	EventManager.Add(EventId.CSLuaManagerShutdown, GamepadUIManager, Uninit)
end
function GamepadUIManager.EnableGamepadUI(sCtrlName, tbNode, goDefaultSelected, bEnableVirtualMouse, bBlockCursor)
	if sCurUIName == sCtrlName then
		printWarn("GamepadUIManager：重复打开Gamepad UI：" .. sCtrlName)
		return
	end
	NovaAPI.ClearSelectedUI()
	if goDefaultSelected then
		NovaAPI.SetSelectedUI(goDefaultSelected)
	end
	InputManager.Instance.IsVirtualMouseEnabled = bEnableVirtualMouse == true
	InputManager.Instance.IsBlockCursor = bBlockCursor == true
	local bSwitch = false
	if sCurUIName then
		DisableNode(sCurUIName)
		bSwitch = true
	end
	sCurUIName = sCtrlName
	mapGamepadUI[sCurUIName] = clone(tbNode)
	if not mapMouseConfig[sCurUIName] then
		mapMouseConfig[sCurUIName] = {}
	end
	mapMouseConfig[sCurUIName].VirtualMouse = bEnableVirtualMouse == true
	mapMouseConfig[sCurUIName].BlockCursor = bBlockCursor == true
	table.insert(tbHistory, sCurUIName)
	RefreshCurTypeUI()
	if bSwitch then
		local wait = function()
			coroutine.yield(CS.UnityEngine.WaitForEndOfFrame())
			EnableNode(sCurUIName)
		end
		cs_coroutine.start(wait)
	else
		EnableNode(sCurUIName)
	end
end
function GamepadUIManager.DisableGamepadUI(sCtrlName)
	local nIndex = table.indexof(tbHistory, sCtrlName)
	if nIndex == 0 then
		return
	end
	if sCurUIName == sCtrlName then
		DisableNode(sCtrlName)
		mapGamepadUI[sCtrlName] = nil
		mapMouseConfig[sCtrlName] = nil
		table.remove(tbHistory, nIndex)
		sCurUIName = nil
		if next(tbHistory) ~= nil then
			sCurUIName = tbHistory[#tbHistory]
			InputManager.Instance.IsVirtualMouseEnabled = mapMouseConfig[sCurUIName].VirtualMouse
			InputManager.Instance.IsBlockCursor = mapMouseConfig[sCurUIName].BlockCursor
			RefreshCurTypeUI()
			local wait = function()
				coroutine.yield(CS.UnityEngine.WaitForEndOfFrame())
				if sCurUIName then
					EnableNode(sCurUIName)
					EventManager.Hit("GamepadUIReopen", sCurUIName)
				else
					printWarn("GamepadUIManager：关闭历史未找到对应ctrl")
				end
			end
			cs_coroutine.start(wait)
		end
	else
		mapGamepadUI[sCtrlName] = nil
		mapMouseConfig[sCtrlName] = nil
		table.remove(tbHistory, nIndex)
	end
end
function GamepadUIManager.AddGamepadUINode(sCtrlName, tbNode)
	if not mapGamepadUI or not mapGamepadUI[sCtrlName] then
		printWarn("GamepadUIManager：当前ui不存在，添加节点失败Gamepad UI：" .. sCtrlName)
		return
	end
	for _, v in pairs(tbNode) do
		table.insert(mapGamepadUI[sCtrlName], v)
	end
	if sCurUIName == sCtrlName then
		EnableNode(sCtrlName)
		for _, v in pairs(tbNode) do
			RefreshCurTypeUINode(v)
		end
	else
		DisableNode(sCtrlName)
	end
end
function GamepadUIManager.SetSelectedUI(goSelected)
	NovaAPI.SetSelectedUI(goSelected)
end
function GamepadUIManager.ClearSelectedUI()
	NovaAPI.ClearSelectedUI()
end
function GamepadUIManager.SetNavigation(tbUIObj, bHorizontal, bLoop)
	if bHorizontal == nil then
		bHorizontal = true
	end
	if bLoop == nil then
		bLoop = true
	end
	NovaAPI.SetGamepadUINavigation(tbUIObj, bHorizontal, bLoop)
end
function GamepadUIManager.GetCurUIType()
	return nCurUIType
end
function GamepadUIManager.GetCurUIName()
	return sCurUIName
end
function GamepadUIManager.GetInputState()
	return bEnableInput
end
function GamepadUIManager.GetPrveUIName()
	if next(tbHistory) == nil then
		return
	end
	local nCount = #tbHistory
	if 1 < nCount then
		return tbHistory[nCount - 1]
	end
end
function GamepadUIManager.EnterAdventure(bSkipFirstInputEnable)
	InputManager.Instance.IsVirtualMouseEnabled = false
	InputManager.Instance.IsBlockCursor = false
	InputManager.Instance.IsBattleSubmit = true
	sCurUIName = nil
	tbHistory = {}
	mapGamepadUI = {}
	mapMouseConfig = {}
	bEnableInput = true
	bFirstInputEnable = bSkipFirstInputEnable
end
function GamepadUIManager.QuitAdventure()
	InputManager.Instance.IsVirtualMouseEnabled = true
	InputManager.Instance.IsBlockCursor = false
	InputManager.Instance.IsBattleSubmit = false
	sCurUIName = nil
	tbHistory = {}
	mapGamepadUI = {}
	mapMouseConfig = {}
	bEnableInput = false
	bFirstInputEnable = false
end
function GamepadUIManager.GetInputName(mapInput)
	if not mapInput.name or not mapInput.displayName then
		return
	end
	local sName = mapInput.displayName
	if string.find(mapInput.name, "left") then
		sName = string.gsub(mapInput.name, "left", "L-")
	elseif string.find(mapInput.name, "right") then
		sName = string.gsub(mapInput.name, "right", "R-")
	elseif sName == "Num Del" then
		sName = "Num."
	elseif string.find(mapInput.name, "numpad") then
		local position = string.find(sName, " ")
		if position then
			sName = "Num" .. string.sub(sName, position + 1)
		else
			sName = "Num" .. sName
		end
	end
	return sName
end
return GamepadUIManager
