local this = class("pageFormationMain", G_UIPageBase)
local MinFormationIndex = 1
local _heroTpl = L_GameTpl:getHeroTpl()

function this.bind()
  return {
    go_overlook = true,
    go_btnEnableFormation = true,
    module_commonTop = {
      moduleName = "modulePages/moduleCommonTop"
    },
    go_listBtnAdd = false,
    list_btnAdd = {
      moduleName = "pages/formation/formationModule/cellTeamBtnAdd"
    },
    list_hud = {
      moduleName = "pages/formation/formationModule/cellTeamUnitHud"
    },
    go_teamInfo = false,
    txt_teamName = "",
    img_teamIndex = nil,
    list_formationIndexTab = {
      moduleName = "pages/formation/formationModule/cellFormationIndexTab"
    },
    go_editHero = false,
    module_selectHero = {
      moduleName = "modulePages/unit/moduleSelectHero"
    },
    go_editPet = false,
    module_selectPet = {
      moduleName = "modulePages/unit/moduleSelectPet"
    },
    txt_posIndex = nil
  }
end

function this.methods()
  return {
    onClick_quickFormation = function(self)
      L_UI:open("pageQuickFormation", {
        formationType = L_FormationManager:getRuntimeFormationType(),
        teamIndex = L_FormationManager:getRuntimeFormationIndex(),
        vfxCb = function(teamInfo)
          self:playRandHeroVoice(teamInfo)
        end
      })
    end,
    onClick_enableFormation = function(self)
      L_FormationManager:switchGroup(L_FormationManager:getRuntimeFormationType(), L_FormationManager:getRuntimeFormationIndex(), function()
        self.bind.go_btnEnableFormation = false
        L_FlyMsgManager:showNormalMsg(L_WordsTpl:getValue("notice_formation_DefaultEnable"))
      end)
    end,
    onClick_last = function(self)
      self:changeTeamIndex(-1)
    end,
    onClick_next = function(self)
      self:changeTeamIndex(1)
    end,
    onClick_emptyArea = function(self)
      self:onClickEmptyArea()
    end,
    onClick_editTeamName = function(self)
      local systemId = L_SystemConst.enum.renameTeam
      if L_SystemBreakManager:checkBanSystemAndTip(systemId) then
        return
      end
      local data = {
        txtTitle = L_WordsTpl:getValue("notice_pageFormationMain_04"),
        placeHolder = L_WordsTpl:getValue("ui_formaitonName"),
        limit = 7,
        textBoxType = L_Const.CommonTextBoxType.Rename,
        confirmCallback = function(txt)
          if string.isEmpty(string.trim(txt)) then
            L_FlyMsgManager:showNormalMsgByKey("notice_pageFormationMain_03")
            return
          end
          if string.gsub(txt, " ", "") ~= txt then
            L_FlyMsgManager:showNormalMsgByKey("notice_pageFormationMain_02")
            return
          end
          AzurWorld.formationMgr:ReqChangeFormationName(L_FormationManager:getRuntimeFormationType(), L_FormationManager:getRuntimeFormationIndex(), txt)
        end
      }
      L_GameUtil.showNormalTextBox(data)
    end,
    list_btnAdd = {
      onClick_addHero = function(self, bind)
        local editStatus = L_FormationManager:getEditStatus()
        if editStatus == L_FormationConst.FormationEditStatus.EditHero then
          if bind.posIndex == L_FormationManager:getFocusIndex() then
            return
          end
          L_FormationManager:setFocusIndex(bind.posIndex)
          self:initEditHeroView()
          self:initEditHeroViewWithEntity()
          self:initSelectHeroModule()
        else
          self:editHeroByPos(bind.posIndex)
        end
      end,
      onClick_addPet = function(self, bind)
        self:editPetByPos(bind.posIndex)
      end,
      onClick_addSwitchPos = function(self, bind)
        self:changePos(bind.posIndex)
      end
    },
    module_selectHero = {
      onClick_selectHero = function(self, heroGuid, callBack)
        if L_FormationManager:getEditStatus() ~= L_FormationConst.FormationEditStatus.EditHero then
          return
        end
        local posData = L_FormationStore:getFormationPosData(L_FormationManager:getRuntimeFormationType(), L_FormationManager:getRuntimeFormationIndex())
        if heroGuid == posData[L_FormationManager:getFocusIndex()] then
          L_FormationManager:req_removeHero(L_FormationManager:getRuntimeFormationType(), L_FormationManager:getRuntimeFormationIndex(), L_FormationManager:getFocusIndex(), function()
            L_FlyMsgManager:showNormalMsg(L_WordsTpl:getValue("notice_formation_remove"))
            if callBack then
              callBack()
            end
          end)
        else
          L_FormationManager:req_addHero(L_FormationManager:getRuntimeFormationType(), L_FormationManager:getRuntimeFormationIndex(), L_FormationManager:getFocusIndex(), heroGuid, function()
            local heroData = L_HeroStore:getHero(heroGuid)
            self._nextPlayAudioTime = self._nextPlayAudioTime or 0
            if L_TimeUtil.getServerTime() >= self._nextPlayAudioTime then
              L_HeroVoiceManager:playHeroVoice(string.format("Play_VO_System_%s_Forming", L_HeroStore:getHeroConfigId(heroData)))
              self._nextPlayAudioTime = L_TimeUtil.getServerTime() + L_GameConstTpl:getValue("CHAR_VOICE_TEAM_INTERVAL") / 1000
            end
            if callBack then
              callBack()
            end
          end)
        end
      end,
      onVFXPlay_hide = function(self)
        self.bind.go_editHero = false
      end
    },
    module_selectPet = {
      onClick_selectPet = function(self, petGuid)
        if L_FormationManager:getEditStatus() ~= L_FormationConst.FormationEditStatus.EditPet then
          return
        end
        self.petCameraSwitchFlag = nil
        local curPosHero = L_FormationStore:getFormationPosData(L_FormationManager:getRuntimeFormationType(), L_FormationManager:getRuntimeFormationIndex())[L_FormationManager:getFocusIndex()]
        local curPosPet = L_FormationStore:getFormationPosPetGuid(L_FormationManager:getRuntimeFormationType(), L_FormationManager:getRuntimeFormationIndex(), L_FormationManager:getFocusIndex())
        if curPosPet == petGuid then
          L_HeroManager:reqWearPet(curPosHero, nil, function()
            L_FlyMsgManager:showNormalMsg(L_WordsTpl:getValue("notice_formation_remove"))
          end)
        else
          local _confirmFunc = function()
            L_HeroManager:reqWearPet(curPosHero, petGuid, function()
              local pet = L_PetStore:getPetItem(petGuid)
              L_AudioUtil.stopSound(self._petVoiceWrap)
              self._petVoiceWrap = L_PetStore:playPetVoiceSound(pet.id, L_PetConst.PetSystemVoiceType.IntoTeam)
            end)
          end
          if L_SettingStore:getSetData(L_Const.settingType.formationPetConfirm) == "true" and curPosPet and 0 < curPosPet then
            local heroData = _heroTpl:getTplById(L_HeroStore:getHeroConfigId(L_HeroStore:getHero(curPosHero)))
            local heroStr = _heroTpl:getName(heroData)
            L_GameUtil.showCommonTip({
              txtContent = L_Lang:get(L_WordsTpl:getValue("notice_formation_change_pet"), {
                [0] = heroStr
              }),
              confirmCallback = _confirmFunc
            })
          else
            _confirmFunc()
          end
        end
      end,
      onVFXPlay_hide = function(self)
        self.bind.go_editPet = false
      end
    }
  }
