local this = class("pageHero", G_UIPageBase)
local _heroTpl = L_GameTpl:getHeroTpl()

function this:created(...)
  this.super.created(self, ...)
  self.modeController = nil
  self.heroGuidList = {}
  self._ESyncHeroServerDataHandler = handler(self, self.onEvent_refreshHero)
  AzurWorld.heroMgr:RegisterEvent(C_EHeroEvent.ESyncHeroServerData, self._ESyncHeroServerDataHandler)
  L_HeroStore:listenCallFunc(L_HeroStore.event.setCurHeroGuid, self.onEvent_setCurHeroID, self)
  L_PlayerStore:listenCallFunc(L_PlayerStore.event.refreshModAvatar, self.onEvent_refreshAvatar, self)
  L_HeroManager:addListener(L_HeroManager.event.showHeroSelection, self.onShowHeroSelection, self)
end

local moduleShowRing = {
  [L_Const.heroModuleType.Property] = true,
  [L_Const.heroModuleType.Talent] = false,
  [L_Const.heroModuleType.Star] = false,
  [L_Const.heroModuleType.Spiritron] = false,
  [L_Const.heroModuleType.Accessory] = false,
  [L_Const.heroModuleType.Data] = false
}
local heroModuleType2ModuleName = {
  [L_Const.heroModuleType.Property] = "moduleProperty",
  [L_Const.heroModuleType.Talent] = "talentModule",
  [L_Const.heroModuleType.Star] = "starModule",
  [L_Const.heroModuleType.Spiritron] = "moduleSpirit",
  [L_Const.heroModuleType.Accessory] = "moduleAccessory",
  [L_Const.heroModuleType.Data] = "dataModule"
}
local heroModuleTypeList = {
  L_Const.heroModuleType.Property,
  L_Const.heroModuleType.Talent,
  L_Const.heroModuleType.Star,
  L_Const.heroModuleType.Spiritron,
  L_Const.heroModuleType.Accessory,
  L_Const.heroModuleType.FormationPet,
  L_Const.heroModuleType.Data
}
local heroModuleType2ToggleName = {
  [L_Const.heroModuleType.Property] = "togglePropertyActive",
  [L_Const.heroModuleType.Talent] = "toggleTalentActive",
  [L_Const.heroModuleType.Star] = "toggleStarActivee",
  [L_Const.heroModuleType.Spiritron] = "toggleSpiritronActive",
  [L_Const.heroModuleType.Accessory] = "toggleAccessoryActive",
  [L_Const.heroModuleType.Data] = "toggleDataActive"
}

function this.bind()
  return {
    bg = false,
    go_staticBg = false,
    go_timelineBg = false,
    heroModule = "",
    paintingPath = "",
    toggleInfo = 0,
    go_topbg = true,
    downBg = true,
    mask = false,
    togglePropertyActive = true,
    toggleSkillActive = false,
    toggleGiftActive = false,
    toggleStarActivee = true,
    toggleTalentActive = true,
    toggleAccessoryActive = true,
    toggleDataActive = true,
    togglePetActive = false,
    previewLevelToggles = false,
    toggleModuleBar = {
      type = "toggleModule",
      moduleProperty = {
        assetName = "UI/Pages/HeroPanel/moduleProperty",
        moduleName = "pages/heroPanel/moduleProperty"
      },
      skillModule = {
        assetName = "UI/Pages/HeroPanel/moduleHeroSkill",
        moduleName = "pages/heroPanel/skill/moduleSkill"
      },
      talentModule = {
        assetName = "UI/Pages/HeroPanel/moduleHeroTalent",
        moduleName = "pages/heroPanel/talent/moduleHeroTalent"
      },
      starModule = {
        assetName = "UI/Pages/HeroPanel/moduleHeroStar",
        moduleName = "pages/heroPanel/moduleHeroStar"
      },
      moduleSpirit = {
        assetName = "UI/Pages/HeroPanel/moduleHeroSpirit",
        moduleName = "pages/heroPanel/spirit/moduleHeroSpirit"
      },
      moduleAccessory = {
        assetName = "UI/Pages/HeroPanel/moduleHeroAccessory",
        moduleName = "pages/heroPanel/accessory/moduleAccessory"
      },
      dataModule = {
        assetName = "UI/Pages/HeroPanel/moduleHeroData",
        moduleName = "pages/heroPanel/moduleHeroData"
      },
      moduleGift = {
        assetName = "UI/Pages/HeroPanel/moduleHeroGift",
        moduleName = "pages/heroPanel/gift/moduleHeroGift"
      }
    },
    toggleModuleName = "",
    listHeroActive = true,
    listHeroHeads = {
      moduleName = "modulePages/cellHeroHeadItemCircle"
    },
    lastAndNext = true,
    ringActive = true,
    lockActive = false,
    modulesActive = true,
    txt_Property = "",
    txt_Talent = "",
    txt_Star = "",
    txt_Jewelry = "",
    txt_Data = "",
    txt_UnProperty = "",
    txt_UnTalent = "",
    txt_UnStar = "",
    txt_UnJewelry = "",
    txt_UnData = "",
    txt_CheckProperty = "",
    txt_CheckTalent = "",
    txt_CheckStar = "",
    txt_CheckJewelry = "",
    txt_CheckData = ""
  }
