local ChapterCompBaseCell = require "app/ui/main_city/component/main_comp_base_cell"
local ChapterComp = class("ChapterComp", ChapterCompBaseCell)

local UISpineObject = require "app/bf/unity/ui_spine_object"

-- local CHAPTER_PATH = "assets/arts/textures/background/chapter/%s.png"
local HERO_SPINE_ASSET_PATH = "assets/arts/spines/characters/%s/%s_skeletondata.asset"
local CHAPTER_PATH = "assets/arts/textures/background/main/%s.png"

local BOX_ICON = {
	"common_chest_1",
	"common_chest_4"
}

function ChapterComp:getIsOpen()
    return true
end

function ChapterComp:getEntranceName()
    return I18N:getGlobalText(I18N.GlobalConst.MAIN_CHAPTER)
end

function ChapterComp:isShowTopNode()
    return true
end

function ChapterComp:isShowSideBar()
    return true
end

function ChapterComp:isShowBounty()
    return true
end

function ChapterComp:isShowHeroFormation()
    return true
end

function ChapterComp:getFightHpCost()
    return DataManager.ChapterData:getFightCost()
end

function ChapterComp:onClickFight()
	ModuleManager.ChapterManager:startFight()
end

function ChapterComp:init()
	self.uiMap = self:getBaseObject():genAllChildren()
	self:initChapter()
end

function ChapterComp:initChapter()
	self.chapterImg = self.uiMap["chapter.img"]
	self.chapterNameTx = self.uiMap["chapter.name_tx"]
	self.chapterWavetx = self.uiMap["chapter.record_tx"]
	self.leftArrow = self.uiMap["chapter.left_arrow"]
	local leftArrowBtn = self.uiMap["chapter.left_arrow.btn"]
	leftArrowBtn:addClickListener(function()
		if DataManager.ChapterData:goLastChapter() then
			self:refresh()
		end
	end)
	self.rightArrow = self.uiMap["chapter.right_arrow"]
	local rightArrowBtn = self.uiMap["chapter.right_arrow.btn"]
	rightArrowBtn:addClickListener(function()
		if DataManager.ChapterData:goNextChapter() then
			self:refresh()
		end
	end)

	self.uiMap["chapter.effect_node.ui_spine_obj"]:playAnim("idle", true, false)

	self.chapterBg = self.uiMap["chapter_comp.bg"]
	self.chapterBg:setAnchoredPositionX(-720)
	self.bossSmoke = self.uiMap["chapter_comp.boss_smoke"]
	self.bossSmoke:setAnchoredPositionX(10000)
	self.smokeNodeTop = self.uiMap["chapter_comp.smoke_node_1"]
	self.monsterNodeTop = self.uiMap["chapter_comp.monster_node_1"]
	self.bossNode = self.uiMap["chapter_comp.boss_node"]
	self.bossNode:setActive(false)
	self.bossSpine = self.uiMap["chapter_comp.boss_node.boss"]
	self.smokeNodeDown = self.uiMap["chapter_comp.smoke_node_2"]
	self.monsterNodeDown = self.uiMap["chapter_comp.monster_node_2"]
	self.dialogueTx = self.uiMap["chapter_comp.dialogue_node.bg.text"]
	self.dialogueBg = self.uiMap["chapter_comp.dialogue_node.bg"]
	self.dialogueNode = self.uiMap["chapter_comp.dialogue_node"]
	self.dialogueNode:setAnchoredPositionX(0)
	self.monsterSpineTopPool = {}
	self.monsterSpineDownPool = {}
	self.monsterSpineTopList = {}
	self.monsterSpineDownList = {}
	-- self.monsterShadowPool = {}
	self.monsterSmokePool = {}
	self.startMonsterAction = true
end

function ChapterComp:refresh()
	self:refreshChapter()
end