end

function this:check(options, callback)
  if L_DungeonManager:getIsInTrainTaskDungeon() then
    callback(false)
    return
  end
  if L_PlayerManager:inKiBoTransformMainControl() then
    L_FlyMsgManager:showNormalMsg(L_WordsTpl:getValue("notice_transform_02"))
    callback(false)
    return
  end
  if L_FormationStore:getIsTrailFormation(L_FormationManager:getCurFormationType()) or L_DungeonManager:getIsInDungeon() then
    L_FlyMsgManager:showNormalMsg(L_WordsTpl:getValue("notice_pageFormationMain_01"))
    callback(false)
    return
  end
  if L_BattleDataManager:checkPlayerBattle() then
    L_FlyMsgManager:showNormalMsg(L_BattleDataManager:getBattleBlockTips(L_Const.BattleBlockType.FormationSetting))
    callback(false)
    return
  end
  local result = L_SystemUnlockManager:checkAndTip(L_SystemConst.enum.formation)
  if not L_FormationManager:checkCanChangeFormation() then
    callback(false)
    return
  end
  callback(result)
end

function this:preOpen(options)
  this.super.preOpen(self, options)
  L_FormationManager:loadFormationScene()
  L_FormationManager:setRuntimeFormationType(options and options.formationType or L_FormationConst.FormationType.world)
  L_FormationManager:setRuntimeFormationIndex(L_FormationStore:getUsingTeamIndex(L_FormationManager:getRuntimeFormationType()))
  self._ESyncFormationServerDataHandler = handler(self, self.onEvent_refreshFormation)
  AzurWorld.formationMgr:RegisterEvent(C_EFormationEvent.ESyncFormationServerData, self._ESyncFormationServerDataHandler)
  self._ESyncHeroServerDataHandler = handler(self, self.onEvent_refreshFormation)
  AzurWorld.heroMgr:RegisterEvent(C_EHeroEvent.ESyncHeroServerDataList, self._ESyncHeroServerDataHandler)
  L_PetStore:listenCallFunc(L_PetStore.event.refreshPet, self.onEvent_refreshFormation, self, nil, 0)
  self._lateUpdateHandle = L_CommonUtil.handle(self.onLateUpdate_displayFollow, self)
  C_UpdateSource.AddLateUpdateEventHandler(self._lateUpdateHandle, "FormationMainPage.lateUpdate")
  L_SceneManager:setSceneActive(false)
  L_HomeManager:setHomeRootActive(false)
  self._moduleSelectPet = self.modules.module_selectPet
  self._moduleSelectHero = self.modules.module_selectHero
  self._dragStartPosX = 0
  self:initPage()
  self.dontBack2RootWhenClose = options and options.dontBack2RootWhenClose or false
  if AzurWorld.playerMgr and AzurWorld.playerMgr.myPlayerUnitAdapter then
    AzurWorld.playerMgr.myPlayerUnitAdapter.pause = true
  end