end

function this.methods()
  return {
    btnProperty = function(self)
      self:onSelectionChange(L_Const.heroModuleType.Property)
    end,
    btnGift = function(self)
      self:onSelectionChange(L_Const.heroModuleType.Gift)
    end,
    btnAccessory = function(self)
      self:onSelectionChange(L_Const.heroModuleType.Accessory)
    end,
    btnData = function(self)
      self:onSelectionChange(L_Const.heroModuleType.Data)
    end,
    btnSkill = function(self)
      self:onSelectionChange(L_Const.heroModuleType.Skill)
    end,
    btnTalent = function(self)
      self:onSelectionChange(L_Const.heroModuleType.Talent)
    end,
    btnStar = function(self)
      self:onSelectionChange(L_Const.heroModuleType.Star)
    end,
    btnFormationPet = function(self)
      self:onSelectionChange(L_Const.heroModuleType.FormationPet)
    end,
    togglePreviewOrigin = function(self)
      self:onTogglePreviewChange(false)
    end,
    togglePreviewMax = function(self)
      self:onTogglePreviewChange(true)
    end,
    onClick_lastHero = function(self)
      self.heroIndex = self.heroIndex == 1 and #self.heroGuidList or self.heroIndex - 1
      self.modeController:setSelectGuid(self.heroGuidList[self.heroIndex])
    end,
    onClick_nextHero = function(self)
      self.heroIndex = self.heroIndex == #self.heroGuidList and 1 or self.heroIndex + 1
      self.modeController:setSelectGuid(self.heroGuidList[self.heroIndex])
    end,
    listHeroHeads = {
      onClick = function(self, bind)
        if self.modeController:getSelectGuid() == bind.id then
          return
        end
        self.modeController:setSelectGuid(bind.id)
      end
    }
  }
end

function this:check(options, callback)
  local result = L_SystemUnlockManager:checkAndTip(L_SystemConst.enum.hero)
  if not result then
    callback(false)
    return
  end
  if L_PlayerManager:inKiBoTransformMainControl() then
    L_FlyMsgManager:showNormalMsg(L_WordsTpl:getValue("notice_transform_04"))
    callback(false)
    return
  end
  callback(true)
end