function ChapterComp:refreshChapter(force)
	local chapterId = DataManager.ChapterData:getChapterId()
	if self.currChapterId ~= chapterId or force then
		if DataManager.ChapterData:getIsFirstChapter(chapterId) then -- 第一章不需要左箭头
			self.leftArrow:setVisible(false)
			self.rightArrow:setVisible(DataManager.ChapterData:getMaxChapterId() >= 1)
		elseif chapterId == DataManager.ChapterData:getMaxChapterId() + 1 then -- 只能看打的最远的关卡
			self.leftArrow:setVisible(true)
			self.rightArrow:setVisible(false)
		else
			self.leftArrow:setVisible(true)
			self.rightArrow:setVisible(not DataManager.ChapterData:isFinalChapter(chapterId))
		end

		self.currChapterId = chapterId
		local chapterInfo = ConfigManager:getConfig("chapter")[chapterId]
		local chapterI18NInfo = I18N:getConfig("chapter")[chapterId]
		if chapterInfo then
			local monsterIdList = chapterInfo.monster_id
			if monsterIdList then
				local bossId = monsterIdList[1]
				if bossId then
					local monsterCfg = ConfigManager:getConfig("monster_base")
					local monsterInfo = monsterCfg[bossId]
					if monsterInfo then
						-- self.dialogueBg:setAnchoredPositionY(monsterInfo.blood * monsterInfo.ui/10 + 20)
					end
				end
			end
			-- main_bg_1
			-- self.chapterBg:setTexture(string.format(CHAPTER_PATH, chapterInfo.scenes_a))		end
			self.chapterBg:setTexture(string.format(CHAPTER_PATH, "main_bg_1"))
		end
		if chapterI18NInfo then
			self.chapterNameTx:setText(chapterI18NInfo.name)
		end
		self.chapterWavetx:setText(I18N:getGlobalText(I18N.GlobalConst.CHAPTER_DESC_1, DataManager.ChapterData:getChapterMaxWave()))

		local slider = self.uiMap["chapter.progress_bg.slider"]
		if not self.boxObjs then
			self.boxObjs = {}
			for i = 1, 3 do
				self.boxObjs[i] = {
					box = self.uiMap["chapter.progress_bg.box_" .. i],
					desc = self.uiMap["chapter.progress_bg.box_desc_" .. i],
					spineObj = self.uiMap["chapter.progress_bg.spine_node.ui_spine_obj_" .. i],
					boxIcon = self.uiMap["chapter.progress_bg.box_" .. i .. ".box_icon"]
				}
			end
		end

		local mysteryBoxCount = DataManager.ChapterData:getChapterMysteryBoxRewardCount(chapterId)
		local mysteryBoxBg = self.uiMap["chapter_comp.img.bg"]
		mysteryBoxBg:setVisible(mysteryBoxCount > 0)
		local mysteryBoxIcon = self.uiMap["chapter.img.mystery_box_icon"]
		mysteryBoxIcon:setVisible(mysteryBoxCount > 0)
		if mysteryBoxCount > 0 then
			local gotCount = DataManager.ChapterData:getChapterMysteryBoxGotCount(chapterId)
			local desc = I18N:getGlobalText(I18N.GlobalConst.CHAPTER_DESC_2, gotCount, mysteryBoxCount)
			self.uiMap["chapter.img.mystery_box_icon.desc"]:setText(desc)
		end

		local rewardChapterId = DataManager.ChapterData:getIsHaveRewardsMinId()
		if rewardChapterId > chapterId then
			rewardChapterId = chapterId
		end

		local curMaxWave = DataManager.ChapterData:getChapterMaxWave(rewardChapterId)
		local boxCount = DataManager.ChapterData:getChapterBoxCount(rewardChapterId)
		local unitValue = 1 / boxCount
		local sliderValue = 0
		local lastValue = 0
		for i = 1, boxCount do
			if curMaxWave < lastValue then
				break
			end
			local maxWave = DataManager.ChapterData:getChapterBoxNum(rewardChapterId, i)
			local wave = math.min(curMaxWave, maxWave)
			sliderValue = sliderValue + unitValue * (wave - lastValue) / (maxWave - lastValue)
			lastValue = maxWave
		end
		slider:getComponent(GConst.TYPEOF_UNITY_CLASS.BF_SLIDER).value = sliderValue

		for index, objs in ipairs(self.boxObjs) do
			local show = boxCount >= index
			objs.box:setActive(show)
			objs.desc:setActive(show)
			objs.spineObj:setVisible(false)
			if show then
				local needWave = DataManager.ChapterData:getChapterBoxNum(rewardChapterId, index)
				local x = 370 * (index / boxCount)
				local rewards = DataManager.ChapterData:getChapterBoxRewards(rewardChapterId, index)
				local num = DataManager.ChapterData:getChapterBoxNum(rewardChapterId, index)
				local rewardGot = DataManager.ChapterData:getChapterBoxRewardGot(rewardChapterId, index)
				local icon = BOX_ICON[1]
				if rewardGot then
					icon = BOX_ICON[2]
				end
				objs.box:addClickListener(function()
					if needWave <= curMaxWave and not rewardGot then
						objs.spineObj:setVisible(true)
						objs.spineObj:playAnimComplete("open", false, false, function()
							ModuleManager.ChapterManager:openBox(rewardChapterId, index)
						end)
					else
						ModuleManager.TipsManager:showRewardsTips(rewards, nil, objs.box)
					end
				end)
				objs.boxIcon:setSprite(GConst.ATLAS_PATH.COMMON, icon)
				objs.box:setAnchoredPositionX(x)
				if needWave <= curMaxWave and not rewardGot then
					objs.spineObj:setVisible(true)
					objs.spineObj:playAnim("idle", true, false)
					objs.spineObj:setAnchoredPositionX(x)
					objs.boxIcon:setVisible(false)
				else
					objs.spineObj:setVisible(false)
					objs.boxIcon:setVisible(true)
				end
				objs.desc:setAnchoredPositionX(x)
				if boxCount == index then
					objs.desc:setText(I18N:getGlobalText(I18N.GlobalConst.MAIN_DESC_1, rewardChapterId))
				else
					objs.desc:setText(num)
				end
			end
		end

        self:refreshFightBtn()
		self:doBossAction()
	end
	self:doChapterMove()
	self:doMonsterAction()
