local this = class("mapManager")
local mapSandwich = {pageBigMap = 1, pageWorldAreaMap = 2}
local _worldMapTpl = L_GameTpl:getWorldMapTpl()
local _worldPointTpl = L_GameTpl:getWorldBorthposTpl()
local _worldAreaTpl = L_GameTpl:getWorldAreaTpl()
local _areaTpl = L_GameTpl:getAreaTpl()
local _mapNodeTpl = L_GameTpl:getMapNodeTpl()
local _filterMarkTpl = L_GameTpl:getWorldFilterMarkTpl()
local _fishPondTpl = L_GameTpl:getFishPondTpl()
local _fishGroupTpl = L_GameTpl:getFishGroupTpl()
local _staminaChestDropTpl = L_GameTpl:getStaminaChestDropTpl()
local _worldSpawnerTpl = L_GameTpl:getWorldSpawnerTpl()
local _worldCityTpl = L_GameTpl:getWorldCityTpl()
local _worldFilterTpl = L_GameTpl:getWorldFilterTpl()
local _petTpl = L_GameTpl:getPetTpl()
local _worldCollectingTypeTpl = L_GameTpl:getWorldCollectingTypeTpl()
local _worldCollectionTpl = L_GameTpl:getWorldCollectingTpl()

function this:ctor()
  self.mapKeyPair = {
    [L_MapConst.mapSievingType.npc] = self.getAllNpcNode,
    [L_MapConst.mapSievingType.transfer] = self.getAllTransferNode,
    [L_MapConst.mapSievingType.collection] = self.getAllCollectionNode,
    [L_MapConst.mapSievingType.task] = self.getAllTaskNode,
    [L_MapConst.mapSievingType.taskNpc] = self.getAllTaskNpcNode,
    [L_MapConst.mapSievingType.dynamicDungeon] = self.getAllDynamicDungeonNode,
    [L_MapConst.mapSievingType.homeArea] = self.getAllHomeAreaNode,
    [L_MapConst.mapSievingType.specialPet] = self.getAllSpecialPetNode,
    [L_MapConst.mapSievingType.homeTrace] = self.getAllHomeTraceNode,
    [L_MapConst.mapSievingType.mythicalPet] = self.getAllMythicalPetNode,
    [L_MapConst.mapSievingType.wildBuffBuild] = self.getAllWildBuffBuildNode,
    [L_MapConst.mapSievingType.mapCollectionItem] = self.getCurMapCollectionItemNode
  }
  self.canTelePortNode = {
    [L_MapConst.mapSievingType.transfer] = 1,
    [L_MapConst.mapSievingType.dungeon] = 1,
    [L_MapConst.mapSievingType.dungeonBoss] = 1,
    [L_MapConst.mapSievingType.entrustTaskNpc] = 1
  }
  self.noMaskNode = {
    [L_MapConst.mapSievingType.transfer] = 1,
    [L_MapConst.mapSievingType.task] = 1,
    [L_MapConst.mapSievingType.mythicalPet] = 1
  }
  self.petCatalogMapPair = {
    [L_MapConst.mapSievingType.kiboHabitat] = self.getCurKiBoHabitatNode
  }
end

function this:createMapBuilder(mapData)
  return require("ui.manager.map.builder.mapBuilder").new(mapData)
end

function this:createMapNode(nodeType)
  if L_MapConst.SpecialMapNodeRes[nodeType] then
    return require(L_MapConst.SpecialMapNodeRes[nodeType]).new(nodeType)
  else
    return require("ui.manager.map.node.mapNode").new(nodeType)
  end
end

function this:createMapData(mapAreaId, isMini)
  return require("ui.manager.map.builder.mapBuilderData").new(mapAreaId, isMini)
end

function this:getCanTelePortNodeEnum()
  return self.canTelePortNode
end

function this:getMapNodeList(sceneId, filterNode, isBigMap)
  sceneId = sceneId or AzurWorldInstance.CurWorldId
  local nodeList = {}
  for key, func in pairs(self.mapKeyPair) do
    if filterNode and filterNode[key] then
    else
      func(self, sceneId, nodeList, isBigMap)
    end
  end
  return nodeList
end

function this:getMapNodeListByType(sceneId, type, isBigMap)
  sceneId = sceneId or AzurWorldInstance.CurWorldId
  local nodeList = {}
  if self.mapKeyPair[type] then
    self.mapKeyPair[type](self, sceneId, nodeList, isBigMap)
  end
  return nodeList
end

function this:getMapNodeDic(sceneId, isBigMap)
  sceneId = sceneId or AzurWorldInstance.CurWorldId
  local dic = {}
  for key, func in pairs(self.mapKeyPair) do
    dic[key] = func(self, sceneId, nil, isBigMap)
  end
  return dic
end