function this:preOpen(options)
  options = options or {}
  if options.jumpParams then
    options.selectModuleType = options.jumpParams[1]
  end
  self.options = options
  self:initModeController(options)
  self.bind.bg = true
  self.heroGuidList = options.heroIdList or self:getAllHeroList()
  self._heroId2FormationData = self:getFormationData()
  self:sortHeroGuidList()
  local selectHeroGuid = options.heroId or L_FormationStore:getControl(L_FormationConst.FormationType.world)
  local hero = L_HeroStore:getHero(selectHeroGuid)
  if L_HeroStore:getIsTrail(hero) then
    selectHeroGuid = nil
    local posData = L_FormationStore:getFormationPosData(L_FormationManager:getCurFormationType())
    for i, v in ipairs(posData) do
      if not math.isEmpty(v) then
        local hero_temp = L_HeroStore:getHero(v)
        if not L_HeroStore:getIsTrail(hero_temp) then
          selectHeroGuid = v
          break
        end
      end
    end
  end
  selectHeroGuid = selectHeroGuid or self.heroGuidList[1]
  if options and options.heroIdList then
    selectHeroGuid = options.heroIdList[1]
  end
  if options.callBack then
    self.callBack = options.callBack
  end
  self.modeController:setSelectGuid(selectHeroGuid, true)
  self.heroIndex = self:getHeroIndex()
  self:initHeroTimeline(true)
  self.preOpenInit = true
  self.lastTimelineState = L_Const.heroTimelineState.None
  self:setDownBg(true)
  self:refreshModuleTypeArea()
  self:initSystem()
  self:initTogglesRed()
  self:initHeroLock()
  L_SceneManager:setSceneActive(false)
  L_HomeManager:setHomeRootActive(false)
  self.bind.txt_Property = L_WordsTpl:getValue("ui_hero_dec_01")
  self.bind.txt_Talent = L_WordsTpl:getValue("ui_hero_dec_02")
  self.bind.txt_Star = L_WordsTpl:getValue("ui_hero_dec_03")
  self.bind.txt_Jewelry = L_WordsTpl:getValue("ui_hero_dec_04")
  self.bind.txt_Data = L_WordsTpl:getValue("ui_hero_dec_05")
  self.bind.txt_UnProperty = L_WordsTpl:getValue("ui_hero_dec_01")
  self.bind.txt_UnTalent = L_WordsTpl:getValue("ui_hero_dec_02")
  self.bind.txt_UnStar = L_WordsTpl:getValue("ui_hero_dec_03")
  self.bind.txt_UnJewelry = L_WordsTpl:getValue("ui_hero_dec_04")
  self.bind.txt_UnData = L_WordsTpl:getValue("ui_hero_dec_05")
  self.bind.txt_CheckProperty = L_WordsTpl:getValue("ui_hero_dec_01")
  self.bind.txt_CheckTalent = L_WordsTpl:getValue("ui_hero_dec_02")
  self.bind.txt_CheckStar = L_WordsTpl:getValue("ui_hero_dec_03")
  self.bind.txt_CheckJewelry = L_WordsTpl:getValue("ui_hero_dec_04")
  self.bind.txt_CheckData = L_WordsTpl:getValue("ui_hero_dec_05")
end

function this:onTopBarRefresh()
  self:setTopBarCloseCallback()
end

function this:setTopBarCloseCallback()
  L_TopBarManager:setTopBarCloseFunc(function()
    self:dealBack()
  end)
end

function this:dealBack()
  if self.closeCurPageFunc then
    self.closeCurPageFunc()
    self.closeCurPageFunc = nil
    L_TopBarManager:setTopBarBackName(self.modeController:getHomeName())
    return
  end
  L_UI:close(self.pageName)
end

function this:update()
  if L_Const.heroModuleType.Accessory == self.currentModuleType then
    local isShow = not L_UI:checkPageOpen("pageHeroSpiritUpgrade") and not L_UI:checkPageOpen("pageHeroSpiritSwitch") and not L_UI:checkPageOpen("pageAccessoryStrength") and not L_UI:checkPageOpen("pageSpiritronInfo") and not L_UI:checkPageOpen("pageSpiritronInfoLow")
    if self.bind.modulesActive ~= isShow then
      self:setDownBg(isShow)
      self.bind.modulesActive = isShow
    end
  end
end

function this:getAllHeroList()
  local list = {}
  for i, v in pairs(L_HeroStore:getAllHero()) do
    table.insert(list, L_HeroStore:getHeroGuid(v))
  end
  return list
end

function this:getFormationData()
  local formationType = L_FormationConst.FormationType.world
  local posData = L_FormationStore:getFormationPosData(formationType)
  local data = {}
  for i, guid in pairs(posData) do
    if not math.isEmpty(guid) then
      data[guid] = i
    end
  end
  return data
end

function this:getHeroIndex()
  for i, v in ipairs(self.heroGuidList) do
    if self.modeController:getSelectGuid() == v then
      return i
    end
  end
  return 1
end

function this:setCommonTopData(func, name)
  self.closeCurPageFunc = func
  if string.isEmpty(name) then
    L_TopBarManager:setTopBarBackName(self.modeController:getHomeName())
  else
    L_TopBarManager:setTopBarBackName(name)
  end
