local this = class("cellStackElement", G_UIModuleBase)
local _buffInfoTpl = L_GameTpl:getBuffInfoTpl()
local _battleDamageTpl = L_GameTpl:getBattleDamagetextTpl()
local _elementTypeTpl = L_GameTpl:getElementTypeTpl()
local BorderGMNormalPath = "UI/Atlas/BuffS/tex_battle_bar_gm1.png"
local BorderGMOverPath = "UI/Atlas/BuffS/tex_battle_bar_gm2.png"
local BorderCXNormalPath = "UI/Atlas/BuffS/tex_battle_bar_cx1.png"
local BorderCXOverPath = "UI/Atlas/BuffS/tex_battle_bar_cx2.png"
local BgGMNormalPath = "UI/Atlas/BuffS/tex_battle_bg_gm1.png"
local BgGMOverPath = "UI/Atlas/BuffS/tex_battle_bg_gm2.png"
local BgCXNormalPath = "UI/Atlas/BuffS/tex_battle_bg_cx1.png"
local BgCXOverPath = "UI/Atlas/BuffS/tex_battle_bg_cx2.png"
local LayerNumPath = "UI/Atlas/BuffS/tex_battle_word_cxgm%d.png"
local fxMatBattleElement = {
  "UI_FX/Battle/Hud/mat_battle_element_fx_huo",
  "UI_FX/Battle/Hud/mat_battle_element_fx_feng",
  "UI_FX/Battle/Hud/mat_battle_element_fx_di",
  "UI_FX/Battle/Hud/mat_battle_element_fx_mu",
  "UI_FX/Battle/Hud/mat_battle_element_fx_shui",
  "UI_FX/Battle/Hud/mat_battle_element_fx_guang",
  "UI_FX/Battle/Hud/mat_battle_element_fx_an"
}
local BgBattleElement = {
  "UI/Page/BattleHpBar/tex_battle_icon_echobg_2_fire.png",
  "UI/Page/BattleHpBar/tex_battle_icon_echobg_2_wind.png",
  "UI/Page/BattleHpBar/tex_battle_icon_echobg_2_earth.png",
  "UI/Page/BattleHpBar/tex_battle_icon_echobg_2_wood.png",
  "UI/Page/BattleHpBar/tex_battle_icon_echobg_2_ice.png",
  "UI/Page/BattleHpBar/tex_battle_icon_echobg_2_water.png",
  "UI/Page/BattleHpBar/tex_battle_icon_echobg_2_thunder.png",
  "UI/Page/BattleHpBar/tex_battle_icon_echobg_2_light.png",
  "UI/Page/BattleHpBar/tex_battle_icon_echobg_2_dark.png"
}
local animator_param_big = "Big"
local animator_param_small = "Small"
local animator_param_initBig = "InitBig"
local animator_param_initSmall = "InitSmall"
local animator_param_mid = "Mid"
local animator_param_initMid = "InitMid"
local StackElementStep = {
  NORMAL = 1,
  OVER = 2,
  MAX = 3
}

function this.bind()
  return {
    img_icon = "",
    img_bgNormal = BgGMNormalPath,
    effect_fx = ""
  }
end

function this.methods()
  return {}
end

function this:open()
  self._buffNum = 0
  self._currStep = StackElementStep.NORMAL
  self._curLayer = 0
  self._currLevel = 0
  L_TimerManager:newOrResetTimer(self, "initAni", function()
    self:setSameElement(self.bind.element)
    self:refreshShowView(true, true)
  end, 0.01)
end

function this:setSameElement(element)
  self.element = element
  self:refresh()
end

function this:close()
  self:resetHandle()
  self:clearAniObjs()
  L_TimerManager:stopTimer(self, "initAni")
end

function this:resetHandle()
  if not self.element then
    return
  end
  self.element.onStackElementLayerChange:Remove(self.onStackElementLayerChangeHandle)
end