end

function this:show()
  L_TimerManager:clearTimer(self)
  L_FormationManager:setSceneArtActive(true)
  self:configTouch("+")
  local status = L_FormationManager:getEditStatus()
  if L_FormationManager:getNeedRevertFormationScene() then
    self:initFormationModel()
    self:initHudList()
    if status == L_FormationConst.FormationEditStatus.Overlook then
      self:initOverlookView()
      self:initAddBtnList()
    elseif status == L_FormationConst.FormationEditStatus.EditHero then
      self:initEditHeroView()
      self:initEditHeroViewWithEntity()
      self:initSelectHeroModule()
    elseif status == L_FormationConst.FormationEditStatus.EditPet then
      self:initEditPetView()
      self:initSelectPetModule()
    end
    L_FormationManager:revertFormationScene()
  end
  if status == L_FormationConst.FormationEditStatus.EditPet then
    self.modules.module_selectPet:refreshContent()
  end
end

function this:hide()
  L_TimerManager:newOrResetTimer(self, "hide", function()
    L_FormationManager:setSceneArtActive(false)
  end, 0.07)
  self:configTouch("-")
end

function this:close(options)
  this.super.close(self, options)
  L_TimerManager:clearTimer(self)
  L_AudioUtil.stopSound(self._petVoiceWrap)
  if self._lateUpdateHandle then
    C_UpdateSource.RemoveLateUpdateEventHandler(self._lateUpdateHandle)
  end
  self._lateUpdateHandle = nil
  AzurWorld.formationMgr:UnregisterEvent(C_EFormationEvent.ESyncFormationServerData, self._ESyncFormationServerDataHandler)
  AzurWorld.heroMgr:UnregisterEvent(C_EHeroEvent.ESyncHeroServerDataList, self._ESyncHeroServerDataHandler)
  L_PetStore:unListenCallFunc(L_PetStore.event.refreshPet, self.onEvent_refreshFormation, self, nil, 0)
  L_FormationManager:removeFormationScene()
  if AzurWorld.playerMgr and AzurWorld.playerMgr.myPlayerUnitAdapter then
    AzurWorld.playerMgr.myPlayerUnitAdapter.pause = false
  end
end

function this:escHandle()
  local editStatus = L_FormationManager:getEditStatus()
  if editStatus == L_FormationConst.FormationEditStatus.EditPet then
    if not self._moduleSelectPet:escHandle() then
      self:closeEditPet()
    end
  elseif editStatus == L_FormationConst.FormationEditStatus.EditHero then
    if self._isChangePosMode then
      self:closeChangePosView()
      self:initEditHeroView()
      self:initEditHeroViewWithEntity()
      self:initSelectHeroModule()
      self:initHudList()
    elseif not self._moduleSelectHero:escHandle() then
      self:closeEditHero()
    end
  elseif editStatus == L_FormationConst.FormationEditStatus.Overlook then
    self:closeCurPage()
  end