function this:getMapAreaBlockList(sceneId, nodeList)
  sceneId = sceneId or AzurWorldInstance.CurWorldId
  nodeList = nodeList or {}
  local list = {}
  for i, v in pairs(_worldAreaTpl:getAllArea(sceneId)) do
    table.insert(list, v)
  end
  if #list <= 1 then
    return {}
  end
  table.sort(list, function(a, b)
    return a.id < b.id
  end)
  table.remove(list, 1)
  local allAreaList = list
  for _, v in pairs(allAreaList) do
    local id = _worldAreaTpl:getId(v)
    local type = L_MapConst.mapSievingType.areaBlock
    local node = self:createMapNode(type)
    node.id = id
    node.configPos = _worldAreaTpl:getAreaPos(v, true)
    node.name = _worldAreaTpl:getName(v)
    node.sceneId = sceneId
    table.insert(nodeList, node)
  end
  if #nodeList <= 1 then
    return {}
  end
  return nodeList
end

function this:getMiniAreaBlockList(sceneId, nodeList)
  sceneId = sceneId or AzurWorldInstance.CurWorldId
  nodeList = nodeList or {}
  local allMiniAreaBlock = _worldPointTpl:getAllTplByCityId(sceneId, 3)
  for _, tpl in pairs(allMiniAreaBlock) do
    local type = L_MapConst.mapSievingType.miniAreaBlock
    local node = self:createMapNode(type)
    node.id = _worldPointTpl:getId(tpl)
    node.configPos = _worldPointTpl:getPosition(tpl)
    node.name = _worldPointTpl:getName(tpl)
    node.sceneId = sceneId
    table.insert(nodeList, node)
  end
  if #nodeList <= 1 then
    return {}
  end
  return nodeList
end

function this:getMapAreaMask(sceneId, nodeList)
  sceneId = sceneId or AzurWorldInstance.CurWorldId
  nodeList = nodeList or {}
  local list = _filterMarkTpl:getTplListByWorldId(sceneId, L_MapConst.mapSievingType.transfer)
  for _, tpl in ipairs(list) do
    local wpTpl = _worldMapTpl:getTplById(sceneId, _filterMarkTpl:getWorldmapId(tpl))
    if wpTpl and not string.isEmpty(_filterMarkTpl:getMapMaskIcon(tpl)) then
      local node = self:createMapNode(L_MapConst.mapSievingType.areaMask)
      local birthPosId = _filterMarkTpl:getPosId(tpl)
      node.id = birthPosId
      node.configPos = _worldMapTpl:getPosition(wpTpl)
      node.name = ""
      node.iconPath = _filterMarkTpl:getMapMaskIcon(tpl)
      node.order = _filterMarkTpl:getParam(tpl)
      node.sceneId = sceneId
      node.isUnLock = L_SceneStore:getPointIsUnlock(birthPosId)
      node.cityId = _filterMarkTpl:getWorldId(tpl)
      node.worldMapId = _filterMarkTpl:getWorldmapId(tpl)
      table.insert(nodeList, node)
    end
  end
  return nodeList
end

function this:getMapAreaBoundary(areaId, nodeList)
  nodeList = nodeList or {}
  local tpl = _worldAreaTpl:getTplById(areaId)
  if tpl then
    local boundary = _worldAreaTpl:getMapBoundary(tpl)
    if string.isEmpty(boundary) then
      return {}
    end
    local node = self:createMapNode(L_MapConst.mapSievingType.areaBoundary)
    node.id = areaId
    node.iconPath = boundary
    table.insert(nodeList, node)
    return nodeList
  else
    return {}
  end
end

function this:getSelfNodeList(sceneId, nodeList)
  sceneId = sceneId or AzurWorldInstance.CurWorldId
  nodeList = nodeList or {}
  local curSceneAreaList = _worldAreaTpl:getCurSceneAreaList(sceneId)
  if table.isEmpty(curSceneAreaList) then
    return {}
  end
  local mapAreaId = _worldAreaTpl:getId(curSceneAreaList[1])
  local allMySelfNode = L_MapStore:getSelfNodeInfo(mapAreaId)
  for _, v in pairs(allMySelfNode) do
    local type = L_MapConst.mapSievingType.selfNode
    local node = self:createMapNode(type)
    node.id = v.guid
    node.iconPath = _mapNodeTpl:getIcon(_mapNodeTpl:getTplById(v.markId))
    node.configPos = L_Vector3.new(v.pos_x, v.pos_y, v.pos_z)
    node.name = v.notes or L_WordsTpl:getValue("ui_signPiont")
    node.sceneId = sceneId
    node.markId = v.markId
    table.insert(nodeList, node)
  end
  if #nodeList <= 1 then
    return {}
  end
  return nodeList
end