end

function this:sortHeroGuidList()
  table.sort(self.heroGuidList, function(a, b)
    local heroDataA = self.modeController:getHero(a)
    local heroDataB = self.modeController:getHero(b)
    if heroDataA == nil or heroDataB == nil then
      return a < b
    end
    local configA = L_ItemTplManager:getHeroItem(L_HeroStore:getHeroConfigId(heroDataA))
    local configB = L_ItemTplManager:getHeroItem(L_HeroStore:getHeroConfigId(heroDataB))
    local isOutA = self._heroId2FormationData[a] or math.huge
    local isOutB = self._heroId2FormationData[b] or math.huge
    if isOutA ~= isOutB then
      return isOutA < isOutB
    end
    local priorityOrder = {
      function()
        return L_HeroStore:getHeroLevel(heroDataA), L_HeroStore:getHeroLevel(heroDataB)
      end,
      function()
        return configA.quality, configB.quality
      end,
      function()
        return L_HeroStore:getHeroStar(heroDataA), L_HeroStore:getHeroStar(heroDataB)
      end
    }
    for _, getPriorityValue in ipairs(priorityOrder) do
      local valueA, valueB = getPriorityValue()
      if valueA ~= valueB then
        return valueB < valueA
      end
    end
    return a < b
  end)
end

function this:open(options)
  options = options or {}
  if options.jumpParams then
    options.selectModuleType = options.jumpParams[1]
  end
  self.curSelectButton = nil
  if not self.modeController:isPreviewMode() then
    self:populateHeroList()
  end
  self:refreshCanChangeHero(true)
  if options.selectModuleType then
    self:selectButtonIsOn(self.bindComponents["trans" .. L_Const.heroModuleType.Property], false)
  end
  self.frameSchedulerId = FrameScheduler.add(function()
    self.frameSchedulerId = nil
    self:refresh(options)
  end)
end

function this:populateHeroList()
  local tempData = {}
  local formationData = self:getFormationData()
  for k, v in ipairs(self.heroGuidList) do
    local heroId = v
    local hero = self.modeController:getHero(heroId)
    local heroConfigId = L_HeroStore:getHeroConfigId(hero)
    local heroHeadAvatarTexture = L_GameUtil.getAvatarTexturePath(heroConfigId, L_Const.resourceIndexOfAvatarTextureInHeroTpl.small)
    local tpl = _heroTpl:getTplById(heroConfigId)
    local elementId = _heroTpl:getElement(tpl)
    local elementTypeTpl = L_GameTpl:getElementTypeTpl()
    local bgIconPath = elementTypeTpl:getProfessionColor(elementTypeTpl:getTplById(elementId), L_Const.professionColorType.circle)
    self.bind.professionBg = bgIconPath
    local professionTpl = L_GameTpl:getProfessionTpl()
    local professionIcon = professionTpl:getIcon(professionTpl:getTplById(_heroTpl:getPosition(tpl)))
    local rarity = _heroTpl:getRarity(tpl)
    local rarityTpl = L_RarityTpl:getTplById(rarity)
    local colorCfg = L_RarityTpl:getColorCircle(rarityTpl)
    for id, _ in pairs(formationData) do
      if id == heroId then
        colorCfg = "#eaffaa"
      end
    end
    local _, color = C_ColorUtility.TryParseHtmlString(colorCfg)
    table.insert(tempData, {
      id = heroId,
      imgHead = heroHeadAvatarTexture,
      txtLevel = string.format("%02d", L_HeroStore:getHeroLevel(hero)),
      imgCarrer = professionIcon,
      carrerBg = bgIconPath,
      selected = k == self.heroIndex,
      qualityColor = color
    })
  end
  self.bind.listHeroHeads:clear()
  self.bind.listHeroHeads:insert_array(tempData)
  if self.heroIndex then
    self.bindComponents.panelHeroHeads:FocusItemIndex(self.heroIndex - 1)
  end
end