end

function this:initPage()
  self:initCommonTopModule()
  self:initTeamInfo()
  self:initOverlookView()
  self:initAddBtnList()
  self:initFormationModel()
  self:initHudList()
end

function this:initCommonTopModule()
  local data = {
    name = L_WordsTpl:getValue("ui_systemMessage_17"),
    nameEn = "TE                            AM",
    closeCurPage = handler(self, self.escHandle)
  }
  self.modules.module_commonTop:initModule(data)
end

function this:initOverlookView()
  self.bind.go_overlook = true
  self.bind.go_teamInfo = true
  self:initTeamInfo()
  self:initBtnGroup()
end

function this:initTeamInfo()
  if self._lastTeamIndex ~= L_FormationManager:getRuntimeFormationIndex() then
    self.bindComponents.ani_node_teamInfo:Stop()
    self.bindComponents.ani_node_teamInfo:Play("anim_formation_team_name_show")
    self._lastTeamIndex = L_FormationManager:getRuntimeFormationIndex()
  end
  self.bind.txt_teamName = L_FormationStore:getFormationName(L_FormationManager:getRuntimeFormationType(), L_FormationManager:getRuntimeFormationIndex())
  self.bind.img_teamIndex = string.format("UI/Atlas/FormationPage/tex_formation_icon_team%s.png", L_FormationManager:getRuntimeFormationIndex())
  self:initFormationIndexTabList()
end

function this:initFormationIndexTabList()
  local formationCount = L_FormationConst.FormationTeamPresetCount[L_FormationManager:getRuntimeFormationType()]
  local temp = {}
  for i = 1, formationCount do
    local isSelect = i == L_FormationManager:getRuntimeFormationIndex()
    local isUse = i == L_FormationStore:getUsingTeamIndex(L_FormationManager:getRuntimeFormationType())
    table.insert(temp, {
      selectId_group = isSelect and 0 or isUse and 1 or 2
    })
  end
  self.bind.list_formationIndexTab:clear()
  self.bind.list_formationIndexTab:insert_array(temp)
end

function this:initFormationModel(isSync)
  local posData = L_FormationStore:getFormationPosData(L_FormationManager:getRuntimeFormationType(), L_FormationManager:getRuntimeFormationIndex())
  for index = 1, L_FormationConst.FormationPosNum do
    local heroId = posData[index]
    local petId = L_FormationStore:getFormationPosPetGuid(L_FormationManager:getRuntimeFormationType(), L_FormationManager:getRuntimeFormationIndex(), index)
    L_FormationManager:loadHeroModelAtPlace(heroId, index, isSync)
    L_FormationManager:loadPetModelAtPlace(petId, index)
  end
end

function this:initHudList()
  local posData = L_FormationStore:getFormationPosData(L_FormationManager:getRuntimeFormationType(), L_FormationManager:getRuntimeFormationIndex())
  local temp = {}
  for index = 1, L_FormationConst.FormationPosNum do
    local heroId = posData[index]
    local petId = L_FormationStore:getFormationPosPetGuid(L_FormationManager:getRuntimeFormationType(), L_FormationManager:getRuntimeFormationIndex(), index)
    if not math.isEmpty(heroId) and (not self._isChangePosMode or self._isChangePosMode and index ~= L_FormationManager:getFocusIndex()) then
      table.insert(temp, {
        roleType = L_Const.roleType.hero,
        roleId = heroId,
        changePosMode = self._isChangePosMode,
        index = index,
        needDownBtn = true
      })
    end
    if not self._isChangePosMode and not math.isEmpty(petId) then
      table.insert(temp, {
        roleType = L_Const.roleType.pet,
        roleId = petId,
        index = index,
        needDownBtn = true
      })
    end
  end
  self.bind.list_hud:clear()
  self.bind.list_hud:insert_array(temp)
end

function this:refreshHudList()
  local list = self.modules.list_hud
  for i, hud in pairs(list) do
    hud:setFollow()
  end
end