end

function ChapterComp:onOpen()
	self.startMonsterAction = true
	if self.bossNode then
		self.bossNode:setAnchoredPositionX(0)
	end
	-- if self.bossShadow then
	-- 	self.bossShadow:setAnchoredPositionX(0)
	-- end
	if self.dialogueNode then
		self.dialogueNode:setAnchoredPositionX(0)
	end
end

function ChapterComp:onClose()
	if self.chapterMoveSeq then
		self.chapterMoveSeq:Kill()
		self.chapterMoveSeq = nil
	end
	if self.chapterMonsterGenerateSeq then
		self.chapterMonsterGenerateSeq:Kill()
		self.chapterMonsterGenerateSeq = nil
	end
	self.currChapterId = nil
	self.isTopTurn = nil
	self.startMonsterAction = false
	GFunc.killDOTween(GConst.DOTWEEN_IDS.CHAPTER_MONSTER)
	self.monsterSpineTopPool = {}
	self.monsterSpineDownPool = {}
	self.monsterSpineTopList = {}
	self.monsterSpineDownList = {}
	-- self.monsterShadowPool = {}
	self.monsterSmokePool = {}
	self.monsterNodeTop:removeAllChildren()
	self.monsterNodeDown:removeAllChildren()
	-- self.shadowNode:removeAllChildren()
	self.smokeNodeTop:removeAllChildren()
	self.smokeNodeDown:removeAllChildren()
end

-- region 动画
function ChapterComp:doChapterMove()
	if self.chapterMoveSeq then
		return
	end
	self.chapterBg:setAnchoredPositionX(-720)
	self.chapterMoveSeq = self.chapterBg:createBindTweenSequence()
	local moveTween = self.chapterBg:getTransform():DOAnchorPosX(720, 20):SetEase(CS.DG.Tweening.Ease.Linear)
	self.chapterMoveSeq:Append(moveTween)
	self.chapterMoveSeq:AppendCallback(function()
		self.chapterBg:setAnchoredPositionX(-720)
	end)
	self.chapterMoveSeq:SetLoops(-1)
end

