local this = class("cellBattleBossHp", G_UIModuleBase)
local enumPetBreakLinkStatus = {
  disable = 0,
  init = 1,
  ready = 2
}
local listCountToLimit = {
  [1] = {stack = 7, buff = 7},
  [2] = {stack = 6, buff = 3},
  [3] = {stack = 4, buff = 2}
}
local _enemyTpl = L_GameTpl:getEnemyTpl()
local _petTpl = L_GameTpl:getPetTpl()

function this.bind()
  return {
    moduleBuff = {
      moduleName = "pages/battle/moduleBattleBuff_Boss"
    },
    moduleBuffInfo = {
      moduleName = "pages/battle/moduleBattleBuffInfoBox"
    },
    txt_name = "",
    txt_nameFX = "",
    txt_level = "",
    go_break = false,
    txt_break = "",
    txt_break_bg = "",
    go_breakTxt = false,
    go_noBreak = false,
    go_infoBox = false,
    anim_break_playAnimation = "anim_battle_HP_petlink_init",
    goCatch = false,
    elementList = {
      moduleName = "pages/battle/cellBattleElement"
    },
    list_bossHpPoint = {
      moduleName = "pages/Battle/cellBossHpPoint"
    }
  }
end

function this.methods()
  return {
    moduleBuff = {
      onEnter = function(self, buffId, elementType, layer)
        self.bind.go_infoBox = true
        self.modules.moduleBuffInfo:initModuleInfo(buffId, layer, elementType)
      end,
      onLeave = function(self)
        self.bind.go_infoBox = false
      end
    }
  }
end

function this:open()
  self.isNotShowHp = false
end

function this:show()
  self.noBreakFlag = nil
  self.bind.go_noBreak = false
  if self.isNotShowHp then
    self.bindComponents.bossHpTypeAnim:Play("anim_battle_bossHp_switch2Shield")
  end
end

function this:toBind(uiBinding)
  self.super.toBind(self, uiBinding)
  self.noBreakFlag = false
  self.breakLinkStatus = enumPetBreakLinkStatus.disable
  self.preBreakPosZero = C_Vector2(0, 0)
  self.preBreakAnchorV2 = C_Vector2(0, 0.5)
  self.catchAnchorV2 = C_Vector2(0, 0.5)
  self.lastEnemyEntityId = -1
  self.onRefreshHPHandle = self.onRefreshHPHandle or handler(self, self.refreshHP)
  self.updateHandle = handler(self, self.updateFunc)
  C_UpdateSource.AddUpdateEventHandler(self.updateHandle, "cellBattleBossHp.update")
  L_BattleDataManager:addListener(L_BattleDataManager.event.addShield, self.onEvent_addShield, self)
  L_BattleDataManager:addListener(L_BattleDataManager.event.refreshShield, self.onEvent_refreshShield, self)
  L_BattleDataManager:addListener(L_BattleDataManager.event.removeShield, self.onEvent_removeShield, self)
  L_BattleDataManager:addListener(L_BattleDataManager.event.bossHpIndexChange, self.onEvent_bossHpIndexChange, self)
end

function this:unBind()
  self.super.unBind(self)
  local enemyEntity = C_EntityManager.GetAliveEntity(self.enemyEntityId)
  if enemyEntity then
    enemyEntity.data.aliveProperty.statusChangeEvent:Remove(self.onRefreshHPHandle)
  end
  C_UpdateSource.RemoveUpdateEventHandler(self.updateHandle)
  L_BattleDataManager:removeListener(L_BattleDataManager.event.addShield, self.onEvent_addShield)
  L_BattleDataManager:removeListener(L_BattleDataManager.event.refreshShield, self.onEvent_refreshShield, self)
  L_BattleDataManager:removeListener(L_BattleDataManager.event.removeShield, self.onEvent_removeShield)
  L_BattleDataManager:removeListener(L_BattleDataManager.event.bossHpIndexChange, self.onEvent_bossHpIndexChange, self)
end

function this:onEvent_addShield(args)
  if self.enemyEntityId ~= args.entityId then
    return
  end
  if self.isNotShowHp ~= true then
    self.bindComponents.bossHpTypeAnim:Play("anim_battle_bossHp_switch2Shield")
  end
  self.bindComponents.shieldBarEffectShow:InitHp(1)
  self.isNotShowHp = true
end

function this:onEvent_refreshShield(args)
  if self.enemyEntityId ~= args.entityId then
    return
  end
  self.bindComponents.shieldBarEffectShow:SetHp(args.floatArg)
end

function this:onEvent_removeShield(args)
  if self.enemyEntityId ~= args.entityId then
    return
  end
  self.bindComponents.bossHpTypeAnim:Play("anim_battle_bossHp_switch2Hp")
  self.isNotShowHp = false
end

function this:onEvent_bossHpIndexChange(args)
  if self.enemyEntityId ~= args.entityId then
    return
  end
  local entity = C_EntityManager.GetAliveEntity(self.enemyEntityId)
  self:initHp(entity)
  self:refreshBossHpPointList(entity)