function this:getAllNpcNode(sceneId, nodeList)
  nodeList = nodeList or {}
  local list = _filterMarkTpl:getTplListByWorldId(sceneId)
  for _, tpl in pairs(list) do
    local node
    local markType = _filterMarkTpl:getMarkType(tpl)
    if markType == L_MapConst.mapSievingType.transfer or markType == L_MapConst.mapSievingType.dynamicDungeon or markType == L_MapConst.mapSievingType.sceneBorderTransfer or markType == L_MapConst.mapSievingType.collection or markType == L_MapConst.mapSievingType.homeArea or markType == L_MapConst.mapSievingType.specialPet or markType == L_MapConst.mapSievingType.homeTrace or markType == L_MapConst.mapSievingType.mythicalPet then
    else
      local wpTpl
      node = self:createMapNode(markType)
      wpTpl = _worldMapTpl:getTplById(sceneId, _filterMarkTpl:getWorldmapId(tpl))
      if wpTpl then
        local birthPosId = _filterMarkTpl:getPosId(tpl)
        if math.isEmpty(birthPosId) then
          node.id = _worldMapTpl:getId(wpTpl)
        else
          node.birthPosId = birthPosId
          node.id = birthPosId
          local birthPosTpl = _worldPointTpl:getTplById(birthPosId)
          if not birthPosTpl then
            errorf(string.format("worldFilterMark\232\161\168\228\184\173id\228\184\186%s\231\154\132posId:%s\230\156\137\233\151\174\233\162\152", _filterMarkTpl:getId(tpl), birthPosId))
            node.isUnLock = false
          else
            node.isUnLock = L_SceneStore:getPointIsUnlock(birthPosId)
          end
        end
        node.configPos = _worldMapTpl:getPosition(wpTpl)
        node.iconPath = _filterMarkTpl:getIcon(tpl)
        if not string.isEmpty(_filterMarkTpl:getIconBg(tpl)) then
          node.iconBg = _filterMarkTpl:getIconBg(tpl)
        end
        node.filterMarkId = _filterMarkTpl:getId(tpl)
        node.name = _filterMarkTpl:getName(tpl)
        node.desc = _filterMarkTpl:getDes(tpl)
        node.sceneId = sceneId
        node.rewardShow = _filterMarkTpl:getRewardShow(tpl)
        node.param = _filterMarkTpl:getParam(tpl)
        if markType == L_MapConst.mapSievingType.entrustTaskNpc then
          node.iconBgResize = true
        end
        table.insert(nodeList, node)
      end
    end
  end
  return nodeList
end

function this:getAllDynamicDungeonNode(sceneId, nodeList)
  nodeList = nodeList or {}
  local list = _filterMarkTpl:getTplListByWorldId(sceneId, L_MapConst.mapSievingType.dynamicDungeon)
  for _, tpl in pairs(list) do
    local worldMapId = _filterMarkTpl:getWorldmapId(tpl)
    local wpTpl = _worldMapTpl:getTplById(sceneId, worldMapId)
    if wpTpl then
      local node = self:createMapNode(L_MapConst.mapSievingType.dynamicDungeon)
      node.id = worldMapId
      node.configPos = _worldMapTpl:getPosition(wpTpl)
      node.desc = _filterMarkTpl:getDes(tpl)
      node.filterMarkId = _filterMarkTpl:getId(tpl)
      node.iconPath = _filterMarkTpl:getIcon(tpl)
      node.name = _filterMarkTpl:getName(tpl)
      node.iconBg = _filterMarkTpl:getIconBg(tpl)
      node.rewardShow = _filterMarkTpl:getRewardShow(tpl)
      node.sceneId = sceneId
      table.insert(nodeList, node)
    end
  end
  return nodeList
end

function this:getAllSceneBorderTransferNode(sceneId, nodeList)
  nodeList = nodeList or {}
  local list = _filterMarkTpl:getTplListByWorldId(sceneId, L_MapConst.mapSievingType.sceneBorderTransfer)
  for _, tpl in ipairs(list) do
    local wpTpl = _worldMapTpl:getTplById(sceneId, _filterMarkTpl:getWorldmapId(tpl))
    if wpTpl then
      local node = self:createMapNode(L_MapConst.mapSievingType.sceneBorderTransfer)
      node.id = _worldMapTpl:getId(wpTpl)
      node.configPos = _worldMapTpl:getPosition(wpTpl)
      node:setData(_filterMarkTpl:getId(tpl))
      table.insert(nodeList, node)
    end
  end
  return nodeList
end

