local SeasonFactionWarDataManager = BaseClass("SeasonFactionWarDataManager")
local Localization = CS.GameEntry.Localization

function SeasonFactionWarDataManager:__init()
  self.StepText = {
    "season_s2_faction_war_07",
    "season_s2_faction_war_08",
    "season_s2_faction_war_09",
    "season_s2_faction_war_10",
    "season_s2_faction_war_11",
    "season_s2_faction_war_12"
  }
  self.lastRequestServerDataTime = 0
  self.currStep = nil
  self.stepEndTime = nil
  self.attackCampId = 0
  self.defenceCampId = 0
  self.myCampId = 0
  self.warInfo = {}
  self.theDefenderList = {}
  self.theAttackerList = {}
  EventManager:GetInstance():AddListenerWithSelf(EventId.OnEnterWorld, self.OnEnterWorld, self)
  EventManager:GetInstance():AddListenerWithSelf(EventId.OnEnterCity, self.OnEnterCity, self)
end

function SeasonFactionWarDataManager:__delete()
  EventManager:GetInstance():RemoveListener2(EventId.OnEnterWorld, self.OnEnterWorld, self)
  EventManager:GetInstance():RemoveListener2(EventId.OnEnterCity, self.OnEnterCity, self)
end

function SeasonFactionWarDataManager:GetPlunderRatio()
  local seasonType = SeasonUtil.GetSeasonType()
  local factionWarActivityType = SeasonUtil.GetFactionWarActivityType(seasonType)
  if SeasonUtil.SeasonHasMilitaryCenterAttachment(seasonType) then
    local dataList = DataCenter.ActivityListDataManager:GetActivityDataByType(factionWarActivityType)
    local actData = dataList[1]
    if actData and actData.para_3 then
      local num1, num2 = string.split_ii(actData.para_3, "|")
      return (toInt(num1) + toInt(num2) * 4) / 100
    end
  elseif seasonType == SeasonMapType.Snow then
    local dataList = DataCenter.ActivityListDataManager:GetActivityDataByType(EnumActivity.SeasonFactionBigWarActivity.Type)
    local actData = dataList[1]
    if actData ~= nil then
      local num = toInt(actData.para_1)
      if 0 < num then
        return num / 100
      end
    end
    dataList = DataCenter.ActivityListDataManager:GetActivityDataByType(EnumActivity.SeasonFactionDeclareWarActivity.Type)
    actData = dataList[1]
    if actData and actData.para_3 then
      return toInt(actData.para_3) / 100
    end
  end
  return 0
end

function SeasonFactionWarDataManager:InitData()
  local seasonType = SeasonUtil.GetSeasonType()
  if SeasonUtil.SeasonHasFactionWar(seasonType) and SeasonUtil.IsInSeason() then
    SFSNetwork.SendMessage(MsgDefines.FetchSeasonFactionVsInfo)
    SFSNetwork.SendMessage(MsgDefines.GetSeasonFactionInfo)
    SFSNetwork.SendMessage(MsgDefines.FetchSeasonFactionDeclareWarInfo)
    self.lastRequestServerDataTime = UITimeManager:GetInstance():GetServerTime()
  end
end

function SeasonFactionWarDataManager:OnEnterWorld()
  if DataCenter.SeasonFactionWarDataManager.currStep == nil then
    DataCenter.SeasonFactionWarDataManager:InitData()
  else
    DataCenter.SeasonFactionWarDataManager:CalcStepAndStepTime()
  end
end

function SeasonFactionWarDataManager:OnEnterCity()
  if DataCenter.SeasonFactionWarDataManager.currStep == nil then
    DataCenter.SeasonFactionWarDataManager:InitData()
  else
    DataCenter.SeasonFactionWarDataManager:CalcStepAndStepTime()
  end
end

function SeasonFactionWarDataManager:UpdateAttackGroupInfo(defender, attacker)
  if defender and attacker then
    self.theDefenderList = {}
    self.theAttackerList = {}
    for i, aid in ipairs(defender) do
      if i == 1 then
        self.defenderAllianceId = aid
      end
      self.theDefenderList[aid] = aid
    end
    for _, aid in ipairs(attacker) do
      self.theAttackerList[aid] = aid
    end
  end