end

function this:initBoss(enemyId, listCount)
  self.listCount = listCount
  if self.lastEnemyEntityId ~= enemyId then
    local lastEntity = C_EntityManager.GetAliveEntity(self.lastEnemyEntityId)
    if lastEntity then
      lastEntity.data.aliveProperty.statusChangeEvent:Remove(self.onRefreshHPHandle)
    end
    if self.listCount == 1 then
      self.bindComponents.bossHpTypeAnim:Play("anim_battle_bossHp_show")
    else
      self.bindComponents.bossHpTypeAnim:Play("anim_battle_bossHp_show_simple")
    end
    self.lastEnemyEntityId = enemyId
    local enemyEntity = C_EntityManager.GetAliveEntity(enemyId)
    if enemyEntity then
      enemyEntity.data.aliveProperty.statusChangeEvent:Add(self.onRefreshHPHandle)
    end
  end
  self.enemyEntityId = enemyId
  local entity = C_EntityManager.GetAliveEntity(enemyId)
  self.configId = entity.data.config.id
  local tpl = _enemyTpl:getTplById(self.configId)
  local isShowWeak = _enemyTpl:getHpBarWeakness(tpl)
  self.bind.go_break = isShowWeak
  local monsterName = entity.data.configName
  if entity.data.SpecialParam > 0 and entity.data.catchProperty then
    local spName = entity.data.catchProperty.catchPet:GetPetNameSp(entity.data.SpecialParam - 1)
    if spName ~= nil then
      monsterName = spName.value
    end
  end
  self.bind.txt_name = monsterName
  self.bind.txt_nameFX = monsterName
  self.bind.txt_level = tostring(entity.data.level)
  local showStackCount = self.listCount >= 3 and 5 or 7
  self.modules.moduleBuff:initBuff(entity, listCountToLimit[listCount].stack, listCountToLimit[listCount].buff, false, showStackCount)
  self.modules.moduleBuff:SetHPType(self.listCount)
  self:initHp(entity)
  self:refreshBossHpPointList(entity)
  local pet = _petTpl:getTplById(_enemyTpl:getPetId(tpl))
  self.bind.goCatch = 0 < _enemyTpl:getPetId(tpl) and _petTpl:getIsCatch(pet) == true
  local element = _enemyTpl:getElement(tpl)
  local elementListData = {}
  for _, elementId in ipairs(element) do
    local element = {elementId = elementId}
    table.insert(elementListData, element)
  end
  self.bind.elementList:clear()
  self.bind.elementList:insert_array(elementListData)
end

function this:initHp(csEntity)
  local aliveProperty = csEntity.data.aliveProperty
  local hp = C_MyFloatUtility.GetFloat(aliveProperty.hp)
  local maxHp = C_MyFloatUtility.GetFloat(aliveProperty.maxHp)
  self.bind.txt_hp = math.floor(hp) .. "/" .. math.floor(maxHp)
  self.bindComponents.hpEffectShow:InitHp(hp / maxHp)
  self.bindComponents.hpEffectShow:SetCatchIconData(csEntity.data)
  self.bindComponents.hpEffectShow:SetHpData(hp)
end

function this:refreshBossHpPointList(csEntity)
  local aliveProperty = csEntity.data.aliveProperty
  local info = {}
  for i = 1, aliveProperty.hpCount do
    table.insert(info, {
      active_point = aliveProperty.hpIndex <= i - 1,
      active_curPoint = aliveProperty.hpIndex == i - 1
    })
  end
  self.bind.list_bossHpPoint:clear()
  self.bind.list_bossHpPoint:insert_array(info)
end

function this:updateFunc()
  if self.enemyEntityId == nil then
    return
  end
  if self.bind.go_break then
    self:refreshWeak()
  end
  self:refreshPreBreak()
  self:refreshCatchIcon()
end

function this:doNoBreak(flag, aliveProperty)
  if self.noBreakFlag == flag then
    return
  end
  self.noBreakFlag = flag
  if flag then
    self:refreshBreakTxt(aliveProperty)
    self.bind.go_noBreak = flag
    self.bind.go_breakTxt = flag
    self.bindComponents.emptyWeakAnim:Stop()
    self.bindComponents.emptyWeakAnim:Play("anim_battle_bossBreak_icon_show")
    self.bindComponents.breakAnim:Stop()
    self.bindComponents.breakAnim:Play("anim_damagemult_show")
  else
    self.bindComponents.emptyWeakAnim:Stop()
    self.bindComponents.emptyWeakAnim:Play("anim_battle_bossBreak_icon_hide")
    self.bindComponents.breakAnim:Stop()
    self.bindComponents.breakAnim:Play("anim_damagemult_hide")
    Timer.once(0.2, function()
      self.bind.go_breakTxt = false
    end)
  end
end