function ChapterComp:doBossAction()
	if self.currChapterId == nil then
		return
	end
	local chapterInfo = ConfigManager:getConfig("chapter")[self.currChapterId]
	if chapterInfo == nil then
		return
	end
	local monsterIdList = chapterInfo.monster_id
	monsterIdList = {20001, 10001, 10002}
	if monsterIdList == nil then
		return
	end
	self.chapterMonsterShowList = monsterIdList
	if self.chapterBossId == nil then -- 还没显示boss模型
		self.chapterBossId = self.chapterMonsterShowList[1]
		local chapterBossId = self.chapterBossId
		local monsterCfg = ConfigManager:getConfig("monster_base")
		local monsterInfo = monsterCfg[self.chapterBossId]
		if monsterInfo then
			local modelId = monsterInfo.model_id
			local path = string.format(HERO_SPINE_ASSET_PATH, modelId, modelId)
			self.bossNode:setActive(false)
			local scale = monsterInfo.ui or 1
			local shadowScale = (monsterInfo.shadow or 1) * scale
			-- local shadowOffset = (monsterInfo.shadow_offset or 0) * scale
			-- self.bossShadow:setLocalScale(shadowScale, shadowScale, shadowScale)
			-- self.bossShadow:setAnchoredPosition(10000, shadowOffset)
			self.bossSmoke:setLocalScale(-shadowScale, shadowScale, shadowScale)
			self.bossSmoke:setAnchoredPositionX(10000)
			self.bossSpine:loadAssetAsync(modelId, function()
				if chapterBossId == self.chapterBossId then
					self.bossNode:setActive(true)
					self.bossSpine:setLocalScale(-scale, scale, scale)
					self.bossSpine:playAnim("move", true, true, true)
					-- self.bossShadow:setAnchoredPositionX(0)
					self.bossSmoke:playAnim("idle", true, true, true)
					self.bossSmoke:setAnchoredPositionX(0)
				else -- 加载完成后，已经切换到其他boss了
					self:doChangeBossAction()
				end
			end, path)
		end
	else
		local chapterBossId = self.chapterMonsterShowList[1]
		if self.chapterBossId ~= chapterBossId then
			self.chapterBossId = chapterBossId
			self:doChangeBossAction()
		end
	end
end

-- 切换boss
function ChapterComp:doChangeBossAction()
	local chapterBossId = self.chapterBossId
	local monsterCfg = ConfigManager:getConfig("monster_base")
	local monsterInfo = monsterCfg[self.chapterBossId]
	if monsterInfo then
		local modelId = monsterInfo.model_id
		local path = string.format(HERO_SPINE_ASSET_PATH, modelId, modelId)
		self.bossNode:setActive(false)
		local scale = monsterInfo.ui or 1
		local shadowScale = (monsterInfo.shadow or 1) * scale
		-- local shadowOffset = (monsterInfo.shadow_offset or 0) * scale
		-- self.bossShadow:setLocalScale(shadowScale, shadowScale, shadowScale)
		-- self.bossShadow:setAnchoredPosition(10000, shadowOffset)
		self.bossSmoke:setLocalScale(-shadowScale, shadowScale, shadowScale)
		self.bossSmoke:setAnchoredPositionX(10000)
		self.bossSpine:loadAssetAsync(modelId, function()
			if chapterBossId == self.chapterBossId then
				self.bossNode:setActive(true)
				self.bossSpine:setLocalScale(-scale, scale, scale)
				self.bossSpine:playAnim("move", true, true, true)
				-- self.bossShadow:setAnchoredPositionX(0)
				self.bossSmoke:playAnim("idle", true, true, true)
				self.bossSmoke:setAnchoredPositionX(0)
			else -- 加载完成后，已经切换到其他boss了
				self:doChangeBossAction()
			end
		end, path)
	end
end

function ChapterComp:doMonsterAction()
	if self.chapterMonsterGenerateSeq then
		return
	end
	self.chapterMonsterGenerateSeq = DOTweenManager:createSeqWithIntId()
	local interval = GFunc.getConstValue("chapter_idel_monster_x") / 1000
	interval = 2
	self.chapterMonsterGenerateSeq:AppendCallback(function()
		self:generateChapterMonsters()
	end)
	self.chapterMonsterGenerateSeq:AppendInterval(interval)
	self.chapterMonsterGenerateSeq:SetLoops(-1)
end

