local FixedRoguelikeRewardGachaCtrl = class("FixedRoguelikeRewardGachaCtrl", BaseCtrl)
local GameResourceLoader = require("Game.Common.Resource.GameResourceLoader")
local ResType = GameResourceLoader.ResType
local WwiseAudioMgr = CS.WwiseAudioManager.Instance
FixedRoguelikeRewardGachaCtrl._mapNodeConfig = {
	uieffectBg = {sComponentName = "GameObject"},
	goGacha = {sComponentName = "GameObject"},
	btnClose = {
		sComponentName = "Button",
		callback = "OnBtnClick_Close"
	},
	rtContent = {
		sComponentName = "RectTransform"
	},
	ItemRoot = {
		sComponentName = "RectTransform"
	}
}
FixedRoguelikeRewardGachaCtrl._mapEventConfig = {}
local HULF_PAGE = 6
local FULL_PAGE = 12
local FALLIN_TIME = 0.03
local LINE_SPACE_TIME = 0.1
local OPEN_R_TIME = 0.2
local OPEN_SSR_TIME = 1
local FALLIN_ALL_TIME = 0.5
local RewardGachaIconType = {
	A = "a",
	B = "b",
	C = "c",
	D = "d"
}
function FixedRoguelikeRewardGachaCtrl:ProcessResult(mapResult)
	local tbRarityItem = self:ReallocateRarity(mapResult.tbItem)
	local tbRarityPresents = self:ReallocateRarity(mapResult.tbPresents)
	local tbRarityOutfit = self:ReallocateRarity(mapResult.tbOutfit)
	local tbRarityGacha = mapResult.tbRarityCount
	local tbAllRarity = {}
	for nRarity, _ in pairs(tbRarityGacha) do
		table.insert(tbAllRarity, nRarity)
	end
	table.sort(tbAllRarity, function(a, b)
		return a < b
	end)
	local nAllRarity = #tbAllRarity
	for j = 1, nAllRarity - 1 do
		local nRarity = tbAllRarity[j]
		local nItem = 0
		for _, mapItem in pairs(tbRarityItem[nRarity]) do
			nItem = nItem + mapItem.nCount
		end
		local nPresents = #tbRarityPresents[nRarity]
		local nOutfit = #tbRarityOutfit[nRarity]
		local nNeed = tbRarityGacha[nRarity] - nItem - nPresents - nOutfit
		nNeed = 0 < nNeed and nNeed or 0
		if tbRarityItem[nRarity + 1] and #tbRarityItem[nRarity + 1] > 0 and 0 < nNeed then
			local nCount = #tbRarityItem[nRarity + 1]
			for i = nCount, 1, -1 do
				if nNeed <= 0 then
					break
				end
				local mapItem = tbRarityItem[nRarity + 1][i]
				if nNeed < mapItem.nCount then
					table.insert(tbRarityItem[nRarity], {
						nTid = mapItem.nTid,
						nCount = nNeed
					})
					mapItem.nCount = mapItem.nCount - nNeed
					nNeed = 0
				else
					table.insert(tbRarityItem[nRarity], mapItem)
					table.remove(tbRarityItem[nRarity + 1], i)
					nNeed = nNeed - mapItem.nCount
				end
			end
		end
		if tbRarityPresents[nRarity + 1] and #tbRarityPresents[nRarity + 1] > 0 and 0 < nNeed then
			local nCount = #tbRarityPresents[nRarity + 1]
			for i = nCount, 1, -1 do
				if nNeed <= 0 then
					break
				end
				local mapItem = tbRarityPresents[nRarity + 1][i]
				table.insert(tbRarityPresents[nRarity], mapItem)
				table.remove(tbRarityPresents[nRarity + 1], i)
				nNeed = nNeed - 1
			end
		end
		if tbRarityOutfit[nRarity + 1] and #tbRarityOutfit[nRarity + 1] > 0 and 0 < nNeed then
			local nCount = #tbRarityOutfit[nRarity + 1]
			for i = nCount, 1, -1 do
				if nNeed <= 0 then
					break
				end
				local mapItem = tbRarityOutfit[nRarity + 1][i]
				table.insert(tbRarityOutfit[nRarity], mapItem)
				table.remove(tbRarityOutfit[nRarity + 1], i)
				nNeed = nNeed - 1
			end
		end
	end
	local tbRarityReward = {}
	local tbPresentsToNext = {}
	local tbOutfitToNext = {}
	local tbItemToNext = {}
	for i = 5, 1, -1 do
		local nRarity = i
		if not tbRarityGacha[nRarity] then
			local add_next = function(tbItem, tbNext)
				if not tbItem then
					return
				end
				for _, mapItem in pairs(tbItem) do
					table.insert(tbNext, mapItem)
				end
			end
			add_next(tbRarityPresents[nRarity], tbPresentsToNext)
			add_next(tbRarityOutfit[nRarity], tbOutfitToNext)
			add_next(tbRarityItem[nRarity], tbItemToNext)
		else
			tbRarityReward[nRarity] = {}
			do
				local nItem = #tbRarityItem[nRarity]
				local nPresents = #tbRarityPresents[nRarity]
				local nOutfit = #tbRarityOutfit[nRarity]
				local nHas = nItem + nPresents + nOutfit + #tbPresentsToNext + #tbOutfitToNext + #tbItemToNext
				local bFull = nHas >= tbRarityGacha[nRarity]
				local add_previous = function(tbNext)
					for _, mapItem in pairs(tbNext) do
						table.insert(tbRarityReward[nRarity], mapItem)
						tbRarityGacha[nRarity] = tbRarityGacha[nRarity] - 1
					end
				end
				add_previous(tbPresentsToNext)
				tbPresentsToNext = {}
				add_previous(tbOutfitToNext)
				tbOutfitToNext = {}
				if bFull then
					add_previous(tbItemToNext)
				else
					for _, mapItem in pairs(tbItemToNext) do
						table.insert(tbRarityItem[nRarity], mapItem)
					end
				end
				tbItemToNext = {}
				local bClear = false
				local add_cur = function(tbItem, tbNext)
					for _, mapItem in pairs(tbItem) do
						if 0 < tbRarityGacha[nRarity] then
							table.insert(tbRarityReward[nRarity], mapItem)
							tbRarityGacha[nRarity] = tbRarityGacha[nRarity] - 1
						else
							bClear = true
						end
						if bClear then
							table.insert(tbNext, mapItem)
						end
					end
				end
				add_cur(tbRarityPresents[nRarity], tbPresentsToNext)
				add_cur(tbRarityOutfit[nRarity], tbOutfitToNext)
				if bFull then
					add_cur(tbRarityItem[nRarity], tbItemToNext)
				else
					do
						local tbAfter = self:ReallocateGacha(tbRarityItem[nRarity], tbRarityGacha[nRarity])
						for _, mapItem in pairs(tbAfter) do
							table.insert(tbRarityReward[nRarity], mapItem)
						end
					end
				end
			end
		end
	end
	local tbReward = {}
	for _, nRarity in pairs(tbAllRarity) do
		local tbRandom = self:RandomTable(tbRarityReward[nRarity])
		for _, mapItem in ipairs(tbRandom) do
			table.insert(tbReward, {
				nTid = mapItem.nTid,
				nCount = mapItem.nCount,
				nRarity = nRarity
			})
		end
	end
	return tbReward