end

function SeasonFactionWarDataManager:CanJoinAttack(allianceId)
  if self.dataList1 and self.dataList2 then
    for k, v in ipairs(self.dataList1) do
      if v and v.allianceId == allianceId then
        return true
      end
    end
    for k, v in ipairs(self.dataList2) do
      if v and v.allianceId == allianceId then
        return true
      end
    end
    return false
  else
    return true
  end
end

function SeasonFactionWarDataManager:CanAttackAllianceBuild(buildId, buildAllianceId)
  local myAllianceId = LuaEntry.Player:GetAllianceUid()
  if myAllianceId == buildAllianceId then
    return false
  end
  self:CalcStepAndStepTime()
  if SeasonUtil.IsSeasonMilitaryCenterCarrier(buildId) then
    return true
  end
  if SeasonUtil.IsSeasonMilitaryCenterOrPlugin(buildId) then
    if self.currStep ~= SeasonFactionDeclareWarStep.battle then
      return false
    end
    return self.theDefenderList[buildAllianceId] ~= nil and self.theAttackerList[myAllianceId] ~= nil
  end
  return myAllianceId ~= buildAllianceId
end

function SeasonFactionWarDataManager:CanAssistAllianceBuild(buildId, buildAllianceId)
  local myAllianceId = LuaEntry.Player:GetAllianceUid()
  if myAllianceId == buildAllianceId then
    return true
  end
  if SeasonUtil.IsSeasonMilitaryCenterOrPlugin(buildId) then
    self:CalcStepAndStepTime()
    if self.currStep ~= SeasonFactionDeclareWarStep.battle_before and self.currStep ~= SeasonFactionDeclareWarStep.battle then
      return myAllianceId == buildAllianceId
    end
    return self.theDefenderList[buildAllianceId] and self.theDefenderList[myAllianceId]
  end
  return myAllianceId == buildAllianceId
end

function SeasonFactionWarDataManager:CanMoveCityTo(serverId)
  self:CalcStepAndStepTime()
  if self.currStep == SeasonFactionDeclareWarStep.battle_before or self.currStep == SeasonFactionDeclareWarStep.battle then
    return not self:ServerIsAttacker(serverId)
  end
  return false
end

function SeasonFactionWarDataManager:GetDeclareWarActInfo()
  return self.declareWarActObj
end

function SeasonFactionWarDataManager:GetCurrStep()
  self:CalcStepAndStepTime()
  return self.currStep
end

function SeasonFactionWarDataManager:UpdateStepAndStepTime(currStep, stepEndTime)
  if currStep and stepEndTime then
    self.currStep = currStep
    self.stepEndTime = stepEndTime
    EventManager:GetInstance():Broadcast(EventId.LWSeasonFactionBattleInfoUpdate)
  end
end