function this:initAddBtnList(toEditStatus)
  self.bind.go_listBtnAdd = true
  local posData = L_FormationStore:getFormationPosData(L_FormationManager:getRuntimeFormationType(), L_FormationManager:getRuntimeFormationIndex())
  local temp = {}
  local editStatus = toEditStatus or L_FormationManager:getEditStatus()
  for index = 1, L_FormationConst.FormationPosNum do
    local heroId = posData[index]
    if editStatus == L_FormationConst.FormationEditStatus.Overlook then
      if math.isEmpty(heroId) then
        table.insert(temp, {
          posIndex = index,
          roleType = L_Const.roleType.hero
        })
      end
    elseif editStatus == L_FormationConst.FormationEditStatus.EditHero then
      local petId = L_FormationStore:getFormationPosPetGuid(L_FormationManager:getRuntimeFormationType(), L_FormationManager:getRuntimeFormationIndex(), index)
      if math.isEmpty(petId) and not math.isEmpty(heroId) and not self._isChangePosMode then
        table.insert(temp, {
          posIndex = index,
          roleType = L_Const.roleType.pet
        })
      elseif math.isEmpty(heroId) then
        table.insert(temp, {
          posIndex = index,
          roleType = L_Const.roleType.hero,
          isChangePosMode = self._isChangePosMode
        })
      end
    end
  end
  self.bind.list_btnAdd:clear()
  self.bind.list_btnAdd:insert_array(temp)
end

function this:refreshAddBtnList()
  local list = self.modules.list_btnAdd
  for i, hud in pairs(list or {}) do
    hud:setFollow()
  end
end

function this:initBtnGroup()
  if L_FormationManager:getRuntimeFormationType() == L_FormationConst.FormationType.world then
    local curIndex = L_FormationStore:getUsingTeamIndex(L_FormationManager:getRuntimeFormationType())
    self.bind.go_btnEnableFormation = curIndex ~= L_FormationManager:getRuntimeFormationIndex()
  end
end

function this:closeCurPage()
  local curTeamIndex = L_FormationStore:getUsingTeamIndex(L_FormationManager:getRuntimeFormationType())
  if curTeamIndex ~= L_FormationManager:getRuntimeFormationIndex() then
    local vaildHeroCount = L_FormationStore:getTeamHeroCount(L_FormationManager:getRuntimeFormationType(), L_FormationManager:getRuntimeFormationIndex())
    if 0 < vaildHeroCount then
      L_GameUtil.showCommonTip({
        txtContent = L_WordsTpl:getValue("notice_formation_DefaultDisable"),
        confirmCallback = function()
          self:saveWorldFormation()
        end
      })
      return
    end
  end
  self:saveWorldFormation()
end

function this:saveWorldFormation()
  L_LoadingManager:openSaveFormationLoading(nil, function()
    if self.dontBack2RootWhenClose then
      L_UI:close(self.pageName)
      AzurWorld.playerMgr.myPlayerUnitAdapter.pause = false
      AzurWorld.playerMgr.myPlayerUnitAdapter:ResumePlayerUnit(nil, true)
      return
    end
    L_UI:backToRoot()
    AzurWorld.playerMgr.myPlayerUnitAdapter.pause = false
    AzurWorld.playerMgr.myPlayerUnitAdapter:ResumePlayerUnit(nil, true)
  end)
end

function this:changeTeamIndex(addNum)
  local presetCount = L_FormationConst.FormationTeamPresetCount[L_FormationManager:getRuntimeFormationType()] or 0
  local tmpIndex = L_FormationManager:getRuntimeFormationIndex() + addNum
  if presetCount < tmpIndex then
    tmpIndex = MinFormationIndex
  elseif tmpIndex < MinFormationIndex then
    tmpIndex = presetCount
  end
  if tmpIndex == L_FormationManager:getRuntimeFormationIndex() then
    return
  end
  L_FormationManager:setRuntimeFormationIndex(tmpIndex)
  self:initPage()
end

function this:editHeroByPos(index)
  if L_FormationManager:getEditStatus() ~= L_FormationConst.FormationEditStatus.Overlook then
    return
  end
  self.bind.go_overlook = false
  self.bind.go_listBtnAdd = false
  L_FormationManager:setFocusIndex(index)
  L_TimerManager:newOrResetTimer(self, "editHeroByPos_VFX", function()
    self:initSelectHeroModule()
    self:initEditHeroView()
    self:initEditHeroViewWithEntity(L_FormationConst.FormationEditStatus.EditHero)
  end, 0.2)
  L_FormationManager:switchToEditHero()