end
function FixedRoguelikeRewardGachaCtrl:ReallocateRarity(tbItem)
	local tbRarity = {}
	for i = 1, 5 do
		if not tbRarity[i] then
			tbRarity[i] = {}
		end
	end
	for _, mapItem in pairs(tbItem) do
		local mapCfg = ConfigTable.GetData_Item(mapItem.nTid)
		local nRarity = mapCfg.Rarity
		table.insert(tbRarity[nRarity], mapItem)
	end
	return tbRarity
end
function FixedRoguelikeRewardGachaCtrl:ReallocateGacha(tbItem, nAllGachaCount)
	if nAllGachaCount == nil or nAllGachaCount == 0 then
		return {}
	end
	for _, mapItem in ipairs(tbItem) do
		mapItem.nRarity = ConfigTable.GetData_Item(mapItem.nTid).Rarity
	end
	local comp = function(a, b)
		if a.nRarity ~= b.nRarity then
			return a.nRarity < b.nRarity
		else
			return a.nTid > b.nTid
		end
	end
	table.sort(tbItem, comp)
	local tbAllocation = {}
	local nTypeCount = #tbItem
	local nRemainGacha = nAllGachaCount - nTypeCount
	for i = 1, nTypeCount do
		if not tbAllocation[i] then
			tbAllocation[i] = 0
		end
	end
	local bFail = false
	local nFailTimes = 0
	while 0 < nRemainGacha do
		if nFailTimes == 2 then
			nRemainGacha = 0
			printError("掉落扭蛋分配错误")
		end
		if bFail then
			nFailTimes = nFailTimes + 1
		end
		bFail = true
		for i = 1, nTypeCount do
			if tbItem[i].nCount > tbAllocation[i] + 1 and 0 < nRemainGacha then
				tbAllocation[i] = tbAllocation[i] + 1
				nRemainGacha = nRemainGacha - 1
				bFail = false
			end
		end
	end
	local tbAfter = {}
	for i = 1, nTypeCount do
		local nItemCount = tbItem[i].nCount
		local tbItemCount = {nItemCount}
		for _ = 1, tbAllocation[i] do
			table.sort(tbItemCount, function(a, b)
				return b < a
			end)
			local nMax = tbItemCount[1]
			local nAllocation = math.random(math.ceil(nMax / 4), math.floor(nMax / 2))
			tbItemCount[1] = nMax - nAllocation
			table.insert(tbItemCount, nAllocation)
		end
		for _, value in pairs(tbItemCount) do
			table.insert(tbAfter, {
				nTid = tbItem[i].nTid,
				nCount = value
			})
		end
	end
	return tbAfter