function SeasonFactionWarDataManager:CalcStepAndStepTime()
  if self.currStep and self.stepEndTime then
    if self.cfgStepDuration == nil then
      local theSeasonType = SeasonUtil.GetSeasonType()
      local dataList
      local factionWarActivityType = SeasonUtil.GetFactionWarActivityType(theSeasonType)
      if factionWarActivityType ~= 0 then
        dataList = DataCenter.ActivityListDataManager:GetActivityDataByType(factionWarActivityType)
      end
      if dataList ~= nil and 0 < #dataList then
        local data = dataList[1]
        if data then
          local stepDeclare, stepInvite, stepPreparation, stepBattle1v1, stepBattle1v2, stepBattle1v3
          local tmp = string.split(data.para_1, "|")
          if tmp and #tmp == 3 then
            stepDeclare, stepInvite, stepPreparation = toInt(tmp[1]), toInt(tmp[2]), toInt(tmp[3])
          end
          tmp = string.split(data.para_2, "|")
          if tmp and #tmp == 3 then
            stepBattle1v1, stepBattle1v2, stepBattle1v3 = toInt(tmp[1]), toInt(tmp[2]), toInt(tmp[3])
          end
          self.cfgStepDuration = {
            stepDeclare,
            stepInvite,
            stepPreparation,
            stepBattle1v1,
            stepBattle1v2,
            stepBattle1v3
          }
        end
      end
    end
    if self.cfgStepDuration ~= nil then
      local now = UITimeManager:GetInstance():GetServerTime()
      if now >= self.stepEndTime then
        if self.currStep == SeasonFactionDeclareWarStep.declare_before then
          self.currStep = SeasonFactionDeclareWarStep.declare
          self.stepEndTime = self.stepEndTime + toInt(self.cfgStepDuration[1]) * 1000
        elseif self.currStep == SeasonFactionDeclareWarStep.declare then
          self.currStep = SeasonFactionDeclareWarStep.invite
          self.stepEndTime = self.stepEndTime + toInt(self.cfgStepDuration[2]) * 1000
        elseif self.currStep == SeasonFactionDeclareWarStep.invite then
          self.currStep = SeasonFactionDeclareWarStep.battle_before
          self.stepEndTime = self.stepEndTime + toInt(self.cfgStepDuration[3]) * 1000
        elseif self.currStep == SeasonFactionDeclareWarStep.battle_before then
          self.currStep = SeasonFactionDeclareWarStep.battle
          local theDefenderCount = table.count(self.theDefenderList)
          local theAttackerCount = table.count(self.theAttackerList)
          local diff = theAttackerCount - theDefenderCount
          if diff == 0 then
            self.stepEndTime = self.stepEndTime + toInt(self.cfgStepDuration[4]) * 1000
          elseif diff == 1 then
            self.stepEndTime = self.stepEndTime + toInt(self.cfgStepDuration[5]) * 1000
          elseif diff == 2 then
            self.stepEndTime = self.stepEndTime + toInt(self.cfgStepDuration[6]) * 1000
          end
        end
        if now - toInt(self.lastRequestServerDataTime) > OneHourTime then
          self:InitData()
        end
      end
    end
  end
end

function SeasonFactionWarDataManager:GetGroupingActInfo()
  return self.groupingActInfo
end

function SeasonFactionWarDataManager:GetGroupingData()
  return self.seasonFactionInfo
end

function SeasonFactionWarDataManager:IsGroupingShownMode()
  if self.groupingMode == true then
    return false
  end
  local campInfo = self.seasonFactionInfo
  local groupingActInfo = self.groupingActInfo
  local seasonType = SeasonUtil.GetSeasonType()
  if SeasonUtil.SeasonHasCampMasterServer(seasonType) then
    if groupingActInfo then
      if groupingActInfo.hasSubStep then
        if groupingActInfo.subStep == 0 then
          return false
        else
          return false
        end
      else
        return groupingActInfo.step == 1
      end
    elseif campInfo then
    end
  end
  if campInfo ~= nil and campInfo[1] and toInt(campInfo[1].campId) ~= 0 and (groupingActInfo == nil or groupingActInfo.step == 1) then
    return true
  end
  return false
end

function SeasonFactionWarDataManager:GetCampIdByServerId(theServerId)
  local campInfo = self.seasonFactionInfo
  if campInfo then
    local serverId = toInt(theServerId)
    if serverId ~= 0 then
      for _, v in ipairs(campInfo) do
        if serverId == v.serverId then
          return v.campId or 0
        end
      end
    end
  end
  return 0
end

function SeasonFactionWarDataManager:IsInSameCampByServer(serverIdA, serverIdB)
  serverIdB = serverIdB or LuaEntry.Player:GetSourceServerId()
  local campIdA = self:GetCampIdByServerId(serverIdA)
  local campIdB = self:GetCampIdByServerId(serverIdB)
  return campIdA ~= 0 and campIdA == campIdB
end

function SeasonFactionWarDataManager:IsSameCampOrSameAllianceOrMe(serverId, allianceId, uid)
  if LuaEntry.Player:GetUid() == uid then
    return true
  end
  if LuaEntry.Player:IsInAlliance() and LuaEntry.Player:GetAllianceUid() == allianceId then
    return true
  end
  if self:IsInSameCampByServer(serverId) then
    return true
  end
  return false
