local this = class("modulePetCatalog", G_UIModuleBase)
local _petTpl = L_GameTpl:getPetTpl()
local _petGradeTpl = L_GameTpl:getPetGradeTpl()
local GifPath = "UI/Texture/PetPixelIcon/tex_icon_pet_%s_%d.png"
local _aniFlowFuncs = {
  petGrowth = {
    "initPage",
    "initExpChange",
    "initGetLvChange"
  },
  getPet = {
    "initGetPage",
    "initGetExpChange",
    "initGetLvChange"
  }
}
local _aniTime = {
  getPet = {
    1.865,
    1.135,
    1.25
  },
  getPetLevelUp = {
    1.865,
    0.8989,
    1.4861
  },
  petGrowth = {
    1.327,
    1.135,
    1.25
  },
  petGrowthLevelUp = {
    1.327,
    1.135,
    1.25
  }
}

function this:bind()
  return {
    module_pixelIcon = {
      moduleName = "pages/pet/modulePetPixelIcon"
    },
    txt_name = "",
    txt_task = "",
    img_taskLevel = "",
    txt_taskLevel = "",
    txt_taskExp = "",
    sliderExp = 0,
    txtTaskActive = true,
    imgTaskLevelActive = true,
    txtTaskLevelActive = true,
    sliderActive = true,
    bottomHintActive = true,
    topInfoActive = false,
    ratingImgActive = false,
    img_rating = "",
    txt_rating = "",
    txt_topDesc = "",
    img_icon = "",
    img_base = "",
    img_icon_effect = "",
    activeIconEffect = false,
    activeBaseEffect = false,
    checkTipsActive = true,
    partShortKeyActive = true,
    starBlue = true,
    starMax = false
  }
end

function this.methods()
  return {}
end

function this:open(options)
  self.super.open(self, options)
  if not options then
    return
  end
  self.gameObject:SetActive(true)
  self.options = options
  self.aniState = 0
  self.tipInfo = options.tipInfo or {}
  if self.tipInfo.isGetPet then
    self:showCutKey()
    self.curAniFlow = _aniFlowFuncs.getPet
  else
    self.curAniFlow = _aniFlowFuncs.petGrowth
  end
  self:setShortKeyVisible(self.tipInfo.isGetPet)
  self:countDownTool()
end

function this:showCutKey()
  if not L_DeviceTpl:getIsPc() then
    return
  end
  L_ShortCutManager:addListener(L_ShortCutConst.event.PetCatalog, self.shortKeyClick, self)
  L_ShortCutManager:addShortKeyFlag(self, "I", L_Const.AnchorType.Middle, self.bindComponents.ShortKey, L_Vector3.new(-211, 0))
end

function this:shortKeyClick()
  if self.tipInfo.isGetPet then
    local petItem = L_PetStore:getPetItem(self.tipInfo.pet.guid)
    L_PetManager:getTempRenderTexture(function(tempTex)
      L_UI:open("pageGetPet", {
        pet = petItem,
        showType = L_Const.getPetShowType.short,
        texture = tempTex
      })
    end)
  end
  self:doClose()
end

function this:setShortKeyVisible(isVisible)
  self.bind.checkTipsActive = isVisible
  self.bind.partShortKeyActive = isVisible
end

function this:close()
  if self.lvTimer1 then
    Timer.remove(self.lvTimer1)
    self.lvTimer1 = nil
  end
  if self.lvTimer2 then
    Timer.remove(self.lvTimer2)
    self.lvTimer2 = nil
  end
  self.gameObject:SetActive(false)
  L_TimerManager:clearTimer(self)
  if L_DeviceTpl:getIsPc() then
    L_ShortCutManager:removeListener(L_ShortCutConst.event.PetCatalog, self.shortKeyClick, self)
    L_ShortCutManager:clearShortKeyFlag(self)
  end
  if self.closeCB then
    self.closeCB(self.options)
  end
end

function this:setCloseCB(closeCB)
  self.closeCB = closeCB
end