function ChapterComp:generateChapterMonsters()
	local monsterId
	if #self.chapterMonsterShowList <= 2 then
		monsterId = self.chapterMonsterShowList[2]
	else
		monsterId = self.chapterMonsterShowList[math.random(2, #self.chapterMonsterShowList)]
	end
	if monsterId == nil then
		return
	end
	local monsterCfg = ConfigManager:getConfig("monster_base")
	local monsterInfo = monsterCfg[monsterId]
	if monsterInfo == nil then
		return
	end
	if self.isTopTurn == nil then
		self.isTopTurn = math.random(1, 100) > 50
	end
	local modelId = monsterInfo.model_id
	local pool
	local list
	local parent
	local posY
	if self.isTopTurn then -- 刷上面
		pool = self.monsterSpineTopPool[modelId]
		list = self.monsterSpineTopList
		parent = self.monsterNodeTop
		posY = math.random(1, 300)
	else -- 刷下面
		pool = self.monsterSpineDownPool[modelId]
		list = self.monsterSpineDownList
		parent = self.monsterNodeDown
		posY = -math.random(1, 240)
	end
	self.isTopTurn = not self.isTopTurn
	if pool and #pool > 0 then
		local spine = table.remove(pool)
		table.insert(list, spine)
		spine:setActive(true)
		self:doMonsterMove(modelId, spine, posY, monsterInfo, not self.isTopTurn)
	else
		SpineManager:loadUIHeroSpineWidgetAsync(modelId, parent, function(spine)
			if not self.startMonsterAction then
				spine:destroy()
				return
			end
			table.insert(list, spine)
			local scale = monsterInfo.ui or 1
			spine:setLocalScale(-scale, scale, scale)
			self:doMonsterMove(modelId, spine, posY, monsterInfo, not self.isTopTurn)
		end)
	end
end

function ChapterComp:doMonsterMove(modelId, spine, posY, monsterInfo, isTopTurn)
	spine:playAnim("move", true, true, true)
	local posX = GConst.UI_SCREEN_WIDTH / 2 + 100
	local targetPosX = -GConst.UI_SCREEN_WIDTH / 2 - 300
	spine:setAnchoredPosition(posX, posY)
	local seq = DOTweenManager:createSeqWithIntId(GConst.DOTWEEN_IDS.CHAPTER_MONSTER)
	if self.chapterMonsterSpeed == nil then
		-- self.chapterMonsterSpeed = GFunc.getConstValue("chapter_idel_monstermove")
		self.chapterMonsterSpeed = 150
	end
	local distance = posX - targetPosX
	local moveTime = distance / self.chapterMonsterSpeed
	local moveTween = spine:getTransform():DOAnchorPosX(targetPosX, moveTime):SetEase(CS.DG.Tweening.Ease.Linear)
	seq:Append(moveTween)

	-- local monsterShadow = self:getMonsterShadow()
	local scale = monsterInfo.ui or 1
	local shadowScale = (monsterInfo.shadow or 1) * scale
	-- monsterShadow:setLocalScale(shadowScale, shadowScale, shadowScale)
	-- local shadowOffset = (monsterInfo.shadow_offset or 0) * scale
	-- monsterShadow:setAnchoredPosition(posX, posY + shadowOffset)
	-- local moveTween2 = monsterShadow:getTransform():DOAnchorPosX(targetPosX, moveTime):SetEase(CS.DG.Tweening.Ease.Linear)
	-- seq:Join(moveTween2)

	local monsterSmoke = self:getMonsterSmoke(isTopTurn)
	monsterSmoke:setAnchoredPosition(posX, posY)
	monsterSmoke:setLocalScale(-shadowScale, shadowScale, shadowScale)
	monsterSmoke:playAnim("idle", true, true, true)
	local moveTween3 = monsterSmoke:getTransform():DOAnchorPosX(targetPosX, moveTime):SetEase(CS.DG.Tweening.Ease.Linear)
	seq:Join(moveTween3)

	seq:AppendCallback(function()
		spine:setActive(false)
		-- monsterShadow:setAnchoredPositionX(10000)
		-- table.insert(self.monsterShadowPool, monsterShadow)
		monsterSmoke:setAnchoredPositionX(10000)
		table.insert(self.monsterSmokePool, monsterSmoke)
		if isTopTurn then
			local pool = self.monsterSpineTopPool[modelId]
			if pool == nil then
				pool = {}
				self.monsterSpineTopPool[modelId] = pool
			end
			table.insert(pool, spine)
			for k, v in ipairs(self.monsterSpineTopList) do
				if v == spine then
					table.remove(self.monsterSpineTopList, k)
					break
				end
			end
		else
			local pool = self.monsterSpineDownPool[modelId]
			if pool == nil then
				pool = {}
				self.monsterSpineDownPool[modelId] = pool
			end
			table.insert(pool, spine)
			for k, v in ipairs(self.monsterSpineDownList) do
				if v == spine then
					table.remove(self.monsterSpineDownList, k)
					break
				end
			end
		end
	end)
end

function ChapterComp:enterChapterBattle()
	-- boss等一会再跑
	local bossWaitTime = GFunc.getConstValue("chapter_fight_bosswait") / 1000
	local bossSeq = DOTweenManager:createSeqWithIntId(GConst.DOTWEEN_IDS.CHAPTER_MONSTER)
	bossSeq:AppendInterval(bossWaitTime)
	local bossSpeed = GFunc.getConstValue("chapter_fight_bossmove")
	local distance = GConst.UI_SCREEN_WIDTH/2 + 100
	local moveTime = distance / bossSpeed
	local targetPosX = -GConst.UI_SCREEN_WIDTH / 2 - 300
	local moveTween = self.bossNode:getTransform():DOAnchorPosX(targetPosX, moveTime):SetEase(CS.DG.Tweening.Ease.Linear)
	bossSeq:Append(moveTween)
	local moveTween2 = self.dialogueNode:getTransform():DOAnchorPosX(targetPosX, moveTime):SetEase(CS.DG.Tweening.Ease.Linear)
	bossSeq:Join(moveTween2)
	-- local moveTween3 = self.bossShadow:getTransform():DOAnchorPosX(targetPosX, moveTime):SetEase(CS.DG.Tweening.Ease.Linear)
	-- bossSeq:Join(moveTween3)


	-- 出来一批小怪从右边跑向左边
	local monsterCount = GFunc.getConstIntValue("chapter_fight_monster_num")
	self.chapterFightMonsterCount = monsterCount
	local wave = 5
	local monsterCountPerWave = math.ceil(monsterCount / wave)
	-- 分批处理
	local monsterSeq = DOTweenManager:createSeqWithIntId(GConst.DOTWEEN_IDS.CHAPTER_MONSTER)
	for i = 1, wave do
		monsterSeq:AppendCallback(function ()
			if monsterCountPerWave > monsterCount then
				monsterCountPerWave = monsterCount
			end
			monsterCount = monsterCount - monsterCountPerWave
			for j = 1, monsterCountPerWave do
				self:generateChapterFightMonsters()
			end
		end)
		monsterSeq:AppendInterval(0.03)
	end
	return GFunc.getConstValue("chapter_fight_wait") / 1000
end

function ChapterComp:generateChapterFightMonsters()
	local monsterId
	if #self.chapterMonsterShowList <= 2 then
		monsterId = self.chapterMonsterShowList[2]
	else
		monsterId = self.chapterMonsterShowList[math.random(2, #self.chapterMonsterShowList)]
	end
	if monsterId == nil then
		return
	end
	local monsterCfg = ConfigManager:getConfig("monster_base")
	local monsterInfo = monsterCfg[monsterId]
	if monsterInfo == nil then
		return
	end
	local modelId = monsterInfo.model_id
	local pool
	local list
	local parent
	local posY
	if self.isTopTurn then -- 刷上面
		pool = self.monsterSpineTopPool[modelId]
		list = self.monsterSpineTopList
		parent = self.monsterNodeTop
		posY = math.random(1, 300)
	else -- 刷下面
		pool = self.monsterSpineDownPool[modelId]
		list = self.monsterSpineDownList
		parent = self.monsterNodeDown
		posY = -math.random(1, 240)
	end
	self.isTopTurn = not self.isTopTurn
	if pool and #pool > 0 then
		local spine = table.remove(pool)
		table.insert(list, spine)
		spine:setActive(true)
		self:doMonsterFightMove(modelId, spine, posY, monsterInfo, not self.isTopTurn)
	else
		SpineManager:loadUIHeroSpineWidgetAsync(modelId, parent, function(spine)
			if not self.startMonsterAction then
				spine:destroy()
				return
			end
			table.insert(list, spine)
			local scale = monsterInfo.ui or 1
			spine:setLocalScale(-scale, scale, scale)
			self:doMonsterFightMove(modelId, spine, posY, monsterInfo, not self.isTopTurn)
		end)
	end
end

function ChapterComp:doMonsterFightMove(modelId, spine, posY, monsterInfo, isTopTurn)
	spine:playAnim("move", true, true, true)
	local posX = GConst.UI_SCREEN_WIDTH / 2 + math.random(100, math.floor(GConst.UI_SCREEN_WIDTH*2/3))
	spine:setAnchoredPosition(posX, posY)
	local seq = DOTweenManager:createSeqWithIntId(GConst.DOTWEEN_IDS.CHAPTER_MONSTER)
	if self.chapterMonsterFightSpeed == nil then
		-- self.chapterMonsterFightSpeed = GFunc.getConstValue("chapter_fight_monstermove")
		self.chapterMonsterFightSpeed = 880
	end
	local distance = posX + GConst.UI_SCREEN_WIDTH/2 + 100
	local moveTime = distance / self.chapterMonsterFightSpeed
	local targetPosX = -GConst.UI_SCREEN_WIDTH / 2 - 100
	local moveTween = spine:getTransform():DOAnchorPosX(targetPosX, moveTime):SetEase(CS.DG.Tweening.Ease.Linear)
	seq:Append(moveTween)

	-- local monsterShadow = self:getMonsterShadow()
	local scale = monsterInfo.ui or 1
	local shadowScale = (monsterInfo.shadow or 1) * scale
	-- monsterShadow:setLocalScale(shadowScale, shadowScale, shadowScale)
	-- local shadowOffset = (monsterInfo.shadow_offset or 0) * scale
	-- monsterShadow:setAnchoredPosition(posX, posY + shadowOffset)
	-- local moveTween2 = monsterShadow:getTransform():DOAnchorPosX(targetPosX, moveTime):SetEase(CS.DG.Tweening.Ease.Linear)
	-- seq:Join(moveTween2)

	local monsterSmoke = self:getMonsterSmoke(isTopTurn)
	monsterSmoke:setAnchoredPosition(posX, posY)
	monsterSmoke:setLocalScale(-shadowScale, shadowScale, shadowScale)
	monsterSmoke:playAnim("idle", true, true, true)
	local moveTween3 = monsterSmoke:getTransform():DOAnchorPosX(targetPosX, moveTime):SetEase(CS.DG.Tweening.Ease.Linear)
	seq:Join(moveTween3)

	seq:AppendCallback(function()
		spine:setActive(false)
		-- monsterShadow:setAnchoredPositionX(10000)
		-- table.insert(self.monsterShadowPool, monsterShadow)
		monsterSmoke:setAnchoredPositionX(10000)
		table.insert(self.monsterSmokePool, monsterSmoke)
		if isTopTurn then
			local pool = self.monsterSpineTopPool[modelId]
			if pool == nil then
				pool = {}
				self.monsterSpineTopPool[modelId] = pool
			end
			table.insert(pool, spine)
			for k, v in ipairs(self.monsterSpineTopList) do
				if v == spine then
					table.remove(self.monsterSpineTopList, k)
					break
				end
			end
		else
			local pool = self.monsterSpineDownPool[modelId]
			if pool == nil then
				pool = {}
				self.monsterSpineDownPool[modelId] = pool
			end
			table.insert(pool, spine)
			for k, v in ipairs(self.monsterSpineDownList) do
				if v == spine then
					table.remove(self.monsterSpineDownList, k)
					break
				end
			end
		end
	end)

	if self.chapterFightMonsterCount then
		self.chapterFightMonsterCount = self.chapterFightMonsterCount - 1
		if self.chapterFightMonsterCount == 0 then -- 最后一个怪物生成完毕后，重新排一下序
			self:sortChapterFightMonstersOrder()
			self:sortChapterFightMonstersOrder()
			self:sortChapterFightMonstersOrder()
			self:sortChapterFightMonstersOrder()
		end
	end
end

function ChapterComp:sortChapterFightMonstersOrder()
	self:sortChildrenOrder(self.monsterNodeTop)
	self:sortChildrenOrder(self.monsterNodeDown)
	self:sortChildrenOrder(self.smokeNodeTop)
	self:sortChildrenOrder(self.smokeNodeDown)
end

function ChapterComp:sortChildrenOrder(parent)
	local children = parent:getChildList()
	if children and #children > 0 then
		table.sort(children, function(a, b)
			return a:getAnchoredPositionY() > b:getAnchoredPositionY()
		end)

		for i = #children, 1, -1 do
			children[i]:getTransform():SetSiblingIndex(i - 1)
		end
	end
end

function ChapterComp:getMonsterSmoke(isTop)
	local monsterSmoke
	if #self.monsterSmokePool > 0 then
		monsterSmoke = table.remove(self.monsterSmokePool)
		monsterSmoke:setParent(isTop and self.smokeNodeTop or self.smokeNodeDown, false)
	else
		local shadowObj = CS.UnityEngine.Object.Instantiate(self.bossSmoke:getGameObject())
		monsterSmoke = UISpineObject:create()
		monsterSmoke:initWithPrefab(GConst.EMPTY_STRING, shadowObj)
		monsterSmoke:getAnimationState()
		monsterSmoke:setParent(isTop and self.smokeNodeTop or self.smokeNodeDown, false)
	end
	return monsterSmoke
end
-- endregion

return ChapterComp