end

function SeasonFactionWarDataManager:CampInfoToString()
  local ret = ""
  local campInfo = self.seasonFactionInfo
  if campInfo then
    for _, v in ipairs(campInfo) do
      ret = ret .. string.format(",%s-%s", v.serverId, v.campId)
    end
  end
  return ret
end

function SeasonFactionWarDataManager:ServerIsAttacker(theServerId)
  if self.attackCampId ~= 0 then
    local serverId = toInt(theServerId)
    if self.myCampId ~= 0 and serverId == LuaEntry.Player:GetSourceServerId() then
      return self.myCampId == self.attackCampId
    end
    local campId = self:GetCampIdByServerId(theServerId)
    if campId ~= 0 then
      return self.attackCampId == campId
    end
  end
  return false
end

function SeasonFactionWarDataManager:CampIsAttacker(campId)
  if self.attackCampId ~= 0 then
    return self.attackCampId == toInt(campId)
  end
  return false
end

function SeasonFactionWarDataManager:GetCampIcon(campId, big)
  local seasonType = SeasonUtil.GetSeasonType()
  if big then
    if seasonType == SeasonMapType.Darkness then
      if toInt(campId) == 1 then
        return "Assets/Main/SeasonRes/S4/Sprites/Common/ljq_s4_zhenying_1_mid.png"
      end
      return "Assets/Main/SeasonRes/S4/Sprites/Common/ljq_s4_zhenying_2_mid.png"
    end
    if seasonType == SeasonMapType.Mummy then
      if toInt(campId) == 1 then
        return "Assets/Main/SeasonRes/S3/Sprites/UI/FactionDeclareWar/ljq_s3_zhenying_huizhang_02.png"
      end
      return "Assets/Main/SeasonRes/S3/Sprites/UI/FactionDeclareWar/ljq_s3_zhenying_huizhang_01.png"
    end
    if toInt(campId) == 1 then
      return "Assets/Main/Sprites/UI/UISeason/UISeason2/SeasonRank/ljq_s2_zhenying_huizhang_02.png"
    end
    return "Assets/Main/Sprites/UI/UISeason/UISeason2/SeasonRank/ljq_s2_zhenying_huizhang_01.png"
  end
  if seasonType == SeasonMapType.Darkness then
    if toInt(campId) == 1 then
      return "Assets/Main/SeasonRes/S4/Sprites/Common/ljq_s4_zhenying_1.png"
    end
    return "Assets/Main/SeasonRes/S4/Sprites/Common/ljq_s4_zhenying_2.png"
  end
  if seasonType == SeasonMapType.Mummy then
    if toInt(campId) == 1 then
      return "Assets/Main/SeasonRes/S3/Sprites/UI/LWCommon/ljq_s3_zhenying_1.png"
    end
    return "Assets/Main/SeasonRes/S3/Sprites/UI/LWCommon/ljq_s3_zhenying_2.png"
  end
  if toInt(campId) == 1 then
    return "Assets/Main/Sprites/UI/UISeason/UISeason2/Faction/mjc_s2_zhenying_fankangjun.png"
  end
  return "Assets/Main/Sprites/UI/UISeason/UISeason2/Faction/mjc_s2_zhenying_xianbingtuan.png"
end

function SeasonFactionWarDataManager:GetCampName(campId)
  local seasonType = SeasonUtil.GetSeasonType()
  if seasonType == SeasonMapType.Mummy then
    if toInt(campId) == SeasonFactionType.Rebels then
      return Localization:GetString("season_s3_activity_1000063_desc10")
    end
    return Localization:GetString("season_s3_activity_1000063_desc11")
  end
  if toInt(campId) == SeasonFactionType.Rebels then
    return Localization:GetString("season_s2_faction_war_03")
  end
  return Localization:GetString("season_s2_faction_war_04")
end