end

function this:initEditHeroView()
  self._isChangePosMode = false
  self.bind.go_overlook = false
  self.bind.go_teamInfo = true
end

function this:initEditHeroViewWithEntity(toEditStatus)
  self:initAddBtnList(toEditStatus)
  L_FormationManager:setFocusEffect(L_FormationManager:getFocusIndex(), toEditStatus)
end

function this:initSelectHeroModule()
  self.bind.go_editHero = true
  local param = {}
  param.systemId = L_SystemConst.enum.formationBaseHero
  self._moduleSelectHero:initModule(param)
end

function this:closeEditHero()
  self:playHideHeroModuleVFX()
  self.bind.go_listBtnAdd = false
  L_TimerManager:newOrResetTimer(self, "closeEditHero_VFX", function()
    self:initOverlookView()
    self:initAddBtnList(L_FormationConst.FormationEditStatus.Overlook)
  end, 0.2)
  L_FormationManager:switchToOverlook()
end

function this:editPetByPos(posIndex)
  if L_FormationManager:getEditStatus() ~= L_FormationConst.FormationEditStatus.EditHero then
    return
  end
  self:playHideHeroModuleVFX()
  self.bind.go_listBtnAdd = false
  self.bind.go_teamInfo = false
  L_FormationManager:setFocusIndex(posIndex)
  L_TimerManager:newOrResetTimer(self, "initSelectPetModule_VFX", function()
    self:initSelectPetModule()
  end, 0.17)
  self.petCameraSwitchFlag = nil
  L_FormationManager:switchToEditPet(posIndex, function()
    self:initEditPetView()
  end)
end

function this:playHideHeroModuleVFX()
  self._moduleSelectHero:playHideVFX()
end

function this:removeHero(idx)
  if not idx or idx <= 0 then
    printf("Formation", "removeHero idx invalid")
    return
  end
  L_FormationManager:req_removeHero(L_FormationManager:getRuntimeFormationType(), L_FormationManager:getRuntimeFormationIndex(), idx, function()
    L_FlyMsgManager:showNormalMsg(L_WordsTpl:getValue("notice_formation_remove"))
  end)
end

function this:initChangePosView()
  self:initAddBtnList()
  self:initHudList()
  L_FormationManager:setPosTranslucent(true)
end

function this:closeChangePosView()
  L_FormationManager:setPosTranslucent(false)
end

function this:changePos(targetPos)
  if targetPos == L_FormationManager:getFocusIndex() then
    return
  end
  local posData = L_FormationStore:getFormationPosData(L_FormationManager:getRuntimeFormationType(), L_FormationManager:getRuntimeFormationIndex())
  L_FormationManager:req_addHero(L_FormationManager:getRuntimeFormationType(), L_FormationManager:getRuntimeFormationIndex(), targetPos, posData[L_FormationManager:getFocusIndex()], function()
    L_FormationManager:setFocusIndex(targetPos)
    self:closeChangePosView()
    self:initEditHeroView()
    self:initSelectHeroModule()
    self:initEditHeroViewWithEntity()
    self:initHudList()
  end)
end

function this:initEditPetView()
  self.bind.go_overlook = false
  self.bind.go_teamInfo = false
end

function this:initSelectPetModule()
  self.bind.go_editPet = true
  local param = {}
  param.systemId = L_SystemConst.enum.formationBasePet
  param.editMode = true
  local curPosPet = L_FormationStore:getFormationPosPetGuid(L_FormationManager:getRuntimeFormationType(), L_FormationManager:getRuntimeFormationIndex(), L_FormationManager:getFocusIndex())
  if not math.isEmpty(curPosPet) then
    local petItem = L_PetStore:getPetItem(curPosPet)
    param.defaultSelectBoxIndex = petItem.box_id // 100
  end
  self._moduleSelectPet:initModule(param)
  self:initPosIndex()
end

function this:closeEditPet()
  self:playHidePetModuleVFX()
  self.bind.go_listBtnAdd = false
  L_TimerManager:newOrResetTimer(self, "initSelectHeroModule_VFX", function()
    self:initSelectHeroModule()
    self:initEditHeroView()
    self:initEditHeroViewWithEntity(L_FormationConst.FormationEditStatus.EditHero)
  end, 0.17)
  L_FormationManager:switchToEditHero()
  self.petCameraSwitchFlag = nil
end