function this:refresh(options)
  local selectModuleType = L_Const.heroModuleType.Property
  local selectModuleParam
  for i = 1, #heroModuleTypeList do
    if self.modeController:checkModuleIsShow(heroModuleTypeList[i]) then
      selectModuleType = heroModuleTypeList[i]
      break
    end
  end
  if options.selectModuleType and self.modeController:checkModuleIsShow(options.selectModuleType) then
    selectModuleType = options.selectModuleType
    selectModuleParam = options.selectModuleParam
  end
  local moduleName = heroModuleType2ModuleName[selectModuleType]
  if moduleName ~= nil and self.bind.toggleModuleName == moduleName then
    return
  end
  self:onSelectionChange(selectModuleType, selectModuleParam)
end

function this:show()
  if not self.preOpenInit then
    self:initHeroTimeline(true)
  end
  self.preOpenInit = false
  self.lastCameraBlendStyle = C_CameraManager.GetMainCameraBrain().m_DefaultBlend.m_Style
  C_CameraManager.SetBrainBlendStyle(L_Const.blendStyle.cut)
  if self.isRefreshAvatar then
    self:playHeroVoice(self.modeController:getSelectConfigId(), self.currentModuleType)
    self.isRefreshAvatar = false
  end
end

function this:playHeroVoice(configId, moduleType)
  if self.options ~= nil and self.options.pageType ~= L_Const.heroPageType.SpritronPreviewMode then
    L_HeroVoiceManager:playHeroVoiceByConfigId(configId, moduleType)
  end
end

function this:hide()
  self.bind.bg = true
  L_HeroManager:disposeTimelineControl()
  if self.lastCameraBlendStyle ~= nil then
    C_CameraManager.SetBrainBlendStyle(self.lastCameraBlendStyle)
    self.lastCameraBlendStyle = nil
  end
end

function this:close(options)
  this.super.close(self, options)
  if self.callBack then
    self.callBack()
  end
  local timelineControl = L_HeroManager:getTimelineControl()
  timelineControl.onPlayTimelineAssetHandle = nil
  L_HeroManager:disposeTimelineControl()
  L_HeroVoiceManager:stopHeroVoice()
  self:destroyAllLocker()
  AzurWorld.heroMgr:UnregisterEvent(C_EHeroEvent.ESyncHeroServerData, self._ESyncHeroServerDataHandler)
  L_HeroStore:unListenCallFunc(L_HeroStore.event.setCurHeroGuid, self.onEvent_setCurHeroID)
  L_PlayerStore:unListenCallFunc(L_PlayerStore.event.refreshModAvatar, self.onEvent_refreshAvatar)
  L_HeroManager:removeListener(L_HeroManager.event.showHeroSelection, self.onShowHeroSelection, self)
  if self.frameSchedulerId then
    FrameScheduler.remove(self.frameSchedulerId)
  end
  self.frameSchedulerId = nil
end

function this:initHeroTimeline(isFirstInit)
  local heroId = self.modeController:getSelectConfigId()
  if not self.modeController:showTimeline() then
    return
  end
  local timelineControl = L_HeroManager:getTimelineControl()
  local hero = _heroTpl:getTplById(heroId)
  local path = L_Config:getPathByHash(hero.uiperform)
  local scenePath = L_Config:getPathByHash(hero.uibackground)
  local state, showHero = self:getTimelineStateAndShowHero()
  local timelineAssetName = timelineControl:getTimelineAssetName(state)
  timelineControl:asyncLoadTimelineAssets(path, timelineAssetName, scenePath, heroId, isFirstInit, function()
  end, function()
    self.bind.bg = false
    timelineControl:setAssetsActive(showHero)
    if showHero then
      timelineControl:playTimelineState(state, true, true)
    end
  end)
end

function this:getTimelineStateAndShowHero()
  local state = L_Const.heroTimelineState.Detail
  local showHero = true
  if self.bind.toggleModuleName then
    local module = self.modules.toggleModuleBar[self.bind.toggleModuleName]
    if module then
      state = module:getTimelineState() ~= L_Const.heroTimelineState.None and module:getTimelineState() or self.lastTimelineState
      showHero = module:getShowHeroAssets()
    end
  end
  return state, showHero
end