function SeasonFactionWarDataManager:OnBattleFinish(t)
  self:InitData()
  local theWorld = CS.SceneManager.World
  if t == nil or t.vsInfo == nil or t.result == nil or t.result == 0 or t.startTime == nil or theWorld == nil or not SceneUtils.GetIsInWorld() then
    return
  end
  local seasonType = SeasonUtil.GetSeasonType()
  local pointId = 0
  local buildServerId = 0
  local hasEffect = false
  local buildId = SeasonUtil.GetSeasonMilitaryCenterId(seasonType)
  if self.s3BuildInfo and self.s3BuildInfo.buildList then
    for k, v in pairs(self.s3BuildInfo.buildList) do
      if v and v.buildId == buildId then
        pointId = v.pointId
        buildServerId = v.buildServerId
        break
      end
    end
  else
    local furnaceInfo = self.defenderFurnaceInfo
    if furnaceInfo == nil and self.warInfo and self.warInfo.furnaceInfo then
      furnaceInfo = self.warInfo.furnaceInfo
    end
    if furnaceInfo ~= nil then
      pointId = furnaceInfo.pointId
      buildServerId = furnaceInfo.buildServerId
    end
  end
  if t.result == 2 and pointId ~= nil and pointId ~= 0 and buildServerId == LuaEntry.Player:GetCurServerId() then
    local obj = theWorld:GetObjectByPoint(pointId)
    if obj ~= nil then
      local modelPath = "Assets/Main/Prefabs/AllianceBuilding/allianceBuilding_s2_boom.prefab"
      local request = CS.GameEntry.Resource:InstantiateAsync(modelPath)
      request:completed("+", function()
        local world = CS.SceneManager.World
        if request.isError or world == nil then
          request:Destroy()
          return
        end
        request.gameObject:SetActive(true)
        request.gameObject.transform:SetParent(world.DynamicObjNode)
        request.gameObject.transform:Set_localScale(ResetScale.x, ResetScale.y, ResetScale.z)
        request.gameObject.transform.position = SceneUtils.TileIndexToWorld(pointId, ForceChangeScene.World)
        TimerManager:GetInstance():DelayInvoke(function()
          request:Destroy()
        end, 7)
      end)
      hasEffect = true
    end
  end
  if t and (t.result == 1 or t.result == 2) then
    if seasonType == SeasonMapType.Snow then
      if hasEffect then
        local battleData = t
        TimerManager:GetInstance():DelayInvoke(function()
          UIManager:GetInstance():OpenWindow(UIWindowNames.UILWSeasonFactionWarSuccess, {anim = true}, battleData)
        end, 3.33)
      else
        UIManager:GetInstance():OpenWindow(UIWindowNames.UILWSeasonFactionWarSuccess, {anim = true}, t)
      end
    elseif seasonType == SeasonMapType.Mummy then
      if hasEffect then
        local battleData = t
        TimerManager:GetInstance():DelayInvoke(function()
          UIManager:GetInstance():OpenWindow(UIWindowNames.UILWSeasonFactionWarSuccessS3, {anim = true}, battleData)
        end, 3.33)
      else
        UIManager:GetInstance():OpenWindow(UIWindowNames.UILWSeasonFactionWarSuccessS3, {anim = true}, t)
      end
    elseif seasonType == SeasonMapType.Darkness then
      if hasEffect then
        local battleData = t
        TimerManager:GetInstance():DelayInvoke(function()
          UIManager:GetInstance():OpenWindow(UIWindowNames.UILWSeasonFactionWarSuccessS4, {anim = true}, battleData)
        end, 3.33)
      else
        UIManager:GetInstance():OpenWindow(UIWindowNames.UILWSeasonFactionWarSuccessS4, {anim = true}, t)
      end
    end
  else
    Logger.LogInfo("\230\136\152\230\150\151\230\178\161\230\156\137\232\131\156\232\180\159\231\187\147\230\158\156\239\188\140\230\151\160\233\156\128\229\188\185\231\170\151")
  end
end

function SeasonFactionWarDataManager:IsSameAsMineCamp(serverId)
  if self.myCampId ~= 0 and self.myCampId == self:GetCampIdByServerId(serverId) then
    return true
  end
  return false