function this:initPage()
  self.bind.topInfoActive = false
  self.bind.ratingImgActive = false
  self.bind.activeIconEffect = false
  self.bind.activeBaseEffect = false
  self.modules.module_pixelIcon:setConfigId(self.tipInfo.petId)
  self.bind.txt_name = _petTpl:getName(_petTpl:getTplById(self.tipInfo.petId))
  local length = self.bindComponents.txt_petName.preferredWidth
  local size_x = math.clamp(length - 104 + 470, 470, 570)
  self.bindComponents.img_bgTrans.sizeDelta = L_Vector3.new(size_x, 60)
  self.bind.txt_task = self.tipInfo.newTaskTxt
  self.bindComponents.anim:Stop()
  self.bindComponents.anim:Play("anim_petget_tips_show_2")
  self.bindComponents.moduleAnim:Stop()
  self.bindComponents.moduleAnim:Play("anim_catalog_tips_show_2")
end

function this:initExpChange()
  local levelTpl = L_GameTpl:getIconographyLevelTpl():getTplByLvPetId(self.tipInfo.oldLv, self.tipInfo.petId)
  self.bind.img_taskLevel = levelTpl.iconparticulars
  self.bind.txt_taskLevel = levelTpl.text
  self.expNumCache = self.tipInfo.oldExp
  self.bind.txt_taskExp = tostring(self.tipInfo.oldExp) .. "/" .. levelTpl.exp
  self.bind.sliderExp = self.tipInfo.oldExp / levelTpl.exp
  self:playAchievementAni()
end

function this:initGetPage()
  if table.isEmpty(self.tipInfo.pet) then
    return
  end
  self.bind.topInfoActive = true
  self.bind.ratingImgActive = true
  local property = L_PetStore:getPetOriginalProperty(self.tipInfo.pet)
  local gradeTpl = _petGradeTpl:getTplById(property.gradeRank)
  self.bind.img_rating = _petGradeTpl:getIcon(gradeTpl)
  self.bind.txt_rating = tostring(property.grade)
  self.bind.txt_name = string.format("Lv.%d %s", self.tipInfo.pet.lv, self.tipInfo.pet.pet_name)
  self.modules.module_pixelIcon:setGuid(self.tipInfo.pet.guid)
  self.modules.module_pixelIcon:outLineShow(false)
  local length = self.bindComponents.txt_petName.preferredWidth
  local size_x = math.clamp(length - 104 + 470, 470, 570)
  self.bindComponents.img_bgTrans.sizeDelta = L_Vector3.new(size_x, 60)
  self.bind.activeIconEffect = true
  self.bind.activeBaseEffect = true
  local tpl = _petTpl:getTplById(self.tipInfo.pet.id)
  self.bind.img_icon = _petTpl:getPetPixelIcon(tpl, self.tipInfo.pet:isSpecialPet())
  self.bind.img_base = _petGradeTpl:getPetPixelBase(gradeTpl)
  self._initFrameIcon = self.bind.img_icon
  self._curFrame = 1
  self._defaultPixelId = string.match(self._initFrameIcon, "%a*%d+")
  local iconPath = string.format(GifPath, self._defaultPixelId, self._curFrame)
  self.bind.img_icon_effect = iconPath
  self.bind.txt_task = self.tipInfo.newTaskTxt
  self.bindComponents.anim:Stop()
  self.bindComponents.anim:Play("anim_petget_tips_show")
  self.bindComponents.moduleAnim:Stop()
  self.bindComponents.moduleAnim:Play("anim_catalog_tips_show")
end

function this:initGetExpChange()
  local levelTpl = L_GameTpl:getIconographyLevelTpl():getTplByLvPetId(self.tipInfo.oldLv, self.tipInfo.petId)
  self.expNumCache = self.tipInfo.oldExp
  self.bind.img_taskLevel = levelTpl.iconparticulars
  self.bind.txt_taskLevel = levelTpl.text
  self.bind.txt_taskExp = tostring(self.tipInfo.oldExp) .. "/" .. levelTpl.exp
  self.bind.sliderExp = self.tipInfo.oldExp / levelTpl.exp
  self:playAchievementAni()
end

