local this = {}

function this:_getBattleConfigId(itemId, step)
  local worldMap_tpl = L_GameTpl:getWorldMapTpl():getTplById(AzurWorldInstance.CurWorldId, itemId)
  local worldTriggerId = L_GameUtil.getWorldTriggerId(L_GameTpl:getWorldMapTpl(), worldMap_tpl)
  if not math.isEmpty(worldTriggerId) then
    local triggerTpl = L_GameTpl:getWorldTriggerTpl():getTpl(worldTriggerId, step)
    local battleConfigId = L_GameTpl:getWorldTriggerTpl():getBattleConfigId(triggerTpl)
    return battleConfigId
  end
  return nil
end

function this:getBattleItem(itemId)
  local battleItem = {item_id = itemId, index = 0}
  local step = L_SceneStore:getSceneObj(itemId).curStep
  battleItem.step = step
  return battleItem
end

function this:req_dungeonBattle(itemId, callback)
  L_UI:backToRoot()
  local createBattleType = self:getCreateBattleType()
  if createBattleType then
    return
  end
  self:setCreateBattleType(L_Const.createBattleType.single)
  local data = {
    entry = L_Const.BattleEntryType.BET_BATTLE_COMPAIGN,
    type = L_Const.battleType.single,
    battle_campaign_obj = itemId
  }
  L_Net:sendMessage(MsgGenCode.CSProtoBattleCreate, data, function(rspData, errorCode)
    if errorCode == L_Const.errorCode.ErrCodeSucc then
      if callback then
        callback()
      end
    else
      self:setCreateBattleType(nil)
    end
  end)
end

function this:req_createMultiBattle(callback)
  printf("\231\187\132\233\152\159\230\136\152\230\150\151\230\154\130\230\151\182\228\184\141\232\128\131\232\153\145\239\188\140\228\187\163\231\160\129\229\183\178\230\179\168\233\135\138")
end

function this:rsp_createBattle(sData)
  errorf("\230\178\146\230\156\137\233\128\153\231\168\174\230\136\176\233\172\165\228\186\134")
end

function this:rsp_finHandle(sData)
end

function this:setBattleReward(rewardList)
  self.data.rewardList = rewardList
end

function this:setCatchReward(rewardList)
  self.data.catchRewardList = rewardList
end

function this:clearHeroDataCache()
  self.data.heroCache = nil
end

function this:req_battleFin(result, callback)
  self:call(self.event.battleFinStart)
  L_Net:sendMessage(MsgGenCode.CSProtoBattleFin, {res = result}, function(rspData, errorCode)
    if callback then
      callback(rspData, errorCode)
    end
  end)
end

function this:req_newBattleCreate(obj_ids, allGroups, objId, index)
  local createBattleType = self:getCreateBattleType()
  if createBattleType then
    return
  end
  self:setCreateBattleType(L_Const.createBattleType.single)
  local groups = {}
  for i = 1, #obj_ids do
    local objGroupKey = {}
    objGroupKey.obj_id = obj_ids[i]
    objGroupKey.battle_group_id = allGroups[i]
    table.insert(groups, objGroupKey)
    AzurWorld.service.map.LockObjState(obj_ids[i], AzurWorldInstance.CurWorldId)
  end
  local obj_key = {
    obj_id = objId,
    obj_index = index,
    group_id = 0
  }
  local data = {
    objs = groups,
    obj_keys = {obj_key}
  }
  self.heroUid = 0
  L_FlyMsgManager:showBattleCutInEffect()
  L_Net:sendMessage(MsgGenCode.CSProtoFightStart, data, function(rspData, errorCode)
    if errorCode == L_Const.errorCode.ErrCodeSucc then
      self:rsp_newBattleCreate(rspData)
    else
      L_BattleStore:setFightOver()
      for i = 1, #obj_ids do
        AzurWorld.service.map.UnlockObjState(obj_ids[i], AzurWorldInstance.CurWorldId)
      end
      self:setCreateBattleType(nil)
    end
  end)
end

function this:req_startTaskBattleToData(obj_ids, allGroups, taskId, objId, index)
  local createBattleType = self:getCreateBattleType()
  if createBattleType then
    return
  end
  self:setCreateBattleType(L_Const.createBattleType.single)
  local groups = {}
  for i = 1, #obj_ids do
    local objGroupKey = {}
    objGroupKey.obj_id = obj_ids[i]
    objGroupKey.battle_group_id = allGroups[i]
    objGroupKey.task_id = taskId
    table.insert(groups, objGroupKey)
  end
  local obj_key = {
    obj_id = objId,
    obj_index = index,
    group_id = 0
  }
  local data = {
    objs = groups,
    obj_keys = {obj_key}
  }
  self.heroUid = 0
  L_FlyMsgManager:showBattleCutInEffect()
  L_Net:sendMessage(MsgGenCode.CSProtoFightStart, data, function(rspData, errorCode)
    if errorCode == L_Const.errorCode.ErrCodeSucc then
      self:rsp_newBattleCreate(rspData)
    else
      L_BattleStore:setFightOver()
      for i = 1, #obj_ids do
        AzurWorld.service.map.UnlockObjState(obj_ids[i], AzurWorldInstance.CurWorldId)
      end
      self:setCreateBattleType(nil)
    end
  end)
end

function this:setFightOver()
  self.fightIdMap = nil
end