function this:getAllTransferNode(sceneId, nodeList)
  nodeList = nodeList or {}
  local list = _filterMarkTpl:getTplListByWorldId(sceneId, L_MapConst.mapSievingType.transfer)
  for _, tpl in ipairs(list) do
    local wpTpl = _worldMapTpl:getTplById(sceneId, _filterMarkTpl:getWorldmapId(tpl))
    if wpTpl then
      local birthPosId = _filterMarkTpl:getPosId(tpl)
      local node = self:createMapNode(L_MapConst.mapSievingType.transfer)
      node.id = birthPosId
      node.iconPath = _filterMarkTpl:getIcon(tpl)
      node.name = _filterMarkTpl:getName(tpl)
      node.desc = _filterMarkTpl:getDes(tpl)
      node.filterMarkId = _filterMarkTpl:getId(tpl)
      node.sceneId = sceneId
      node.worldMapId = _filterMarkTpl:getWorldmapId(tpl)
      node.isUnLock = L_SceneStore:getPointIsUnlock(birthPosId)
      node.birthPosId = birthPosId
      node.configPos = _worldMapTpl:getPosition(wpTpl)
      table.insert(nodeList, node)
    end
  end
  return nodeList
end

function this:getVoidTransferNode(sceneId, nodeList)
  nodeList = nodeList or {}
  local iconTransfer = _worldSpawnerTpl:getTransferIcon()
  local allShowPoint = _worldPointTpl:getAllTplByCityId(sceneId, L_Const.worldPointType.transfer)
  for _, tpl in pairs(allShowPoint) do
    if not _worldPointTpl:getIsLockPoint(tpl) then
      local node = self:createMapNode(L_MapConst.mapSievingType.transfer)
      node.id = _worldPointTpl:getId(tpl)
      node.configPos = _worldPointTpl:getPosition(tpl)
      node.iconPath = iconTransfer
      node.name = _worldPointTpl:getName(tpl)
      node.desc = _worldPointTpl:getName(tpl)
      node.sceneId = sceneId
      table.insert(nodeList, node)
    end
  end
  return nodeList
end

function this:getAllCollectionNode(sceneId, nodeList)
  nodeList = nodeList or {}
  local objIds = L_CollectionManager:getCollectionObjByScene(sceneId)
  for _, v in pairs(objIds) do
    local tpl_obj = _worldMapTpl:getTplById(sceneId, v.objId)
    local filterMarkId = _worldMapTpl:getFilterMark(tpl_obj)
    if not math.isEmpty(filterMarkId) then
      if table.isEmpty(_filterMarkTpl:getTplById(filterMarkId)) then
        errorf("\229\189\147\229\137\141\229\156\186\230\153\175" .. sceneId .. " \233\135\135\233\155\134\229\187\186\231\173\145id " .. v.objId .. "\229\175\185\229\186\148\231\154\132filterMarkId" .. filterMarkId .. "\228\184\141\229\173\152\229\156\168")
      else
        local node = self:createMapNode(L_MapConst.mapSievingType.collection)
        node.id = v.objId
        node.filterMarkId = filterMarkId
        node.configPos = _worldMapTpl:getPosition(tpl_obj)
        node.sceneId = sceneId
        node.name = _filterMarkTpl:getName(_filterMarkTpl:getTplById(filterMarkId))
        node.configData = tpl_obj
        node:setCollectionId(v.collectId)
        table.insert(nodeList, node)
      end
    end
  end
  return nodeList
end

function this:getAllWildBuffBuildNode(sceneId, nodeList)
  nodeList = nodeList or {}
  local objIds = L_CollectionManager:getWildBuffBuildObjByScene(sceneId)
  for _, v in pairs(objIds) do
    local tpl_obj = _worldMapTpl:getTplById(sceneId, v.objId)
    local filterMarkId = _worldMapTpl:getFilterMark(tpl_obj)
    if not math.isEmpty(filterMarkId) then
      if table.isEmpty(_filterMarkTpl:getTplById(filterMarkId)) then
        errorf("\229\189\147\229\137\141\229\156\186\230\153\175" .. sceneId .. " \229\164\167\228\184\150\231\149\140\233\135\142\229\164\150Buff\229\187\186\231\173\145id " .. v.objId .. "\229\175\185\229\186\148\231\154\132filterMarkId" .. filterMarkId .. "\228\184\141\229\173\152\229\156\168")
      else
        local node = self:createMapNode(L_MapConst.mapSievingType.wildBuffBuild)
        node.id = v.objId
        node.filterMarkId = filterMarkId
        node.configPos = _worldMapTpl:getPosition(tpl_obj)
        node.sceneId = sceneId
        node.name = _filterMarkTpl:getName(_filterMarkTpl:getTplById(filterMarkId))
        node.configData = tpl_obj
        node:setCollectionId(v.collectId)
        table.insert(nodeList, node)
      end
    end
  end
  return nodeList
end