function this:initGetLvChange()
  local levelTpl = L_GameTpl:getIconographyLevelTpl():getTplByLvPetId(self.tipInfo.catalogLv, self.tipInfo.petId)
  self.bindComponents.moduleAnim:Stop()
  self.bindComponents.moduleAnim:Play("anim_catalog_tips_levelup")
  self.bind.starBlue = self.tipInfo.catalogLv ~= 10
  self.bind.starMax = self.tipInfo.catalogLv == 10
  self.lvTimer1 = Timer.once(0.0666, function()
    self.bind.img_taskLevel = levelTpl.iconparticulars
    self.bind.txt_taskLevel = levelTpl.text
    self.bind.txt_taskExp = tostring(0)
    self.bind.sliderExp = 0
  end)
  self.lvTimer2 = Timer.once(0.1665, function()
    self.tweenFunc()
    self.tween2Func()
  end)
  self.bind.sliderExp = self.tipInfo.newExp / levelTpl.exp
end

function this:countDownTool()
  self.aniState = self.aniState + 1
  local flowFuncName = self.curAniFlow[self.aniState]
  if flowFuncName ~= nil then
    local flowFunc = self[flowFuncName]
    if flowFunc ~= nil then
      flowFunc(self)
    else
    end
  else
  end
  local func = function()
    local nextFlowFuncName = self.curAniFlow[self.aniState + 1]
    if nextFlowFuncName == nil or self.aniState == 2 and not self.tipInfo.isLvChange then
      self:doClose()
    else
      local nextFlowFunc = self[nextFlowFuncName]
      if nextFlowFunc == nil then
        self:doClose()
      else
        self:countDownTool()
      end
    end
  end
  local animGroup
  if self.tipInfo.isGetPet then
    if self.isLvChange then
      animGroup = "getPetLevelUp"
    else
      animGroup = "getPet"
    end
  elseif self.isLvChange then
    animGroup = "petGrowthLevelUp"
  else
    animGroup = "petGrowth"
  end
  L_TimerManager:newOrResetTimer(self, "timeTick" .. self.aniState, func, _aniTime[animGroup][self.aniState])
end

function this:playAchievementAni()
  local levelTpl = L_GameTpl:getIconographyLevelTpl():getTplByLvPetId(self.tipInfo.oldLv, self.tipInfo.petId)
  local getter = function()
    return self.bind.sliderExp
  end
  local setter = function(r)
    self.bind.sliderExp = r
  end
  local getter2 = function()
    return self.expNumCache
  end
  local setter2 = function(r)
    self.expNumCache = math.round(r)
    self.bind.txt_taskExp = tostring(self.expNumCache) .. "/" .. levelTpl.exp
  end
  if self.tipInfo.isLvChange then
    local target = 1
    self.tween = DOTween.To(getter, setter, target, 1)
    
    function self.tweenFunc()
      local nextLevelTpl = L_GameTpl:getIconographyLevelTpl():getTplByLvPetId(self.tipInfo.catalogLv, self.tipInfo.petId)
      self.bind.img_taskLevel = nextLevelTpl.iconparticulars
      self.bind.txt_taskLevel = nextLevelTpl.text
      self.bind.sliderExp = 0
      target = self.tipInfo.newExp / nextLevelTpl.exp
      self.nextTween = DOTween.To(getter, setter, target, 0.5)
    end
    
    self.tween2 = DOTween.To(getter2, setter2, levelTpl.exp, 1)
    
    function self.tween2Func()
      local nextLevelTpl = L_GameTpl:getIconographyLevelTpl():getTplByLvPetId(self.tipInfo.catalogLv, self.tipInfo.petId)
      self.expNumCache = 0
      local setter2Next = function(r)
        self.expNumCache = math.round(r)
        self.bind.txt_taskExp = tostring(self.expNumCache) .. "/" .. nextLevelTpl.exp
      end
      self.nextTween2 = DOTween.To(getter2, setter2Next, self.tipInfo.newExp, 0.5)
    end
  else
    local target = 1
    if self.tipInfo.newExp then
      target = self.tipInfo.newExp / levelTpl.exp
    else
      target = self.tipInfo.oldExp
    end
    self.tween = DOTween.To(getter, setter, target, 1)
    self.tween2 = DOTween.To(getter2, setter2, self.tipInfo.newExp or self.tipInfo.oldExp, 1)
  end
end

function this:doClose()
  self.bindComponents.anim:Stop()
  self.bindComponents.anim:Play("anim_petget_tips_hide")
  Timer.once(0.25, function()
    self:close()
  end)
end

return this