end
function FixedRoguelikeRewardGachaCtrl:RandomTable(tb)
	local tbRandom = {}
	local nCount = #tb
	while 0 < nCount do
		local nRandomIndex = math.random(1, nCount)
		local mapItem = tb[nRandomIndex]
		table.insert(tbRandom, mapItem)
		table.remove(tb, nRandomIndex)
		nCount = nCount - 1
	end
	return tbRandom
end
function FixedRoguelikeRewardGachaCtrl:ProcessListData(tbReward)
	self.tbRewardList = {}
	local nAllRewardCount = #tbReward
	local nFullListCount = math.floor(nAllRewardCount / FULL_PAGE)
	for _ = 1, nFullListCount do
		local tbSubReward = {}
		for _ = 1, FULL_PAGE do
			table.insert(tbSubReward, tbReward[1])
			table.remove(tbReward, 1)
		end
		table.insert(self.tbRewardList, tbSubReward)
	end
	table.insert(self.tbRewardList, tbReward)
end
function FixedRoguelikeRewardGachaCtrl:RefreshListItem(tbReward, bHulfPage)
	local bHasItem = true
	if self.tbGoItem == nil then
		self.tbGoItem = {}
		bHasItem = false
	end
	for key, v in ipairs(tbReward) do
		local nItemId = v.nTid
		local cfgDataItem = ConfigTable.GetData_Item(nItemId)
		local goItem
		if bHasItem then
			goItem = self.tbGoItem[key].go
		elseif bHulfPage then
			goItem = instantiate(self._mapNode.goGacha, self._mapNode.ItemRoot)
		else
			goItem = instantiate(self._mapNode.goGacha, self._mapNode.rtContent)
		end
		local tr = goItem.transform
		local imgFrame = tr:Find("goIcon/imgFrame"):GetComponent("Image")
		local imgIcon = tr:Find("goIcon/imgFrame/imgIcon"):GetComponent("Image")
		local imgFull = tr:Find("imgFull"):GetComponent("Image")
		local imgSplitB = tr:Find("goSplit/imgSplitB"):GetComponent("Image")
		local imgSplitC = tr:Find("goSplit/imgSplitB/imgSplitC"):GetComponent("Image")
		local imgSplitD = tr:Find("goSplit/imgSplitD"):GetComponent("Image")
		local txtCount = tr:Find("goIcon/imgFrame/ItemCount"):GetComponent("TMP_Text")
		self:SetAtlasSprite(imgFrame, "12_rare", AllEnum.FrameType_New.Item .. AllEnum.FrameColor_New[cfgDataItem.Rarity], true)
		if cfgDataItem.Type == GameEnum.itemType.Outfit or cfgDataItem.Type == GameEnum.itemType.Disc then
			self:SetPngSprite(imgIcon, cfgDataItem.Icon .. AllEnum.OutfitIconSurfix.Item)
		else
			self:SetPngSprite(imgIcon, cfgDataItem.Icon)
		end
		self:SetPngSprite(imgFull, "UI/big_sprites/" .. string.format(AllEnum.RewardGachaType[v.nRarity], RewardGachaIconType.A))
		self:SetPngSprite(imgSplitB, "UI/big_sprites/" .. string.format(AllEnum.RewardGachaType[v.nRarity], RewardGachaIconType.B))
		self:SetPngSprite(imgSplitC, "UI/big_sprites/" .. string.format(AllEnum.RewardGachaType[v.nRarity], RewardGachaIconType.C))
		self:SetPngSprite(imgSplitD, "UI/big_sprites/" .. string.format(AllEnum.RewardGachaType[v.nRarity], RewardGachaIconType.D))
		NovaAPI.SetTMPText(txtCount, v.nCount > 1 and "×" .. v.nCount or "")
		if not bHasItem then
			table.insert(self.tbGoItem, {
				go = goItem,
				bSSR = cfgDataItem.Rarity == GameEnum.itemRarity.SSR
			})
		else
			self.tbGoItem[key].bSSR = cfgDataItem.Rarity == GameEnum.itemRarity.SSR
		end
		NovaAPI.SetCanvasGroupAlpha(tr:GetComponent("CanvasGroup"), 0)
		goItem:SetActive(true)
	end