function this:playHidePetModuleVFX()
  self._moduleSelectPet:playHideVFX()
end

function this:switchPetCamera()
  if L_FormationManager:getEditStatus() == L_FormationConst.FormationEditStatus.EditPet then
    self.petCameraSwitchFlag = not self.petCameraSwitchFlag
    L_FormationManager:switchPetCamera(self.petCameraSwitchFlag)
  end
end

function this:resetPetCamera()
  if L_FormationManager:getEditStatus() == L_FormationConst.FormationEditStatus.EditPet then
    self.petCameraSwitchFlag = nil
    L_FormationManager:resetPetCamera()
  end
end

function this:removePet(idx)
  if not idx or idx <= 0 then
    printf("Formation", "removePet idx invalid")
    return
  end
  local curPosHero = L_FormationStore:getFormationPosData(L_FormationManager:getRuntimeFormationType(), L_FormationManager:getRuntimeFormationIndex())[idx]
  L_HeroManager:reqWearPet(curPosHero, nil, function()
    L_FlyMsgManager:showNormalMsg(L_WordsTpl:getValue("notice_formation_remove"))
  end)
end

function this:initPosIndex()
  self.bind.txt_posIndex = tostring(L_FormationManager:getFocusIndex())
end

function this:onEvent_refreshFormation()
  if not L_FormationManager:getRuntimeFormationType() then
    return
  end
  self:initFormationModel(true)
  self:initHudList()
  self:initAddBtnList()
  self:initBtnGroup()
  self:initTeamInfo()
end

function this:onLateUpdate_displayFollow()
  self:refreshHudList()
  self:refreshAddBtnList()
end

function this:onClickEmptyArea()
  if L_UI:currentPage(L_UI.groupKeys.stack) ~= self.pageName then
    return
  end
  local editStatus = L_FormationManager:getEditStatus()
  if editStatus ~= L_FormationConst.FormationEditStatus.Overlook and editStatus ~= L_FormationConst.FormationEditStatus.EditHero then
    return
  end
  local mousePosition = CS.UnityEngine.Input.mousePosition
  local success, hit = C_CameraManager.mainCamera:ScreenRaycastByLayer(C_Vector2(mousePosition.x, mousePosition.y), "Character")
  if success then
    local hitObj = hit.collider.gameObject
    local name = hitObj.name
    local splitStr = string.split(name, "_")
    if splitStr[1] == "hero" then
      local heroId = tonumber(splitStr[2])
      local index = L_FormationStore:getHeroPlaceInTeam(L_FormationManager:getRuntimeFormationType(), L_FormationManager:getRuntimeFormationIndex(), heroId)
      if math.isEmpty(index) or not math.isEmpty(index) and index < 0 then
        return
      end
      if self._isChangePosMode then
        self:changePos(index)
      elseif editStatus == L_FormationConst.FormationEditStatus.Overlook then
        self:editHeroByPos(index)
      elseif editStatus == L_FormationConst.FormationEditStatus.EditHero then
        if index == L_FormationManager:getFocusIndex() then
          self:editPetByPos(index)
        else
          L_FormationManager:setFocusIndex(index)
          self:initEditHeroView()
          self:initEditHeroViewWithEntity()
          self:initSelectHeroModule()
        end
      end
      C_AudioManager.Play("Play_SFX_System_UI_Team_Seat_Click")
    elseif splitStr[1] == "pet" then
      local petGuid = tonumber(splitStr[2])
      local heroId = L_PetStore:getPetItem(petGuid).hero_id
      local index = L_FormationStore:getHeroPlaceInTeam(L_FormationManager:getRuntimeFormationType(), L_FormationManager:getRuntimeFormationIndex(), heroId)
      if math.isEmpty(index) or not math.isEmpty(index) and index < 0 then
        return
      end
      if self._isChangePosMode then
        self:changePos(index)
      elseif editStatus == L_FormationConst.FormationEditStatus.Overlook then
        self:editHeroByPos(index)
      elseif editStatus == L_FormationConst.FormationEditStatus.EditHero then
        self:editPetByPos(index)
      end
      C_AudioManager.Play("Play_SFX_System_UI_Team_Seat_Click")
    end
  elseif self._isChangePosMode then
    self:closeChangePosView()
    self:initEditHeroView()
    self:initEditHeroViewWithEntity()
    self:initSelectHeroModule()
    self:initHudList()
  end
end

