local this = {}

function this:req_changeFormationData(type, index, posData, callback)
  if not self:checkCanChangeFormation() then
    return
  end
  if type == self:getCurFormationType() and index == L_FormationStore:getUsingTeamIndex(type) and not self:checkCanChangeFormationHero(posData) then
    return
  end
  AzurWorld.formationMgr:ReqChangeFormationPosData(type, index, posData, function(errCode, rspData)
    if errCode == L_Const.errorCode.ErrCodeSucc and callback then
      callback()
    end
  end)
end

function this:switchGroup(teamType, teamIndex, callback)
  if not self:checkCanChangeFormation() then
    return
  end
  if not self:checkCanChangeFormationHero(L_FormationStore:getFormationPosData(teamType, teamIndex)) then
    return
  end
  AzurWorld.formationMgr:ReqChangeCurFormation(teamType, teamIndex, function(errCode, data)
    if errCode == L_Const.errorCode.ErrCodeSucc and callback then
      callback()
    end
  end)
end

function this:req_quickChangeGroup(formationType, formationIndex, wearPets, callback)
  if not self:checkCanChangeFormation() then
    return
  end
  local heroList = {}
  for i, wear in ipairs(wearPets) do
    table.insert(heroList, wear.hero_guid)
  end
  if not self:checkCanChangeFormationHero(heroList) then
    return
  end
  AzurWorld.formationMgr:ReqQuickFormation(formationType, formationIndex, wearPets, function(errCode, data)
    if errCode == L_Const.errorCode.ErrCodeSucc and callback then
      callback()
    end
  end)
end

function this:req_removeHero(formationType, formationIndex, posIndex, callback)
  local posData = L_FormationStore:getFormationPosData(formationType, formationIndex)
  local temp = table.clone(posData)
  temp[posIndex] = 0
  L_FormationManager:req_changeFormationData(formationType, formationIndex, temp, callback)
end

function this:req_addHero(formationType, formationIndex, posIndex, heroGuid, callback)
  local oriPlace = L_FormationStore:getHeroPlaceInTeam(formationType, formationIndex, heroGuid)
  local posData = L_FormationStore:getFormationPosData(formationType, formationIndex)
  local temp = table.clone(posData)
  if 0 < oriPlace then
    temp[oriPlace] = posData[posIndex]
  end
  temp[posIndex] = heroGuid
  L_FormationManager:req_changeFormationData(formationType, formationIndex, temp, callback)
end

function this:checkCanChangeFormation()
  if L_PlayerManager:inMountFly() then
    L_FlyMsgManager:showNormalMsg(L_Lang:get(L_WordsTpl:getValue("notice_dungeon_team_fly")))
    return false
  end
  return true
end

function this:checkCanChangeFormationHero(heroGuids)
  local allDie = true
  for i, guid in pairs(heroGuids) do
    if not math.isEmpty(guid) then
      local remainHp = L_FormationStore:getFormationHeroHp(guid)
      if 0 < remainHp then
        allDie = false
      end
    end
  end
  if allDie then
    self:showFormationTip(L_FormationConst.FormationTipType.NoAliveExist)
    return false
  end
  return true
end

function this:checkCanChangeFormationPet(petGuid, callback)
  if type(petGuid) == "number" then
    local petItem = L_PetStore:getPetItem(petGuid)
    local petGameplayStatus = petItem:getGameplayStatus()
    if petGameplayStatus == L_Const.PetState.PET_WORKING or petGameplayStatus == L_Const.PetState.PET_RESTING then
      L_GameUtil.showCommonTip({
        txtContent = L_WordsTpl:getValue("notice_qibo_confirm_farm_team"),
        confirmCallback = callback
      })
      return false
    end
  end
  return true
end

function this:checkCanReviveHeros()
  if L_DungeonStore:isExitingDungeon() then
    print("checkCanReviveHeros", "\230\173\163\229\156\168\233\128\128\229\135\186\229\137\175\230\156\172\239\188\140\228\184\141\232\131\189\229\164\141\230\180\187")
    return false
  end
  return true