function this:playTimelineAndRefreshInteractable(toggleName)
  if not self.modeController:showTimeline() then
    return
  end
  local timelineControl = L_HeroManager:getTimelineControl()
  local state = L_Const.heroTimelineState.Detail
  local showHero = true
  if toggleName then
    local module = self.modules.toggleModuleBar[toggleName]
    if module then
      local moduleState = module:getTimelineState()
      if moduleState ~= L_Const.heroTimelineState.None or self.lastTimelineState ~= L_Const.heroTimelineState.None then
        state = moduleState
      end
      showHero = module:getShowHeroAssets()
    end
  end
  local lastShowHero = timelineControl.assetActive
  timelineControl:setAssetsActive(showHero)
  timelineControl:checkPlayTimelineState(state, showHero, lastShowHero)
end

function this:initModeController(options)
  if options.pageType then
    if options.pageType == L_Const.heroPageType.DetailMode then
      self.modeController = require("ui.pages.heroPanel.controller.heroDetailModeController").new()
    elseif options.pageType == L_Const.heroPageType.ListMode then
      self.modeController = require("ui.pages.heroPanel.controller.heroListModeController").new()
    elseif options.pageType == L_Const.heroPageType.PreviewMode then
      self.modeController = require("ui.pages.heroPanel.controller.heroPreviewModeController").new()
    elseif options.pageType == L_Const.heroPageType.HandBookMode then
      self.modeController = require("ui.pages.heroPanel.controller.heroHandBookPreviewModeController").new()
    elseif options.pageType == L_Const.heroPageType.SpritronPreviewMode then
      self.modeController = require("ui.pages.heroPanel.controller.spiritronPreviewModeController").new()
      self.modeController._spiritronId = options.spiritronId
    end
  end
  if self.modeController == nil then
    self.modeController = require("ui.pages.HeroPanel.controller.heroListModeController").new()
  end
end

function this:refreshModuleTypeArea()
  for i, toggleName in pairs(heroModuleType2ToggleName) do
    local isShow = self.modeController:checkModuleIsShow(i)
    self.bind[toggleName] = isShow
  end
end

function this:onEvent_refreshAvatar()
  self.isRefreshAvatar = true
  for k, v in ipairs(self.heroGuidList) do
    if v == L_HeroStore:getDefaultHeroGuid() then
      self.bind.listHeroHeads:change(k, {})
      return
    end
  end
end

function this:onEvent_refreshHero(enum, varList)
  local hero = varList:GetObject(0)
  if L_HeroStore:getHeroGuid(hero) ~= self.modeController:getSelectGuid() then
    return
  end
  if self.bind.toggleModuleName == "petModule" then
    self.modules.toggleModuleBar.petModule:refresh()
  end
  self:refreshHeroHead(L_HeroStore:getHeroGuid(hero), nil)
end

function this:onEvent_setCurHeroID(newHeroID, oldHeroID)
  self.heroIndex = self:getHeroIndex()
  self:initData()
  self:initHeroTimeline(false)
  self:refreshHeroHead(newHeroID, oldHeroID)
end

function this:refreshHeroHead(newHeroID, oldHeroID)
  if self.modeController:isPreviewMode() then
    return
  end
  for k, v in ipairs(self.heroGuidList) do
    local heroId = v
    if heroId == newHeroID or heroId == oldHeroID then
      local heroData = self.modeController:getHero(heroId)
      local heroItem = L_ItemManager:parseHeroItem(L_HeroStore:getHeroConfigId(heroData))
      local heroHeadAvatarTexture = L_GameUtil.getAvatarTexturePath(L_HeroStore:getHeroConfigId(heroData), L_Const.resourceIndexOfAvatarTextureInHeroTpl.small)
      self.bind.listHeroHeads:change(k, {
        id = heroId,
        imgHead = heroHeadAvatarTexture,
        txtLevel = string.format("%02d", L_HeroStore:getHeroLevel(heroData)),
        colorCircle = heroItem.qualityColor,
        selected = heroId == newHeroID
      })
    end
  end
end

function this:initSystem()
  self.systemToTrans = {
    [L_SystemConst.enum.heroTalent] = {
      self.bindComponents.transTalent
    },
    [L_SystemConst.enum.spiritron] = {
      self.bindComponents.transSpiritron
    },
    [L_SystemConst.enum.star] = {
      self.bindComponents.transStar
    },
    [L_SystemConst.enum.accessory] = {
      self.bindComponents.transAccessory
    },
    [L_SystemConst.enum.heroData] = {
      self.bindComponents.transData
    }
  }
  for systemId, v in pairs(self.systemToTrans) do
    v.locker = L_SystemUnlockManager:tryGenerateLocker(systemId)
    if v.locker then
      self:refreshSystem(systemId, false)
      v.locker:setCallback(self.refreshSystem, self, self.gameObject)
    end
  end