function this:getAllTaskNode(sceneId, nodeList, isBigMap)
  nodeList = nodeList or {}
  local traceInfos = C_TaskManager.GetTaskTraceInfosBySceneId(sceneId, isBigMap)
  local taskTpl = L_GameTpl:getTaskTpl()
  for i = 0, traceInfos.Count - 1 do
    local taskId = traceInfos[i].TaskId
    local tpl = taskTpl:getTplById(taskId)
    if isBigMap or traceInfos[i]:CanTrace() then
      local taskEntityPos, res = traceInfos[i]:GetPosition(false, sceneId)
      if res then
        local configPos = L_Vector3.new(taskEntityPos.x, taskEntityPos.y, taskEntityPos.z)
        local node = self:createMapNode(L_MapConst.mapSievingType.task)
        node.id = taskId
        node.configPos = configPos
        node.desc = taskTpl:getDesc(tpl) or ""
        node.name = taskTpl:getName(tpl) or ""
        node.sceneId = sceneId
        node.iconPath = taskTpl:getMapTaskIcon(tpl)
        node.iconBg = taskTpl:getMapTaskIconBg(tpl)
        node.iconBgResize = true
        local data = traceInfos[i].TriggerData
        if data.isNeedShowRange then
          node.showRange = data.showRange
          local triggerRange = 0 < data.triggerRange and data.triggerRange or data.showRange
          node.triggerRangeSqr = triggerRange * triggerRange
        end
        table.insert(nodeList, node)
      end
    end
  end
  return nodeList
end

function this:getAllTaskNpcNode(sceneId, nodeList, isBigMap)
  nodeList = nodeList or {}
  local list = C_TaskManager.GetStartNpcIdList()
  if list.Count > 0 then
    for i = 0, list.Count - 1 do
      local taskGetNpc = list[i]
      if taskGetNpc.sceneId == sceneId then
        local taskId = taskGetNpc.taskId
        local taskTpl = L_GameTpl:getTaskTpl()
        local tpl = taskTpl:getTplById(taskId)
        if tpl and taskTpl:getFilter(tpl) == 1 and taskTpl:getMapShow(tpl) == 1 then
          local taskType = taskTpl:getType(tpl)
          if not isBigMap or taskType ~= L_Const.taskType.random then
            local pos = L_TaskManager:getPosByTaskGetNpc(taskGetNpc)
            if pos then
              local node = self:createMapNode(L_MapConst.mapSievingType.taskNpc)
              node.id = taskGetNpc.npcId
              node.configPos = pos
              node.name = taskTpl:getName(tpl) or ""
              node.desc = taskTpl:getDesc(tpl) or ""
              node.sceneId = sceneId
              if taskType == L_Const.taskType.random then
                node.iconPath = "UI/Atlas/MapNode/tex_icon_mapnode_zhixian.png"
                node.iconBg = taskTpl:getMapTaskIconBg(tpl)
                node.iconBgResize = true
              else
                node.iconPath = taskTpl:getMapTaskIcon(tpl)
                node.iconBg = taskTpl:getMapTaskIconBg(tpl)
                node.iconBgResize = true
              end
              table.insert(nodeList, node)
            end
          end
        end
      end
    end
  end
  return nodeList
end

function this:getAllHomeAreaNode(sceneId, nodeList)
  nodeList = nodeList or {}
  local cityTpl = L_GameTpl:getWorldCityTpl()
  local worldCityTpl = cityTpl:getTplById(sceneId)
  if C_TDWorldCityTable.GetWorldType(sceneId) == C_EWorldType.Home then
    local list = _filterMarkTpl:getTplListByWorldId(sceneId, L_MapConst.mapSievingType.homeArea)
    for _, tpl in ipairs(list) do
      local wpTpl = _worldMapTpl:getTplById(sceneId, _filterMarkTpl:getWorldmapId(tpl))
      if wpTpl then
        local node = self:createMapNode(L_MapConst.mapSievingType.homeArea)
        node.id = _filterMarkTpl:getId(tpl)
        node.name = _filterMarkTpl:getName(tpl)
        node.desc = _filterMarkTpl:getDes(tpl)
        node.filterMarkId = _filterMarkTpl:getId(tpl)
        node.entityId = _filterMarkTpl:getWorldmapId(tpl)
        node.iconPath = _filterMarkTpl:getIcon(tpl)
        node.configPos = _worldMapTpl:getPosition(wpTpl)
        table.insert(nodeList, node)
      end
    end
  end
  return nodeList
end