end

function this:isRevivingHeros()
  return self.reviveHeroState ~= nil
end

function this:setReviveHeroState(state)
  self.reviveHeroState = state
  print("setReviveHeroState", state)
  local isForbid = state ~= nil
  local reason = CS.Lens.Framework.Managers.InputManager.EForbidInputReason.ReviveHeros
  C_InputManager.ForbidInput(isForbid, reason)
  local reason2 = CS.Lens.Gameplay.Modules.Azur.EForbidBattleSourceType.Reviving
  local C_WorldHelper = CS.Lens.Gameplay.Modules.Azur.WorldHelper
  if isForbid then
    C_WorldHelper.AddForbidBattleSourceType(reason2)
  else
    C_WorldHelper.RemoveForbidBattleSourceType(reason2)
  end
end

function this:rebornHeros(reviveHeros)
  if not reviveHeros then
    return
  end
  for _, uuid in ipairs(reviveHeros) do
    local curTeam = L_FormationStore:getFormationTeam(L_FormationManager:getCurFormationType())
    if curTeam ~= nil then
      local posData = L_FormationStore:getFormationPosData(L_FormationManager:getCurFormationType())
      for _, guid in pairs(posData) do
        if guid == uuid then
          if AzurWorld.playerMgr.myPlayerUnitAdapter then
            AzurWorld.playerMgr.myPlayerUnitAdapter:RecreateFormationEntity(uuid, 0)
          end
          break
        end
      end
    end
  end
end

function this:reviveHeros()
  if not self:checkCanReviveHeros() then
    return
  end
  self:setReviveHeroState("req_playerRevive")
  L_PlayerStore:req_playerRevive(function()
    self:setReviveHeroState(nil)
    if self.needReviveHeros == nil then
      return
    end
    local needRevive = false
    for _, uuid in ipairs(self.needReviveHeros) do
      local curTeam = L_FormationStore:getFormationTeam(L_FormationManager:getCurFormationType())
      if curTeam ~= nil then
        local posData = L_FormationStore:getFormationPosData(L_FormationManager:getCurFormationType())
        for _, guid in pairs(posData) do
          if guid == uuid then
            needRevive = true
            break
          end
        end
      end
    end
    if needRevive then
      AzurWorld.playerMgr.myPlayerUnitAdapter:SwitchOutMountMainControl(nil, true)
      AzurWorld.playerMgr.myPlayerUnitAdapter:RefreshFormation(nil, true)
      AzurWorld.playerMgr.myPlayerUnitAdapter:ResumePlayerUnit(nil, true)
    end
    self.needReviveHeros = nil
    if not self:checkCanReviveHeros() then
      return
    end
    self:setReviveHeroState("transfer")
    local curModule = L_WorldManager:getCurModule()
    if curModule == L_Const.worldModule.dungeon then
      AzurWorld.playerMgr:SetUnbelievableTime()
      self:setReviveHeroState(nil)
      return
    end
    local isSuccess, pointId = AzurWorld.TaskMgr:GetTaskTransPoint()
    if isSuccess then
      local _worldPointTpl = L_GameTpl:getWorldBorthposTpl()
      local tpl = _worldPointTpl:getTplById(pointId)
      local position = _worldPointTpl:getPosition(tpl)
      local rotation = _worldPointTpl:getRotation(tpl)
      AzurWorld.transferMgr:ClientTransferStartFlow(position, rotation, function()
        AzurWorld.playerMgr:SetUnbelievableTime()
        self:setReviveHeroState(nil)
      end)
    else
      local mapInfo = L_PlayerStore:getPlayerMapInfo()
      AzurWorld.transferMgr:ClientTransferStartFlow(mapInfo.position, mapInfo.rotation, function()
        AzurWorld.playerMgr:SetUnbelievableTime()
        self:setReviveHeroState(nil)
      end)
    end
  end)
end

return this