end
function FixedRoguelikeRewardGachaCtrl:PlayListAni(nPageCount, bLast, bOnePage, callback)
	local nLine = math.ceil(nPageCount / HULF_PAGE)
	local nLastLine = math.fmod(nPageCount, HULF_PAGE)
	if nLastLine == 0 then
		nLastLine = HULF_PAGE
	end
	self.sequence = DOTween.Sequence()
	if nLine == 1 then
		local nTime = 0
		if bOnePage then
			nTime = FALLIN_ALL_TIME / nLastLine
		else
			nTime = FALLIN_TIME
		end
		for i = 1, nLastLine do
			self.sequence:AppendCallback(function()
				NovaAPI.SetCanvasGroupAlpha(self.tbGoItem[i].go.transform:GetComponent("CanvasGroup"), 1)
				self.tbGoItem[i].go:GetComponent("Animator"):Play("gacha_fall_in")
				if i == 1 then
					if nLastLine == 1 then
						WwiseAudioMgr:PlaySound("ui_roguelike_gacha_fall_1")
					elseif nLastLine == 2 then
						WwiseAudioMgr:PlaySound("ui_roguelike_gacha_fall_2")
					elseif 2 < nLastLine and nLastLine <= 6 then
						WwiseAudioMgr:PlaySound("ui_roguelike_gacha_fall_3")
					end
				end
			end)
			self.sequence:AppendInterval(nTime)
		end
	elseif nLine == 2 then
		local nTime = 0
		if bOnePage then
			nTime = FALLIN_ALL_TIME / nPageCount
		else
			nTime = FALLIN_TIME
		end
		for i = 1, HULF_PAGE do
			self.sequence:AppendCallback(function()
				NovaAPI.SetCanvasGroupAlpha(self.tbGoItem[i].go.transform:GetComponent("CanvasGroup"), 1)
				self.tbGoItem[i].go:GetComponent("Animator"):Play("gacha_fall_in")
				if i == 1 then
					WwiseAudioMgr:PlaySound("ui_roguelike_gacha_fall_4")
				end
			end)
			self.sequence:AppendInterval(nTime)
		end
		self.sequence:AppendInterval(LINE_SPACE_TIME)
		for i = HULF_PAGE + 1, HULF_PAGE + nLastLine do
			self.sequence:AppendCallback(function()
				NovaAPI.SetCanvasGroupAlpha(self.tbGoItem[i].go.transform:GetComponent("CanvasGroup"), 1)
				self.tbGoItem[i].go:GetComponent("Animator"):Play("gacha_fall_in")
			end)
			self.sequence:AppendInterval(nTime)
		end
	end
	for i = 1, nPageCount do
		self.sequence:AppendCallback(function()
			if self.tbGoItem[i].bSSR then
				WwiseAudioMgr:PlaySound("ui_roguelike_gacha_specialOpen")
			else
				WwiseAudioMgr:PlaySound("ui_roguelike_gacha_commonOpen")
			end
		end)
		self.sequence:AppendInterval(0.05)
		self.sequence:AppendCallback(function()
			if self.tbGoItem[i].bSSR then
				self.tbGoItem[i].go:GetComponent("Animator"):Play("gacha_open_ssr")
			else
				self.tbGoItem[i].go:GetComponent("Animator"):Play("gacha_open_r")
			end
		end)
		self.sequence:AppendInterval(self.tbGoItem[i].bSSR and OPEN_SSR_TIME or OPEN_R_TIME)
	end
	self.sequence:AppendInterval(bLast and 1 or 0.5)
	self.sequence:Append(self._mapNode.rtContent:DOAnchorPos(Vector2(0, 1000), 0.3))
	for i = 1, nPageCount do
		self.sequence:AppendCallback(function()
			NovaAPI.SetCanvasGroupAlpha(self.tbGoItem[i].go.transform:GetComponent("CanvasGroup"), 0)
		end)
	end
	function self.sequence.onComplete()
		callback()
	end
	self.sequence:SetUpdate(true)
