local LWStageFeatureChapterManager = BaseClass("LWStageFeatureChapterManager", CEventable)

function LWStageFeatureChapterManager:__init()
  self.currStageId = nil
  self.nextStageId = nil
  self.doneStageIds = {}
  self.chapterCfgs = {}
  self.chapterCfg = nil
  self.lastPlayChapterCfgId = nil
  self.resetedStageIds = {}
  self.todayResetTimes = 0
  self.skipIds = {}
  self.failCount = {}
  self.chapterStageInfoDict = {}
  self:RegisterEvent(EventId.ParkourBattleWin, self.OnParkourBattleWin)
  self:RegisterEvent(EventId.GF_enter_city, self.OnEnterCity)
  self:RegisterEvent(EventId.StageFeatureChapterWinCheckUploadGameCenterData, self.JudgeIsEnoughUploadDataToGameCenter)
end

function LWStageFeatureChapterManager:__delete()
  self.currStageId = nil
  self.nextStageId = nil
  self.doneStageIds = nil
  self.chapterCfgs = nil
  self.chapterCfg = nil
  self.chapterIdToIndex = nil
  self.resetedStageIds = nil
  self.lastPlayChapterCfgId = nil
  self.abTest = nil
  self.todayResetTimes = 0
  self.autoOpenMapUIWhenBackToCity = nil
  self.skipIds = nil
  self.failCount = nil
  self.chapterStageInfoDict = nil
end

function LWStageFeatureChapterManager:Startup()
end

local __FindNextStageId = function(self, fillDoneStageIds)
  self.nextStageId = nil
  local hitStageId = false
  for _, chapterCfg in ipairs(self.chapterCfgs) do
    if self.nextStageId ~= nil then
      break
    end
    for _, stageId in ipairs(chapterCfg.stageIds) do
      if hitStageId then
        if not self:IsSkipStage(stageId) then
          self.nextStageId = stageId
          self.chapterCfg = chapterCfg
          break
        end
      else
        if fillDoneStageIds and not self:IsSkipStage(stageId) then
          self.doneStageIds[stageId] = true
        end
        if stageId == self.currStageId then
          self.chapterCfg = chapterCfg
          hitStageId = true
        end
      end
    end
  end
  if not hitStageId and self.nextStageId == nil then
    self.chapterCfg = self.chapterCfgs[1]
    self.nextStageId = self.chapterCfg.stageIds[1]
    if fillDoneStageIds then
      self.doneStageIds = {}
    end
  end
  if fillDoneStageIds then
    for index, resetedStageId in ipairs(self.resetedStageIds) do
      self.doneStageIds[resetedStageId] = false
    end
  end
end

function LWStageFeatureChapterManager:InitData(msg)
  if msg.planeFeatureStageInfo then
    self.currStageId = msg.planeFeatureStageInfo.stageId
    local resetTimesToday = msg.planeFeatureStageInfo.resetTimes
    self.todayResetTimes = resetTimesToday or 0
    local resetedStageIds = msg.planeFeatureStageInfo.ids
    self.resetedStageIds = resetedStageIds or {}
    local skips = msg.planeFeatureStageInfo.skipIds
    self.skipIds = {}
    if skips then
      for _, v in ipairs(skips) do
        self.skipIds[v] = true
      end
    end
  end
  self.chapterCfgs = {}
  local chapterTbl = LocalController:instance():getTable(TableName.LW_STAGE_FEATURE_CHAPTER)
  for chapterId, _ in pairs(chapterTbl.data) do
    local stageIds = LocalController:instance():getValue(TableName.LW_STAGE_FEATURE_CHAPTER, chapterId, "stages")
    local nodePosArr = {}
    local nodePosStrArr = LocalController:instance():getValue(TableName.LW_STAGE_FEATURE_CHAPTER, chapterId, "nodePos")
    for _, nodePosStr in ipairs(nodePosStrArr) do
      local nodePos = string.split(nodePosStr, ",")
      table.insert(nodePosArr, Vector3(tonumber(nodePos[1]), tonumber(nodePos[2]), 0))
    end
    local nodeTipStyleArr = LocalController:instance():getValue(TableName.LW_STAGE_FEATURE_CHAPTER, chapterId, "nodeTipStyle")
    local sign_up_day = LocalController:instance():getValue(TableName.LW_STAGE_FEATURE_CHAPTER, chapterId, "sign_up_day")
    local main_building_level = LocalController:instance():getValue(TableName.LW_STAGE_FEATURE_CHAPTER, chapterId, "main_building_level")
    table.insert(self.chapterCfgs, {
      id = chapterId,
      stageIds = stageIds,
      nodePosArr = nodePosArr,
      nodeTipStyleArr = nodeTipStyleArr,
      sign_up_day = sign_up_day,
      main_building_level = main_building_level
    })
  end
  table.sort(self.chapterCfgs, function(a, b)
    return a.id < b.id
  end)
  self.chapterIdToIndex = {}
  for index, chaperCfgData in ipairs(self.chapterCfgs) do
    if chaperCfgData then
      self.chapterIdToIndex[chaperCfgData.id] = index
    end
  end
  if not self.chapterCfg and 0 < #self.chapterCfgs then
    self.chapterCfg = self.chapterCfgs[1]
  end
  __FindNextStageId(self, true)
  self.countBattleMapMainLv = LuaEntry.DataConfig:TryGetNum("stageFeatureChapter", "k3")
  self:FixCurStageIdForSkip()
  self:CalculateFinishStageCount()