end

function SeasonFactionWarDataManager:InitLevelGroup(para_7, para_8)
  local seasonType = SeasonUtil.GetSeasonType()
  if seasonType == SeasonMapType.Darkness then
    local seasonIndex, seasonWeek = DataCenter.SeasonDataManager:GetSeasonWeekInfo()
    local battleWeek = seasonWeek - 3
    local factionWarActivityType = SeasonUtil.GetFactionWarActivityType()
    local dataAct = DataCenter.ActivityListDataManager:GetOneOpenActivityByType(factionWarActivityType)
    if dataAct and dataAct.startTime then
      local actStartTime = dataAct.startTime
      local curTime = UITimeManager:GetInstance():GetServerTime()
      local elapsedTime = curTime - actStartTime
      if 0 <= elapsedTime then
        battleWeek = math.floor(elapsedTime / (7 * OneDayTime * 1000)) + 1
      end
    end
    local bestCountStr = LuaEntry.DataConfig:TryGetStr("s4_faction_war", "k9", "30|30|30|30")
    local itemMaxCountStr = LuaEntry.DataConfig:TryGetStr("s4_faction_war", "k10", "10|6|3|1")
    local maxCount = 100
    local groupCountSetting = LuaEntry.DataConfig:TryGetNum("s4_faction_war", "k11", "1-68;69-9999|50;100")
    local bestCountList = string.split_ii_array(bestCountStr, "|")
    local itemMaxCountList = string.split_ii_array(itemMaxCountStr, "|")
    local bestCount = math.max(1, bestCountList[battleWeek] or 30)
    local itemMaxCount = math.max(1, itemMaxCountList[battleWeek] or 10)
    if groupCountSetting then
      local t1, t2 = string.split_ss(groupCountSetting, "|")
      if t1 and t2 then
        local t3 = string.split_ss_array(t1, ";")
        local t4 = string.split_ss_array(t2, ";")
        if t3 and t4 and #t3 == #t4 then
          local serverId = LuaEntry.Player:GetCurServerId()
          for index, t5 in ipairs(t3) do
            if t5 then
              local t6, t7 = string.split_ss(t5, "-")
              if serverId >= toInt(t6) and serverId <= toInt(t7) then
                maxCount = math.max(toInt(t4[index]), 50)
                break
              end
            end
          end
        end
      end
    end
    local count = math.floor(bestCount / itemMaxCount)
    local level_group = {}
    for i = 1, count do
      table.insert(level_group, itemMaxCount * i)
    end
    if bestCount < maxCount then
      table.insert(level_group, maxCount)
    end
    self.level_group = level_group
    return
  end
  if para_7 and self.level_group == nil then
    if string.IsNullOrEmpty(para_8) then
      local level_group = {}
      for level in string.gmatch(para_7, "([^|]+)|?") do
        table.insert(level_group, toInt(level))
      end
      self.level_group = level_group
    else
      local serverId = LuaEntry.Player:GetSourceServerId()
      local para_7_list = string.split(para_7, ";")
      local para_8_list = string.split(para_8, ";")
      if #para_7_list == #para_8_list then
        for i, v in ipairs(para_8_list) do
          local strFrom, strTo = string.match(v, "([^-]+)-([^-]+)")
          if strFrom and strTo and serverId >= toInt(strFrom) and serverId <= toInt(strTo) then
            para_7 = para_7_list[i]
            if not string.IsNullOrEmpty(para_7) then
              local level_group = {}
              for level in string.gmatch(para_7, "([^|]+)|?") do
                table.insert(level_group, toInt(level))
              end
              self.level_group = level_group
            end
            break
          end
        end
      else
        para_7 = para_7_list[1]
        if not string.IsNullOrEmpty(para_7) then
          local level_group = {}
          for level in string.gmatch(para_7, "([^|]+)|?") do
            table.insert(level_group, toInt(level))
          end
          self.level_group = level_group
        end
      end
    end
  end
end

return SeasonFactionWarDataManager