function this:playRandHeroVoice(teamInfo)
  local heroList = {}
  for i = 1, #teamInfo do
    if teamInfo[i].hero_guid and teamInfo[i].hero_guid > 0 then
      table.insert(heroList, teamInfo[i].hero_guid)
    end
  end
  local idx = math.random(1, #heroList)
  local heroData = L_HeroStore:getHero(heroList[idx])
  self._nextPlayAudioTime = self._nextPlayAudioTime or 0
  if L_TimeUtil.getServerTime() >= self._nextPlayAudioTime then
    L_HeroVoiceManager:playHeroVoice(string.format("Play_VO_System_%s_Forming", L_HeroStore:getHeroConfigId(heroData)))
    self._nextPlayAudioTime = L_TimeUtil.getServerTime() + L_GameConstTpl:getValue("CHAR_VOICE_TEAM_INTERVAL") / 1000
  end
end

function this:configTouch(operator)
  self.onUILongTapStartHandle = self.onUILongStartEndHandle or L_CommonUtil.handle(self.onUI_longTapStartHandle, self)
  self.onUIDragStartHandle = self.onUIDragStartHandle or L_CommonUtil.handle(self.onUI_dragStartHandle, self)
  self.onUIDragEndHandle = self.onUIDragEndHandle or L_CommonUtil.handle(self.onUI_dragEndHandle, self)
  C_ScreenTouch.OnUI_LongTapStart(operator, self.onUILongTapStartHandle)
  C_ScreenTouch.OnUI_DragStart(operator, self.onUIDragStartHandle)
  C_ScreenTouch.OnUI_DragEnd(operator, self.onUIDragEndHandle)
end

function this:onUI_longTapStartHandle(gesture)
  if L_UI:currentPage(L_UI.groupKeys.stack) ~= self.pageName then
    return
  end
  local editStatus = L_FormationManager:getEditStatus()
  if editStatus ~= L_FormationConst.FormationEditStatus.EditHero then
    return
  end
  local mousePosition = CS.UnityEngine.Input.mousePosition
  local success, hit = C_CameraManager.mainCamera:ScreenRaycastByLayer(C_Vector2(mousePosition.x, mousePosition.y), "Character")
  if success then
    local hitObj = hit.collider.gameObject
    local name = hitObj.name
    local splitStr = string.split(name, "_")
    local index
    if splitStr[1] == "hero" then
      local heroId = tonumber(splitStr[2])
      index = L_FormationStore:getHeroPlaceInTeam(L_FormationManager:getRuntimeFormationType(), L_FormationManager:getRuntimeFormationIndex(), heroId)
    elseif splitStr[1] == "pet" then
      local petGuid = tonumber(splitStr[2])
      local heroId = L_PetStore:getPetItem(petGuid).hero_id
      index = L_FormationStore:getHeroPlaceInTeam(L_FormationManager:getRuntimeFormationType(), L_FormationManager:getRuntimeFormationIndex(), heroId)
    end
    if index and 0 < index then
      L_FlyMsgManager:startLongPress(gesture, 0.5, function()
        self._isChangePosMode = true
        L_FormationManager:setFocusIndex(index)
        L_FormationManager:setFocusEffect()
        self:initChangePosView()
        self:playHideHeroModuleVFX()
      end)
    end
  end
end

function this:onUI_dragStartHandle(gesture)
  if L_UI:currentPage(L_UI.groupKeys.stack) ~= self.pageName then
    return
  end
  if L_FormationManager:getEditStatus() ~= L_FormationConst.FormationEditStatus.Overlook then
    return
  end
  self._dragStartPosX = L_Vector3.screenToLocalInRectangle(self.bindComponents.rect_board, gesture.position).x
end

function this:onUI_dragEndHandle(gesture)
  if L_UI:currentPage(L_UI.groupKeys.stack) ~= self.pageName then
    return
  end
  if L_FormationManager:getEditStatus() ~= L_FormationConst.FormationEditStatus.Overlook then
    self._dragStartPosX = 0
    return
  end
  local dragEndPos = L_Vector3.screenToLocalInRectangle(self.bindComponents.rect_board, gesture.position)
  local dragDelta = dragEndPos.x - self._dragStartPosX
  if math.abs(dragDelta) >= self.bindComponents.rect_board.rect.width * 0.3 then
    local addNum = 0 < dragDelta and -1 or 1
    self:changeTeamIndex(addNum)
  end
  self._dragStartPosX = 0
end

return this