end

function LWStageFeatureChapterManager:OnEnterGame()
  self.countBattleMapMainLv = LuaEntry.DataConfig:TryGetNum("stageFeatureChapter", "k3")
end

function LWStageFeatureChapterManager:SetCurPlayChapterId(chapterId)
  self.lastPlayChapterCfgId = chapterId
end

function LWStageFeatureChapterManager:GetCurPlayChapterId()
  return self.lastPlayChapterCfgId
end

function LWStageFeatureChapterManager:IsAllDone()
  return self.nextStageId == nil
end

function LWStageFeatureChapterManager:IsOpen()
  return true
end

function LWStageFeatureChapterManager:OnParkourBattleWin(stageId)
  local isResetedStage = self:IsStageReseted(stageId)
  local isNextStageId = self.nextStageId and self.nextStageId == stageId
  local isSkipStage = self:IsSkipStage(stageId)
  if not isNextStageId and not isResetedStage and not isSkipStage then
    return
  end
  self.doneStageIds[stageId] = true
  if isSkipStage then
    self:RemoveSkipStage(stageId)
  end
  if isResetedStage then
    local newResetedStageIds = {}
    for i, resetedStageId in ipairs(self.resetedStageIds) do
      if resetedStageId ~= stageId then
        table.insert(newResetedStageIds, resetedStageId)
      end
    end
    self.resetedStageIds = newResetedStageIds
    return
  end
  if isNextStageId then
    self.currStageId = stageId
    __FindNextStageId(self, false)
  end
end

function LWStageFeatureChapterManager:GetTodayResetTimes()
  return self.todayResetTimes
end

function LWStageFeatureChapterManager:GetStageBelongsChapterCfgData(targetStageId)
  for _, chapterCfg in ipairs(self.chapterCfgs) do
    for _, stageId in ipairs(chapterCfg.stageIds) do
      if stageId == targetStageId then
        return chapterCfg
      end
    end
  end
  return nil
end

function LWStageFeatureChapterManager:GetResetedChapterNextStageId(resetedChapterCfg)
  if not resetedChapterCfg then
    return -1
  end
  local resetedChapterStageIds = resetedChapterCfg.stageIds
  for index, stageId in ipairs(resetedChapterStageIds) do
    local stageIsReseted = self:IsStageReseted(stageId)
    if stageIsReseted then
      return stageId
    end
  end
  return -1
end

function LWStageFeatureChapterManager:IsStageReseted(stageId)
  return table.indexof(self.resetedStageIds, stageId)
end

function LWStageFeatureChapterManager:GetChapterCfgData(chapterId)
  local chapterCfgIndex = self.chapterIdToIndex[chapterId]
  if not chapterCfgIndex then
    return nil
  end
  return self.chapterCfgs[chapterCfgIndex]
end

function LWStageFeatureChapterManager:ResetTargetChapterStages(chapterId)
  local chapterCfgIndex = self.chapterIdToIndex[chapterId]
  if not chapterCfgIndex then
    return
  end
  self.targetResetChapterId = chapterId
  self:SendResetStageIdsToSeverMsg(self.targetResetChapterId)
end

function LWStageFeatureChapterManager:UpdateDataFromReset(msg)
  if not msg then
    return
  end
  if self.targetResetChapterId then
    self.resetedStageIds = msg.ids or {}
    self.todayResetTimes = msg.resetTimes or 0
    for i, stageId in ipairs(self.resetedStageIds) do
      self.doneStageIds[stageId] = false
    end
    EventManager:GetInstance():Broadcast(EventId.STAGE_FEATURE_CHAPTER_RESET, self.targetResetChapterId)
  end
end

function LWStageFeatureChapterManager:UpdateDataFromPushTimes(msg)
  if not msg then
    return
  end
  local updatedResetTimes = msg.resetTimes
  if updatedResetTimes then
    self.todayResetTimes = updatedResetTimes
  end
end

function LWStageFeatureChapterManager:SendResetStageIdsToSeverMsg(resetChapterId)
  SFSNetwork.SendMessage(MsgDefines.StageFeatureChapterResetMessage, resetChapterId)
end

function LWStageFeatureChapterManager:OnEnterCity()
  if self.autoOpenMapUIWhenBackToCity then
    self.autoOpenMapUIWhenBackToCity = nil
    DataCenter.LWTrailTowerManager:OpenTrailTowerMainPanel(TrailTowerTabType.StageFeatureChapter)
  end
end

function LWStageFeatureChapterManager:IsChapterFinsh(chapterCfg)
  local stageIds = chapterCfg.stageIds
  for i, stageId in ipairs(stageIds) do
    if not self.doneStageIds[stageId] then
      return false
    end
  end
  return true