end
function FixedRoguelikeRewardGachaCtrl:ShowReward(mapResult)
	local tbReward = self:ProcessResult(clone(mapResult))
	if #tbReward == 0 then
		self:OnBtnClick_Close(nil, false)
		return
	end
	local nListCount = math.ceil(#tbReward / FULL_PAGE)
	self:ProcessListData(tbReward)
	self.gameObject:SetActive(true)
	self:ShowList(nListCount)
end
function FixedRoguelikeRewardGachaCtrl:ShowList(nListCount)
	local nShowOrder = 0
	local function func_ShowList()
		nShowOrder = nShowOrder + 1
		if nShowOrder > nListCount then
			self:OnBtnClick_Close(nil, false)
			return
		end
		local bHulfPage = nListCount == 1 and #self.tbRewardList[1] <= HULF_PAGE
		local bOnePage = nListCount == 1
		self:RefreshListItem(self.tbRewardList[nShowOrder], bHulfPage)
		self:PlayListAni(#self.tbRewardList[nShowOrder], nShowOrder == nListCount, bOnePage, func_ShowList)
	end
	func_ShowList()
end
function FixedRoguelikeRewardGachaCtrl:Awake()
	self.gameObject:SetActive(false)
	self.tbGoItem = nil
	self.tbRewardList = nil
end
function FixedRoguelikeRewardGachaCtrl:OnEnable()
end
function FixedRoguelikeRewardGachaCtrl:OnDisable()
end
function FixedRoguelikeRewardGachaCtrl:OnDestroy()
end
function FixedRoguelikeRewardGachaCtrl:OnBtnClick_Close(btn, bNeedStop)
	if self.sequence then
		self.sequence:Kill()
	end
	if bNeedStop then
		WwiseAudioMgr:PlaySound("ui_roguelike_gacha_allStop")
	end
	self.gameObject:SetActive(false)
	self.tbGoItem = nil
	self.tbRewardList = nil
	delChildren(self._mapNode.rtContent)
	EventManager.Hit("CloseRewardGacha")
end
return FixedRoguelikeRewardGachaCtrl