function this:getAllSpecialPetNode(sceneId, nodeList)
  nodeList = nodeList or {}
  for _, v in pairs(L_MapStore.specialMonsters) do
    if sceneId == v.map_id then
      local wpTpl = _worldMapTpl:getTplById(sceneId, v.obj_id)
      if wpTpl then
        local node = self:createMapNode(L_MapConst.mapSievingType.specialPet)
        node.id = _worldMapTpl:getId(wpTpl)
        node.configPos = _worldMapTpl:getPosition(wpTpl)
        local tpl
        local tplList = _filterMarkTpl:getTplListByWorldId(0, L_MapConst.mapSievingType.specialPet)
        for _, v1 in pairs(tplList) do
          if _filterMarkTpl:getParam(v1) == v.special_type then
            tpl = v1
            break
          end
        end
        node.iconPath = _filterMarkTpl:getIcon(tpl)
        if not string.isEmpty(_filterMarkTpl:getIconBg(tpl)) then
          node.iconBg = _filterMarkTpl:getIconBg(tpl)
        end
        node.filterMarkId = _filterMarkTpl:getId(tpl)
        node.name = _filterMarkTpl:getName(tpl)
        node.desc = _filterMarkTpl:getDes(tpl)
        node.sceneId = sceneId
        node.rewardShow = _filterMarkTpl:getRewardShow(tpl)
        node.param = _filterMarkTpl:getParam(tpl)
        table.insert(nodeList, node)
      end
    end
  end
  return nodeList
end

function this:getAllHomeTraceNode(sceneId, nodeList)
  nodeList = nodeList or {}
  local traceInfo = L_MapStore:getCurNodeTargetTracing()
  if not traceInfo or traceInfo.nodeType ~= L_MapConst.mapSievingType.homeTrace then
    return nodeList
  end
  local node = self:createMapNode(L_MapConst.mapSievingType.homeTrace)
  node.id = traceInfo.id
  node.configPos = traceInfo.pos
  local _filterMarkCfg = _filterMarkTpl:getTplById(traceInfo.id)
  node.iconPath = _filterMarkTpl:getIcon(_filterMarkCfg)
  if not string.isEmpty(_filterMarkTpl:getIconBg(_filterMarkCfg)) then
    node.iconBg = _filterMarkTpl:getIconBg(_filterMarkCfg)
  end
  node.filterMarkId = _filterMarkTpl:getId(_filterMarkCfg)
  node.name = traceInfo.name
  node.desc = traceInfo.desc
  node.sceneId = traceInfo.sceneId
  node.rewardShow = _filterMarkTpl:getRewardShow(_filterMarkCfg)
  node.param = _filterMarkTpl:getParam(_filterMarkCfg)
  table.insert(nodeList, node)
  return nodeList
end

function this:getAllMythicalPetNode(sceneId, nodeList)
  nodeList = nodeList or {}
  for _, v in pairs(L_MapStore.mythicalPets) do
    if v.sceneId == sceneId then
      local node = self:createMapNode(L_MapConst.mapSievingType.mythicalPet)
      node.id = v.id
      node.configPos = v.pos
      local _filterMarkCfg = _filterMarkTpl:getTplById(v.id)
      node.iconPath = _filterMarkTpl:getIcon(_filterMarkCfg)
      if not string.isEmpty(_filterMarkTpl:getIconBg(_filterMarkCfg)) then
        node.iconBg = _filterMarkTpl:getIconBg(_filterMarkCfg)
      end
      node.filterMarkId = _filterMarkTpl:getId(_filterMarkCfg)
      node.name = _filterMarkTpl:getName(_filterMarkCfg)
      node.desc = _filterMarkTpl:getDes(_filterMarkCfg)
      node.sceneId = v.sceneId
      node.rewardShow = _filterMarkTpl:getRewardShow(_filterMarkCfg)
      node.param = _filterMarkTpl:getParam(_filterMarkCfg)
      table.insert(nodeList, node)
    end
  end
  return nodeList
end

function this:getCurMapCollectionItemNode(sceneId, worldCollectionId)
  local tpl = _worldCollectionTpl:getTplById(worldCollectionId)
  local nodeList = {}
  if tpl then
    local spawnerIds = _worldCollectionTpl:getSpawnerId(tpl)
    local tplData = L_ItemTplManager:getItemConfig(_worldCollectionTpl:getItemType(tpl), _worldCollectionTpl:getItemId(tpl))
    for i, v in pairs(spawnerIds) do
      local spawnerId = v
      local allTplData = _worldMapTpl:getAllTplBySpawnerId(sceneId, spawnerId)
      for _, worldMapTpl in pairs(allTplData) do
        local node = self:createMapNode(L_MapConst.mapSievingType.mapCollectionItem)
        node.id = _worldMapTpl:getId(worldMapTpl)
        node.name = _worldCollectionTpl:getName(tpl)
        node.desc = tplData.desc
        node.sceneId = sceneId
        node.worldCollectionId = worldCollectionId
        node.iconPath = tplData.icon
        node.configPos = _worldMapTpl:getPosition(worldMapTpl)
        table.insert(nodeList, node)
      end
    end
  end
  return nodeList
end

function this:checkIsNoMaskNode(nodeType)
  return self.noMaskNode[nodeType] and self.noMaskNode[nodeType] == 1
end