end

function LWStageFeatureChapterManager:IsSkipStage(stageId)
  return self.skipIds[stageId]
end

function LWStageFeatureChapterManager:RemoveSkipStage(stageId)
  self.skipIds[stageId] = nil
  self.failCount[stageId] = nil
end

function LWStageFeatureChapterManager:AddFailStage(stageId)
  if stageId == nil then
    return
  end
  if self.doneStageIds[stageId] then
    self:RemoveSkipStage(stageId)
    return
  end
  if self:IsStageReseted(stageId) then
    self:RemoveSkipStage(stageId)
    return
  end
  local count = self.failCount[stageId] or 0
  count = count + 1
  self.failCount[stageId] = count
end

function LWStageFeatureChapterManager:GetFailCount(stageId)
  if self.failCount then
    return self.failCount[stageId] or 0
  end
  return 0
end

function LWStageFeatureChapterManager:SendSkipMessage(stageId)
  SFSNetwork.SendMessage(MsgDefines.StageFeatureChapterSkip, stageId)
end

function LWStageFeatureChapterManager:OnReceiveSkip(message)
  local skips = message.skipIds
  self.skipIds = {}
  if skips then
    for _, v in ipairs(skips) do
      self.skipIds[v] = true
    end
  end
  self:FixCurStageIdForSkip()
  __FindNextStageId(self, false)
  EventManager:GetInstance():Broadcast(EventId.StageFeatureChapterSkip)
end

function LWStageFeatureChapterManager:FixCurStageIdForSkip()
  if self.currStageId == nil and self.nextStageId and self:IsSkipStage(self.nextStageId) then
    self.currStageId = self.nextStageId
    __FindNextStageId(self, false)
  end
end

function LWStageFeatureChapterManager:TryEnterNextStage()
  if self.nextStageId and self.nextStageId > 0 and self.chapterCfg then
    UIManager:GetInstance():DestroyWindow(UIWindowNames.UIParkourBattleLose, {anim = false})
    local param = {}
    param.type = PVEType.Parkour
    param.levelId = tonumber(self.nextStageId)
    param.fromChapter = true
    DataCenter.LWBattleManager:Enter(param)
    DataCenter.LWStageFeatureChapterManager.autoOpenMapUIWhenBackToCity = true
    DataCenter.LWStageFeatureChapterManager:SetCurPlayChapterId(self.chapterCfg.id)
    return true
  end
  return false
end

function LWStageFeatureChapterManager:RequestChapterStageInfo(chapterId)
  for k, v in pairs(self.chapterCfgs) do
    if v.id == chapterId then
      SFSNetwork.SendMessage(MsgDefines.LwPlaneFeatureInfo, v.stageIds)
    end
  end
end

function LWStageFeatureChapterManager:RefreshChapterStageInfo(message)
  if message.info then
    for k, v in pairs(message.info) do
      if v.id and v.soldier then
        self.chapterStageInfoDict[v.id] = v.soldier
      end
    end
  end
end

function LWStageFeatureChapterManager:UpdateOneStageInfo(stageId, historySoldier)
  if self.chapterStageInfoDict[stageId] then
    if historySoldier > self.chapterStageInfoDict[stageId] then
      self.chapterStageInfoDict[stageId] = historySoldier
    end
  else
    self.chapterStageInfoDict[stageId] = historySoldier
  end
end

function LWStageFeatureChapterManager:JudgeIsEnoughUploadDataToGameCenter(paramData)
  local targetChapterCfg = self:GetStageBelongsChapterCfgData(paramData.stageId)
  if targetChapterCfg then
    local index = table.indexof(targetChapterCfg.stageIds, paramData.stageId)
    local stageCount = table.count(targetChapterCfg.stageIds)
    self:UpdateOneStageInfo(paramData.stageId, paramData.remainMemberCount)
    if index and index == stageCount then
      local totalHistorySoldier = 0
      for _, stageId in pairs(targetChapterCfg.stageIds) do
        if self.chapterStageInfoDict[stageId] then
          totalHistorySoldier = totalHistorySoldier + self.chapterStageInfoDict[stageId]
        end
      end
      if 0 < totalHistorySoldier and totalHistorySoldier <= 99999 then
        local rankName = string.format(GameCenterUploadDataName.StageFeatureChapter, targetChapterCfg.id)
        CS.GameCenterBridge.SubmitScore(rankName, totalHistorySoldier)
      end
    end
  end
  self:CalculateFinishStageCount()
end

function LWStageFeatureChapterManager:CalculateFinishStageCount()
  local finishCount = 0
  for stageId, value in pairs(self.doneStageIds) do
    if value then
      finishCount = finishCount + 1
    end
  end
  local resetCount = table.count(self.resetedStageIds)
  local allCount = finishCount + resetCount
  DataCenter.LWGameCenterUploadAchievementManager:UploadStageFeatureChapterAchievement(allCount)
end

return LWStageFeatureChapterManager