end

function this:destroyAllLocker()
  for _, v in pairs(self.systemToTrans) do
    local locker = v.locker
    if locker then
      L_SystemUnlockManager:removeLocker(locker)
    end
  end
end

function this:refreshSystem(systemId, isUnlock)
  local node = self.systemToTrans[systemId]
  local locker = node.locker
  for _, v in ipairs(node) do
    local isNeedShow = locker:tryShowOrHide(v, isUnlock)
    if isNeedShow then
      local lock = v:Find("Background/lock")
      local unlock = v:Find("Background/unlock")
      if lock then
        lock.gameObject:ActiveTrans(not isUnlock)
      end
      if unlock then
        unlock.gameObject:ActiveTrans(isUnlock)
      end
    end
  end
end

local MODULE_SYSTEM = {
  [L_Const.heroModuleType.Talent] = L_SystemConst.enum.heroTalent,
  [L_Const.heroModuleType.Star] = L_SystemConst.enum.star,
  [L_Const.heroModuleType.Spiritron] = L_SystemConst.enum.spiritron,
  [L_Const.heroModuleType.Accessory] = L_SystemConst.enum.accessory,
  [L_Const.heroModuleType.Data] = L_SystemConst.enum.heroData
}

function this:initHeroLock()
  if self.modeController:isPreviewMode() then
    local currHeroConfigId = self.modeController:getSelectConfigId()
    if L_HeroStore:getHasHero(currHeroConfigId) then
      self.bind.lockActive = false
    else
      self.bind.lockActive = true
    end
  else
    self.bind.lockActive = false
  end
end

function this:initTogglesRed()
  if self.modeController:isPreviewMode() then
    self.bindComponents.redotStar.gameObject:SetActive(false)
    self.bindComponents.redotJewel.gameObject:SetActive(false)
    self.bindComponents.redotHeroInfo.gameObject:SetActive(false)
  else
    local selectGuid = self.modeController:getSelectGuid()
    L_ReddotManager:clearNew(L_ReddotManager.DotDef.HeroNew, selectGuid)
    local reddotDef = L_ReddotManager.DotDef
    L_ReddotManager:registerReddot(self.bindComponents.redotStar, string.format(reddotDef.HeroStar, selectGuid))
    L_ReddotManager:registerReddot(self.bindComponents.redotJewel, string.format(reddotDef.HeroAcc, selectGuid))
    L_ReddotManager:registerReddot(self.bindComponents.redotHeroInfo, string.format(reddotDef.HeroInfo, selectGuid))
    L_ReddotManager:registerReddot(self.bindComponents.redotTalent, string.format(reddotDef.HeroTalent, selectGuid))
  end
end

function this:initData()
  self:initTogglesRed()
  self:playHeroVoice(self.modeController:getSelectConfigId(), self.currentModuleType)
  local curModule = self.modules.toggleModuleBar[self.bind.toggleModuleName]
  if curModule ~= nil then
    curModule:initPage()
  end
end

function this:onTogglePreviewChange(isMaxLevel)
  if not self.modeController:isPreviewMode() then
    return
  end
  local lastIsMax = self.modeController:getIsMaxLevel()
  self.modeController:setisMaxLevel(isMaxLevel)
  if self.bind.toggleModuleName == heroModuleType2ModuleName[L_Const.heroModuleType.Property] and isMaxLevel ~= lastIsMax then
    self.modules.toggleModuleBar[self.bind.toggleModuleName]:playTotalPreviewAnimation(isMaxLevel)
    FrameScheduler.add(function()
      self.modules.toggleModuleBar[self.bind.toggleModuleName]:initPage()
    end, 1)
  else
    self.modules.toggleModuleBar[self.bind.toggleModuleName]:initPage()
  end
end