function this:setHandle()
  self.onStackElementLayerChangeHandle = self.onStackElementLayerChangeHandle or handler(self, function(self, value)
    self:refreshShowView()
  end)
  self.element.onStackElementLayerChange:Add(self.onStackElementLayerChangeHandle)
end

function this:refresh()
  self:resetHandle()
  if self.bind.addNum then
    if self._buffNum ~= self.bind.addNum then
      self._buffNum = self.bind.addNum
      self.bindComponents.addAni:Play("anim_battle_buff_addNum", CS.UnityEngine.PlayMode.StopAll)
    end
    return
  end
  if self._buffNum > 0 then
    self._buffNum = 0
  else
  end
  if not self.element or self.element.free then
    return
  end
  self._curLayer = self.element.numberLayers
  self:setHandle()
  local elementConfigId = self.element.config.elementConfigId
  local tpl = _buffInfoTpl:getTplById(elementConfigId)
  local type = _buffInfoTpl:getType(tpl)
  local elementId = self.element.elementId
  local config = _battleDamageTpl:getTplById(elementId)
  local elemenType = _elementTypeTpl:getTplById(config.element)
  self.bind.img_icon = _elementTypeTpl:getPetPuzzleIcon(elemenType, 1)
  self.bind.img_bgNormal = BgBattleElement[config.element]
  self:refreshShowView()
end

function this:getStep(num)
  if num < 50 then
    return StackElementStep.NORMAL
  elseif num < 100 then
    return StackElementStep.OVER
  else
    return StackElementStep.MAX
  end
end

function this:refreshShowView(force, noAni)
  if self._animating and not force then
    return
  end
  if self.bind.addNum then
    return
  end
  local elementConfigId = self.element.config.elementConfigId
  local tpl = _buffInfoTpl:getTplById(elementConfigId)
  local type = _buffInfoTpl:getType(tpl)
  local notDebuff = type == L_Const.buffType.stackBuff
  local lastStep = self:getStep(self._curLayer)
  local lastLayer = self._curLayer
  local currLayer = math.max(self.element.numberLayers, 0)
  if self._curLayer == currLayer and not force then
    return
  end
  L_TimerManager:stopTimer(self, "ani")
  self._curLayer = currLayer
  local currStep = self:getStep(currLayer)
  local lastLevel = self._currLevel
  local currLevel = math.floor(currLayer / 10)
  self._currLevel = currLevel
  local elementConfigId = self.element.config.elementConfigId
  local tpl = _buffInfoTpl:getTplById(elementConfigId)
  local stage = _buffInfoTpl:getStages(tpl)
  if lastStep < currStep and currStep == StackElementStep.OVER and not noAni then
    self:playStepAni(StackElementStep.OVER)
    return
  end
  if lastStep > currStep and lastStep == StackElementStep.MAX and not noAni then
    self:playStepAni(StackElementStep.MAX)
    return
  end
  local isOver = self.element:GetLayerType() == 1
  local targetFill = math.min(currLayer < 100 and currLayer % 10 / 10 or 1)
  local numImgName = stage == 1 and 0 < currLevel and string.format(LayerNumPath, currLayer < 100 and currLevel % 5 or 5) or ""
  if noAni or currLevel == 10 then
    return
  end
  if lastLevel < currLevel then
    self:stopTween()
  elseif lastLevel > currLevel then
    L_TimerManager:newOrResetTimer(self, "ani", function()
      L_TimerManager:newOrResetTimer(self, "ani", function()
        self:stopTween()
      end, 0.066)
    end, 0.033)
  else
    self:stopTween()
  end
end

function this:playStepAni(step)
  self:clearAniObjs()
  self._animating = true
  if step == StackElementStep.OVER then
    L_TimerManager:newOrResetTimer(self, "ani", function()
      self._animating = false
      self:refreshShowView(true)
    end, 0.429)
  else
    L_TimerManager:newOrResetTimer(self, "ani", function()
      self:stopTween()
    end, 0.5)
  end
end

function this:stopTween()
end

function this:clearAniObjs()
  L_TimerManager:clearTimer(self)
  self:stopTween()
end

return this