function this:sandwichClose(pageName, exitName)
  if not pageName or not exitName then
    return
  end
  if not self.revMapSandwich then
    self.revMapSandwich = {}
    for k, v in pairs(mapSandwich) do
      self.revMapSandwich[v] = k
    end
  end
  local curFloor = mapSandwich[pageName]
  local exitFloor = mapSandwich[exitName]
  if curFloor < exitFloor then
    L_UI:open(self.revMapSandwich[curFloor + 1], {exitName = exitName, mode = "replace"})
  elseif curFloor > exitFloor then
    L_UI:open(self.revMapSandwich[curFloor - 1], {exitName = exitName, mode = "replace"})
  else
    L_UI:close(pageName)
  end
end

function this:filterMarkRewardParse(type, rewardId)
  local reward = {}
  if type == 1 then
    local chestTpl = _staminaChestDropTpl:getTplById(rewardId)
    if chestTpl then
      local needCost = L_DataUtil.parseRewardConfig(_staminaChestDropTpl:getNeed(chestTpl))[1]
      reward.name = _staminaChestDropTpl:getName(chestTpl)
      reward.cost = needCost.itemNum
      reward.rewardDisplay = _staminaChestDropTpl:getRewardDisplay(chestTpl)
      reward.upDuration = _staminaChestDropTpl:getUpDuration(chestTpl)
    end
  elseif type == 2 then
    local pondTpl = _fishPondTpl:getTplById(rewardId)
    local fishGroup = _fishPondTpl:getFishGroup(pondTpl)
    local fishList = _fishGroupTpl:getGroupFish(fishGroup)
    for i, v in pairs(fishList) do
      local id = v
      local item = L_ItemTplManager:getCommonItem(id)
      item.id = id
      item.type = L_Const.resType.commonItem
      table.insert(reward, item)
    end
    table.sort(reward, function(a, b)
      return a.quality > b.quality
    end)
  end
  return reward
end

function this:getPetCatalogMapNodeDic(sceneId, petConfigId, isNight)
  sceneId = sceneId or AzurWorldInstance.CurWorldId
  local dic = {}
  for key, func in pairs(self.petCatalogMapPair) do
    dic[key] = func(self, sceneId, petConfigId, isNight and isNight or false)
  end
  return dic
end

function this:getCurKiBoHabitatNode(sceneId, petConfigId, isNight)
  local nodeList = {}
  local petTpl = _petTpl:getTplById(petConfigId)
  if not petTpl then
    return nodeList
  end
  local allWorldPosList = _petTpl:getIconographyMapPos(petTpl)
  if table.isEmpty(allWorldPosList) then
    return nodeList
  end
  local posList = {}
  if isNight then
    posList = allWorldPosList[2]
  else
    posList = allWorldPosList[1]
  end
  for i, v in ipairs(posList) do
    if math.isEmpty(v) then
      break
    end
    local tpl = _worldPointTpl:getTplById(v)
    if _worldPointTpl:getCityId(tpl) == sceneId then
      local type = L_MapConst.mapSievingType.kiboHabitat
      local node = self:createMapNode(type)
      node.id = _worldPointTpl:getId(tpl)
      node.configPos = _worldPointTpl:getPosition(tpl)
      node.name = _worldPointTpl:getName(tpl)
      node.icon = _petTpl:getPetPixelIcon(petTpl)
      node.sceneId = sceneId
      table.insert(nodeList, node)
    end
  end
  return nodeList
end

function this:getAreaIdByKiBoHabitat(pointId)
  local tpl = _worldPointTpl:getTplById(pointId)
  if not tpl then
    return nil
  end
  local sceneId = _worldPointTpl:getCityId(tpl)
  local dataList = _worldAreaTpl:getAllArea(sceneId)
  if table.isEmpty(dataList) then
    return nil
  end
  local minId = math.maxinteger
  for _, data in pairs(dataList) do
    minId = math.min(minId, _worldAreaTpl:getId(data))
  end
  return minId
end

function this:checkCanTrace(collectionId, curSceneId)
  local canTrace, msg, noInCurWorld = self:_checkTraceHelper(collectionId, curSceneId)
  if canTrace then
    return true
  end
  if noInCurWorld then
    local targetAreaId = self:_tryFindMapAreaIdHasCollect(collectionId)
    local collectTpl = _worldCollectionTpl:getTplById(collectionId)
    local itemName = _worldCollectionTpl:getName(collectTpl)
    return false, L_Lang:get(L_WordsTpl:getValue("ui_world_collect_noitem"), {
      [1] = itemName
    }), targetAreaId
  else
    return false, msg
  end
  return true
end