function this:onSelectionChange(moduleType, params)
  self.bind.ringActive = moduleShowRing[moduleType] == true
  local moduleName = heroModuleType2ModuleName[moduleType]
  if moduleName == nil then
    printf("hero page moduleName error moduleType is not in heroModuleType2ModuleName")
    return
  end
  local systemId = MODULE_SYSTEM[moduleType]
  if systemId then
    local result = not L_SystemBreakManager:checkBanSystemAndTip(systemId) and L_SystemUnlockManager:checkAndTip(systemId)
    if not result then
      return
    end
  end
  local lastModule = self.modules.toggleModuleBar[heroModuleType2ModuleName[self.currentModuleType]]
  if self.currentModuleType == "Property" then
    self.modules.toggleModuleBar.moduleProperty:playSwitchAnimator("LevelToBreak")
    self.bind.ringActive = true
    self.bindComponents.ringAnim:Play("Switch")
    Timer.once(0.67, function()
      self.bind.ringActive = false
    end, self)
    self:playHeroVoice(self.modeController:getSelectConfigId(), moduleType)
    self:initPage(lastModule, moduleName, params)
    self.currentModuleType = moduleType
    self:triggerSelection(moduleType)
    self:refreshCanChangeHero(true)
    self:playTimelineAndRefreshInteractable(moduleName)
    self:playHeroVoice(self.modeController:getSelectConfigId(), moduleType)
    self.bind.previewLevelToggles = self.modeController:checkShowPreviewLevel(moduleType)
  else
    self.currentModuleType = moduleType
    self:triggerSelection(moduleType)
    self:refreshCanChangeHero(true)
    self:playTimelineAndRefreshInteractable(moduleName)
    self:playHeroVoice(self.modeController:getSelectConfigId(), moduleType)
    self:initPage(lastModule, moduleName, params)
    self.bind.previewLevelToggles = self.modeController:checkShowPreviewLevel(moduleType)
  end
end

function this:initPage(lastModule, moduleName, params)
  if lastModule and lastModule.closePage then
    lastModule:closePage()
  end
  self.bind.toggleModuleName = moduleName
  self.modules.toggleModuleBar[moduleName]:initPage(params)
  if self.modules.toggleModuleBar[moduleName].playChangeEffect ~= nil then
    self.modules.toggleModuleBar[moduleName]:playChangeEffect()
  end
end

function this:triggerSelection(moduleType)
  if self.curSelectButton then
    self:selectButtonIsOn(self.curSelectButton, false)
  end
  local trans = self.bindComponents["trans" .. moduleType]
  self:selectButtonIsOn(trans, true)
  self.curSelectButton = trans
end

function this:selectButtonIsOn(trans, isOn)
  trans:Find("Checkmark").gameObject:ActiveTrans(isOn)
  trans:Find("Background").gameObject:ActiveTrans(not isOn)
end

function this:refreshCanChangeHero(canShow)
  local canChangeHero = canShow
  canChangeHero = canChangeHero and #self.heroGuidList > 1
  canChangeHero = canChangeHero and self.modeController:checkCanChangeHero()
  self.bind.lastAndNext = canChangeHero
end

function this:setDownBg(bool)
  bool = bool and self.modeController:checkCanShowDownBG()
  self.bind.downBg = bool
  self:refreshCanChangeHero(bool)
end

function this:setCommonTop(bool)
  self.bind.go_commonTop = bool
end

function this:setMaskActive(active)
  self.bind.mask = active
end

function this:escHandle()
  if self.modules.toggleModuleBar[self.bind.toggleModuleName].getCanClose then
    local canClose = self.modules.toggleModuleBar[self.bind.toggleModuleName]:getCanClose()
    if not canClose then
      return
    end
  end
  self:dealBack()
end

function this:onShowHeroSelection(data)
  if data.selectionType == L_Const.heroModuleType.Talent then
    self:setDownBg(true)
    self:refreshCanChangeHero(true)
    self:setCommonTopData()
  end
  self:onSelectionChange(data.selectionType, data.jumpData)
end

function this:setBlurActive(isBlur)
  self.bindComponents.blur.enabled = isBlur
end

function this:setBgToggles(isActiveBg)
  self.bind.topbg = isActiveBg
  self.bind.downBg = isActiveBg
  L_TopBarManager:setTopBarVisible(isActiveBg)
  self.bind.listHeroActive = isActiveBg
end

return this