function this:rsp_newBattleCreate(sData)
  printf("\229\136\155\229\187\186\230\156\128\230\150\176\231\154\132\230\136\152\230\150\151:", sData)
  local battleId = sData.battle_id
  local obj_keys = sData.obj_keys
  local fightIdMap = {}
  local heroUid = {}
  local petUid = {}
  for i = 1, #sData.objs do
    local v = sData.objs[i]
    if v.obj_type == "FO_Monster" or v.obj_type == "FO_Task_Monster" then
      if fightIdMap[v.obj_key.obj_id] == nil then
        fightIdMap[v.obj_key.obj_id] = {}
      end
      fightIdMap[v.obj_key.obj_id][v.obj_key.obj_index] = v.uid
    elseif v.obj_type == "FO_Pet" then
      petUid[v.guid] = v.uid
    else
      heroUid[v.id] = v.uid
    end
  end
  self.fightIdMap = fightIdMap
  self.fightIdMap.heroUid = heroUid
  self.fightIdMap.petUid = petUid
  self:setBattleServerData(sData)
  self:call(self.event.battleStart)
  L_BattleManager:initWorldServerData()
  L_BattleManager:doFsmBattleField()
end

function this:getHeroUid(heroId)
  if heroId == nil then
    local mainHero = L_PlayerManager:getMainHeroEntity()
    if mainHero == nil then
      return 0
    end
    heroId = mainHero:getConfigId()
  end
  return self.fightIdMap == nil and 0 or self.fightIdMap.heroUid[heroId]
end

function this:rsp_fightFinish(sData, errorCode)
  printf("Finish.......:", sData)
  if sData == nil then
    C_BattleManager.ServerSetFinishType(C_EBattlerServerFinishType.ForceOut)
    self:call(self.event.serverFightFinish)
  else
    local itemList = sData.rewards and sData.rewards.rewards
    if not table.isEmpty(itemList) then
      L_BattleStore:setBattleReward(itemList)
    end
    C_BattleManager.ServerSetFinishType(sData.status)
    if sData.status == L_Const.FightFinishStatus.FFS_Success then
    elseif sData.status == L_Const.FightFinishStatus.FFS_Fail then
    elseif sData.status == L_Const.FightFinishStatus.FFS_Escape then
      L_FlyMsgManager:showNormalMsg(L_WordsTpl:getValue("notice_battleStore"))
    elseif sData.status == L_Const.FightFinishStatus.FFS_Timeout then
      L_FlyMsgManager:showNormalMsg(L_WordsTpl:getValue("notice_battle_time_out"))
    end
    self:call(self.event.serverFightFinish)
  end
end

function this:req_reqFightEscape()
  L_Net:sendMessage(MsgGenCode.CSProtoFightEscape)
end

function this:rsp_syncBattleHeroInfo(sData)
  if sData == nil or sData.heros == nil then
    return
  end
  for i = 1, #sData.heros do
    local hero = sData.heros[i]
    local attrData = hero.attrs and hero.attrs.attrs or {}
    local winfoAttr
    if hero.winfo ~= nil then
      winfoAttr = hero.winfo.attrs.attrs
    end
    local oinfoAttr
    if hero.oinfo ~= nil then
      local oinfo = hero.oinfo
      oinfoAttr = {}
      for i = 1, #oinfo do
        local o = oinfo[i].attrs
        if o.attrs ~= nil then
          for j = 1, #o.attrs do
            local oa = o.attrs[j]
            if oinfoAttr[oa.attr_id] == nil then
              table.insert(oinfoAttr, {
                attr_id = oa.attr_id,
                attr_val = oa.attr_val
              })
            else
              oinfoAttr[oa.attr_id].attr_val = oinfoAttr[oa.attr_id].attr_val + oa.attr_val
            end
          end
        end
      end
    end
    local subAttrs = {
      winfoAttr or {},
      oinfoAttr or {},
      hero.buffs and hero.buffs.attrs or {}
    }
  end
end

function this:rsp_syncObjBattleInfo(data)
  if data == nil then
    return
  end
  local needReviveHeros, reviveHero
  local infos = data.infos
  for i, info in pairs(infos) do
    local lastInfo = self.data.objBattleInfo[info.uuid]
    if lastInfo and lastInfo.hp and lastInfo.hp <= 0 and info.hp > 0 then
      reviveHero = reviveHero or {}
      table.insert(reviveHero, info.uuid)
    end
    self.data.objBattleInfo[info.uuid] = info
    if info.reason == L_Const.HeroBattleInfoSyncReason.HBISR_TRANS_POINT or info.reason == L_Const.HeroBattleInfoSyncReason.HBISR_CHARGE then
      L_StarHealingStore:call(L_StarHealingStore.event.playStarHealingEffect, info.uuid)
    elseif info.reason == L_Const.HeroBattleInfoSyncReason.HBISR_ACED then
      if needReviveHeros == nil then
        needReviveHeros = {}
      end
      table.insert(needReviveHeros, info.uuid)
    end
  end
  if needReviveHeros ~= nil then
    L_FormationManager.needReviveHeros = needReviveHeros
  end
  if reviveHero ~= nil then
    L_FormationManager:rebornHeros(reviveHero)
  end
end

function this:rsp_syncObjBattleInfoByHurt(data)
  if data == nil then
    return
  end
  local hurt = data.hurt or {}
  for i, v in pairs(hurt) do
    self.data.objBattleInfo[v.tar_id] = {
      hp = v.cur_hp,
      sp = v.sp,
      uuid = v.tar_id
    }
  end
end

return this