function this:_tryFindMapAreaIdHasCollect(collectionId)
  local allScene = _worldAreaTpl:getAllScene()
  local collectTpl = _worldCollectionTpl:getTplById(collectionId)
  for _, sceneId in ipairs(allScene) do
    local list = _filterMarkTpl:getTplListByWorldId(sceneId, L_MapConst.mapSievingType.transfer)
    local areaMaskDict = {}
    for _, tpl in ipairs(list) do
      local wpTpl = _worldMapTpl:getTplById(sceneId, _filterMarkTpl:getWorldmapId(tpl))
      if wpTpl and not string.isEmpty(_filterMarkTpl:getMapMaskIcon(tpl)) then
        local birthPosId = _filterMarkTpl:getPosId(tpl)
        local isUnLock = L_SceneStore:getPointIsUnlock(birthPosId)
        local cityId = _filterMarkTpl:getWorldId(tpl)
        local worldMapId = _filterMarkTpl:getWorldmapId(tpl)
        local areaId = AzurWorld.WorldMapMgr:GetItemAreaId(cityId, worldMapId)
        areaMaskDict[areaId] = isUnLock
      end
    end
    local spawnerIds = _worldCollectionTpl:getSpawnerId(collectTpl)
    for _, spawnerId in pairs(spawnerIds) do
      local allTplData = _worldMapTpl:getAllTplBySpawnerId(sceneId, spawnerId)
      for _, worldMapTpl in pairs(allTplData) do
        local worldMapId = _worldMapTpl:getId(worldMapTpl)
        local serverData = AzurWorld.service.map:GetServerData(worldMapId, sceneId)
        local canCollect = true
        if serverData and serverData.complete then
          canCollect = false
        end
        local areaId = AzurWorld.WorldMapMgr:GetItemAreaId(sceneId, worldMapId)
        local isUnlock = areaMaskDict[areaId]
        if isUnlock and canCollect then
          local l = {}
          for i, v in pairs(_worldAreaTpl:getAllArea(sceneId)) do
            table.insert(l, v)
          end
          table.sort(l, function(a, b)
            return _worldAreaTpl:getId(a) < _worldAreaTpl:getId(b)
          end)
          return _worldAreaTpl:getId(l[1])
        end
      end
    end
  end
end

function this:_checkTraceHelper(collectionId, sceneId)
  local list = _filterMarkTpl:getTplListByWorldId(sceneId, L_MapConst.mapSievingType.transfer)
  local areaMaskDict = {}
  for _, tpl in ipairs(list) do
    local wpTpl = _worldMapTpl:getTplById(sceneId, _filterMarkTpl:getWorldmapId(tpl))
    if wpTpl and not string.isEmpty(_filterMarkTpl:getMapMaskIcon(tpl)) then
      local birthPosId = _filterMarkTpl:getPosId(tpl)
      local isUnLock = L_SceneStore:getPointIsUnlock(birthPosId)
      local cityId = _filterMarkTpl:getWorldId(tpl)
      local worldMapId = _filterMarkTpl:getWorldmapId(tpl)
      local areaId = AzurWorld.WorldMapMgr:GetItemAreaId(cityId, worldMapId)
      areaMaskDict[areaId] = isUnLock
    end
  end
  local noInCurWorld = true
  local hasUnlock = false
  local hasCanCollect = false
  local hasLockCanCollect = false
  local collectTpl = _worldCollectionTpl:getTplById(collectionId)
  if collectTpl then
    local spawnerIds = _worldCollectionTpl:getSpawnerId(collectTpl)
    for _, spawnerId in pairs(spawnerIds) do
      local allTplData = _worldMapTpl:getAllTplBySpawnerId(sceneId, spawnerId)
      for _, worldMapTpl in pairs(allTplData) do
        noInCurWorld = false
        local worldMapId = _worldMapTpl:getId(worldMapTpl)
        local serverData = AzurWorld.service.map:GetServerData(worldMapId, sceneId)
        local canCollect = true
        if serverData and serverData.complete then
          canCollect = false
        end
        local areaId = AzurWorld.WorldMapMgr:GetItemAreaId(sceneId, worldMapId)
        local isUnlock = areaMaskDict[areaId]
        if isUnlock and canCollect then
          return true
        end
        if isUnlock then
          hasUnlock = true
        end
        if canCollect then
          hasCanCollect = true
        end
        if not isUnlock and canCollect then
          hasLockCanCollect = true
        end
      end
    end
  end
  if not hasUnlock then
    return false, L_WordsTpl:getValue("ui_world_collect_locked"), noInCurWorld
  end
  if hasUnlock and hasLockCanCollect then
    local itemName = _worldCollectionTpl:getName(collectTpl)
    return false, L_Lang:get(L_WordsTpl:getValue("ui_world_collect_noitem"), {
      [1] = itemName
    }), noInCurWorld
  end
  if not hasCanCollect then
    return false, L_WordsTpl:getValue("ui_world_collect_refresh_tips"), noInCurWorld
  end
  return false
end

return this