function this:refreshBreakTxt(aliveProperty)
  local percent = C_MyFloatUtility.GetFloat(aliveProperty.breakDmgUp) * 100 + 100
  local breakText = string.format("x%d%%", percent)
  self.bind.txt_break = breakText
  self.bind.txt_break_bg = breakText
end

function this:refreshWeak()
  local enemy = C_EntityManager.GetAliveEntity(self.enemyEntityId)
  if not enemy then
    return
  end
  local aliveProperty = enemy.data.aliveProperty
  local inWeak = enemy.data.controlProperty.inWeakState
  local weakPoint = C_MyFloatUtility.GetFloat(aliveProperty.weaknessPoint)
  local weaknessPointMax = C_MyFloatUtility.GetFloat(aliveProperty.weaknessPointMax)
  if self.weakPoint and weakPoint < self.weakPoint then
    self.bindComponents.breakEffectShow:SetHp(weakPoint / weaknessPointMax)
  elseif self.weakPoint ~= weakPoint then
    self.bindComponents.breakEffectShow:InitHp(weakPoint / weaknessPointMax)
  end
  self.weakPoint = weakPoint
  self.inWeak = inWeak
  self:doNoBreak(enemy.data.controlProperty.inWeakState, aliveProperty)
end

function this:refreshHP(arg1, arg2)
  if arg1 ~= 0 and arg1 ~= 2 then
    return
  end
  local enemy = C_EntityManager.GetAliveEntity(self.enemyEntityId)
  if not enemy then
    return
  end
  local aliveProperty = enemy.data.aliveProperty
  local hp = C_MyFloatUtility.GetFloat(aliveProperty.hp)
  local maxHp = C_MyFloatUtility.GetFloat(aliveProperty.maxHp)
  self.bindComponents.hpEffectShow:SetHp(hp / maxHp)
  self.bindComponents.hpEffectShow:SetHpData(hp)
end

function this:changeBreakLinkStatus(status)
  if self.breakLinkStatus ~= status then
    if status == enumPetBreakLinkStatus.disable then
      self.bindComponents.preBreakNode.gameObject:SetActive(false)
    elseif status == enumPetBreakLinkStatus.init then
      self.bindComponents.preBreakNode.gameObject:SetActive(true)
      self.bind.anim_break_playAnimation = "anim_battle_HP_petlink_init"
    elseif status == enumPetBreakLinkStatus.ready then
      self.bindComponents.preBreakNode.gameObject:SetActive(true)
      if self.breakLinkStatus == enumPetBreakLinkStatus.disable then
        self.bind.anim_break_playAnimation = "anim_battle_HP_petlink_ready_change"
      else
        self.bind.anim_break_playAnimation = "anim_battle_HP_petlink_ready"
      end
    end
    self.breakLinkStatus = status
  end
end

function this:refreshPreBreak()
  local enemy = C_EntityManager.GetAliveEntity(self.enemyEntityId)
  if not enemy then
    return
  end
  local bossData = enemy.data
  local preBreakThreshold = C_MyFloatUtility.GetFloat(bossData.aliveProperty.preBreakThreshold)
  local weaknessPointMax = C_MyFloatUtility.GetFloat(bossData.aliveProperty.weaknessPointMax)
  local weaknessPoint = C_MyFloatUtility.GetFloat(bossData.aliveProperty.weaknessPoint)
  if preBreakThreshold <= 0 or bossData.controlProperty.inWeakState then
    self:changeBreakLinkStatus(enumPetBreakLinkStatus.disable)
  elseif preBreakThreshold > weaknessPoint then
    self:changeBreakLinkStatus(enumPetBreakLinkStatus.ready)
  else
    self.preBreakAnchorV2.x = preBreakThreshold / weaknessPointMax
    self.bindComponents.preBreakIcon.anchorMin = self.preBreakAnchorV2
    self.bindComponents.preBreakIcon.anchorMax = self.preBreakAnchorV2
    self.bindComponents.preBreakIcon.anchoredPosition = self.preBreakPosZero
    self:changeBreakLinkStatus(enumPetBreakLinkStatus.init)
  end
end

function this:refreshCatchIcon()
  local enemy = C_EntityManager.GetAliveEntity(self.enemyEntityId)
  if not enemy then
    return
  end
  self.configId = enemy.data.config.id
  local tpl = _enemyTpl:getTplById(self.configId)
  local petId = _enemyTpl:getPetId(tpl)
  if petId == 0 then
    return
  end
  local pet = _petTpl:getTplById(petId)
  if pet == nil then
    return
  end
  local hp = _petTpl:getCatchHP(pet)
  self.catchAnchorV2.x = hp / 10000
  self.bindComponents.catchIcon.anchorMin = self.catchAnchorV2
  self.bindComponents.catchIcon.anchorMax = self.catchAnchorV2
  self.bindComponents.catchIcon.anchoredPosition = self.preBreakPosZero
end

function this:close()
  self.lastEnemyEntityId = -1
end

return this
