local this = class("moduleSpiritLevelUp", G_UIModuleBase)
local spiritronLevelTpl = L_GameTpl:getSpiritronLevelTpl()
local commonItemTpl = L_GameTpl:getCommonItemTpl()
local qualities = L_GameClientTpl:getValue("FILTER_QUALITY")

function this.bind()
  return {
    moduleSpiritProperty = {
      moduleName = "pages/heroPanel/spirit/moduleSpiritProperty"
    },
    upgradePartActive = true,
    maxPartActive = false,
    levelText = "1",
    levelLimitText = "/1",
    currentExpBar = 0,
    addExpBar = 0,
    costList = {
      moduleName = "pages/heroPanel/spirit/cellCostItemSquare"
    },
    levelUpBtn = L_Const.ModuleInfo.ModuleBtn,
    currentExpBarActive = true,
    addExpBarActive = false,
    expText = "",
    filterTypeText = "",
    optionList = {
      moduleName = "modulePages/sortFilter/cellSortFilterDropdown"
    },
    currentFilterText = "",
    filterContentActive = false
  }
end

function this.methods()
  return {
    optionList = {
      onClick_select = function(self, itemBind)
        self.filterQuality = itemBind.quality
        self.bind.filterContentActive = false
        self:refreshOptionList()
      end
    },
    onClick_autoBtn = function(self)
      self.bind.filterContentActive = false
      self:autoSelect()
    end,
    onClick_filterBtn = function(self)
      self.bind.filterContentActive = not self.bind.filterContentActive
    end
  }
end

function this:autoSelect()
  if self.onAuto then
    self.selectItems = {}
    self.onAuto = false
    self:refreshCost()
    return
  end
  if self.showLv >= self:getMaxLv() then
    return
  end
  self.onAuto = true
  self.selectItems = {}
  local spData = L_SpiritronStore:getSpiritronItem(self.spiritGuid)
  local item = L_ItemTplManager:getSpiritronItem(spData.spiritronId)
  local selfLvExp = spiritronLevelTpl:getExpAll(spiritronLevelTpl:getTplById(spData.spiritronLv, item.quality))
  local tempExp = spiritronLevelTpl:getExpAll(spiritronLevelTpl:getTplById(self:getMaxLv(), item.quality)) - spData.exp - selfLvExp
  local exp2NumMap = {}
  local tempItems = L_Config:getConfig("game", "SPIRITRON_EXP_ITEM")
  local expItems = {}
  for _, itemId in ipairs(tempItems) do
    local tempItem = L_ItemManager:parseItem(L_Const.resType.commonItem, itemId)
    if tempItem.quality <= self.filterQuality then
      table.insert(expItems, itemId)
    end
  end
  for _, itemId in ipairs(expItems) do
    local unitExp = self:getItemUnitExp(itemId)
    exp2NumMap[unitExp] = L_BagStore:getItemNum(itemId)
  end
  local autoItems = L_HeroManager:autoLvUp(exp2NumMap, tempExp)
  for exp, num in pairs(autoItems) do
    for _, itemId in ipairs(expItems) do
      if 0 < num then
        local unitExp = self:getItemUnitExp(itemId)
        if unitExp == exp then
          table.insert(self.selectItems, {
            itemType = L_Const.resType.commonItem,
            itemId = itemId,
            itemSelectNum = num
          })
        end
      end
    end
  end
  table.sort(self.selectItems, function(a, b)
    return a.itemId < b.itemId
  end)
  self:calculateExp()
  local index = 1
  local spiritList = L_SpiritronManager:getSpiritsForAutoLevelSelect(self.filterQuality, self.spiritGuid)
  while not self.expOverFlow and #self.selectItems < 4 and spiritList[index] do
    local spirit = spiritList[index]
    if spirit.guid ~= self.spiritGuid then
      table.insert(self.selectItems, {
        itemType = spirit.itemType,
        guid = spirit.guid,
        itemSelectNum = 1
      })
    end
    index = index + 1
    self:calculateExp()
  end
  if #self.selectItems == 0 then
    L_FlyMsgManager:showNormalMsg(L_WordsTpl:getValue("ui_spirit_auto_empty"))
  end
  self:refreshCost()
end

function this:getAllSelects()
  return L_SpiritronManager:getAdvancedSelectItem(self.selectItems)
end

function this:onClickLevelUp()
  local items, spiritronData = self:getAllSelects()
  if #spiritronData == 0 and #items == 0 then
    return L_HeroManager:heroHintInfo(6)
  end
  if not self.currencyEnough then
    return L_HeroManager:heroHintInfo(1)
  end
  local data = {
    guid = self.spiritGuid,
    costs = spiritronData,
    cost_items = items
  }
  local showSpiritTip = false
  local spiritronId
  for i = 1, #spiritronData do
    local spirit = L_SpiritronStore:getSpiritronItem(spiritronData[i])
    showSpiritTip = showSpiritTip or 1 < spirit.star
    showSpiritTip = showSpiritTip or 1 < spirit.spiritronLv
    showSpiritTip = showSpiritTip or 0 < spirit.exp
    if showSpiritTip then
      spiritronId = spirit.spiritronId
      break
    end
  end
  if not showSpiritTip then
    self:spiritronStrength(data)
  else
    local item = L_ItemTplManager:getSpiritronItem(spiritronId)
    L_GameUtil.showCommonTip({
      txtContent = L_WordsTpl:getValue("ui_level_up_spirit_tip", {
        [0] = item.name
      }),
      txtTitle = L_WordsTpl:getTplById("notice_title_hint"),
      confirmCallback = function()
        self:spiritronStrength(data)
      end
    })
  end
end

function this:spiritronStrength(data)
  local curData = L_SpiritronStore:getSpiritronItem(self.spiritGuid)
  local curPropertyList = L_SpiritronManager:getConfigAttList(curData.spiritronId, curData.spiritronLv, curData.curRank)
  local preLv = curData.spiritronLv
  L_SpiritronStore:req_composeSpiritron(data, function()
    local afterData = L_SpiritronStore:getSpiritronItem(self.spiritGuid)
    if afterData.spiritronLv > preLv then
      L_UI:open("pageSpiritronStrengthSuccess", {
        guid = data.guid,
        curPropertyList = curPropertyList
      })
    end
    self.selectItems = {}
    self:refreshCost()
  end)
end

function this:intensifySuccess(preLv, preStar)
  local spData = L_SpiritronStore:getSpiritronItem(self.spiritGuid)
  local item = L_ItemTplManager:getSpiritronItem(spData.spiritronId)
  local spiritronRankTpl = L_GameTpl:getSpiritronRankTpl()
  local wordsTpl = L_GameTpl:getWordsTpl()
  if preStar < spData.star then
    local data = {
      guid = self.spiritGuid,
      describe = self:getSkillContent(spData.star, true),
      callback = function()
        local rankData = spiritronRankTpl:getChildren(spData.spiritronId)
        if spData.spiritronLv >= rankData[spData.rank].rankLevelLimit and #rankData > spData.rank then
          local rankTpl = rankData[spData.rank]
          local condition = spiritronRankTpl:getCondition(rankTpl)
          local bComplete = true
          if not table.isEmpty(condition) then
            bComplete = L_ConditionManager:singleIsComplete(condition)
          end
          if bComplete then
            L_GameUtil.showCommonTip({
              txtContent = wordsTpl:getTplById("notice_spiritron_levelmax"),
              txtTitle = wordsTpl:getTplById("notice_spiritron_breakhint"),
              confirmCallback = function()
                L_UI:open("pageSpiritronAdvance", {
                  weaponGuid = self.spiritGuid
                })
              end
            })
          end
        end
      end
    }
    L_UI:open("pageSpiritronStrengthSuccess", data)
  end
end

function this:open(options)
end

function this:close(options)
end

function this:initModule(data)
  self.spiritGuid = data.spiritGuid
  self.heroGuid = data.heroGuid
  self.isPreview = data.isPreview
  self.selectItems = {}
  if not self.filterQuality then
    self.filterQuality = L_Const.quality.sr
  end
  self:refreshCost()
end

function this:updateCostList()
  local data = {}
  for i = 1, 4 do
    if self.selectItems[i] then
      local selectItem = self.selectItems[i]
      local itemNum = 1
      if selectItem.itemType == L_Const.resType.commonItem then
        itemNum = L_BagStore:getItemNum(selectItem.itemId)
      end
      table.insert(data, {
        itemType = selectItem.itemType,
        itemId = selectItem.itemId,
        guid = selectItem.guid,
        selectNum = selectItem.itemSelectNum,
        bgActive = true,
        addBtnActive = false,
        cellIconActive = true,
        params = {
          selectNum = selectItem.itemSelectNum,
          selectMode = true,
          mutiSelect = true,
          validateSelectFunc = function(beforeNum, afterNum)
            if afterNum <= 0 then
              table.remove(self.selectItems, i)
              self:refreshCost()
              return false
            end
            if afterNum > itemNum then
              return false
            end
            local isReduce = afterNum < selectItem.itemSelectNum
            selectItem.itemSelectNum = afterNum
            if self.expOverFlow and not isReduce then
              L_FlyMsgManager:showNormalMsg(L_WordsTpl:getValue("ui_spirit_exp_limit"))
              selectItem.itemSelectNum = afterNum - 1
              return false
            end
            if isReduce then
              self:refreshCost()
            end
            return true
          end,
          itemNum = itemNum,
          callback = function()
            self:refreshCost()
          end
        }
      })
    else
      table.insert(data, {
        addBtnActive = true,
        cellIconActive = false,
        bgActive = false,
        onAddClick = function()
          L_UI:open("pageSpiritMaterialBag", {
            bagType = L_Const.spiritMaterialBagType.level,
            pageCloseCallback = function()
              self:onBagClose()
            end,
            onSelectItem = function(passData)
              self:onSelectItem(passData)
            end,
            selectItems = self.selectItems,
            spiritGuid = self.spiritGuid
          })
          self.parent:setLeftAreaActive(false)
        end
      })
    end
  end
  self.bind.costList:clear()
  self.bind.costList:insert_array(data)
end

function this:onBagClose()
  self.parent:setLeftAreaActive(true)
end

function this:onSelectItem(data)
  self.selectItems = data
  self:refreshCost()
end

function this:refreshCost()
  self:updateCostList()
  self:refreshExp()
  if #self.selectItems == 0 then
    self.onAuto = false
  elseif #self.selectItems == 4 then
    self.onAuto = true
  end
  if self.onAuto then
    self.bind.filterTypeText = L_WordsTpl:getValue("ui_spirit_auto_clear")
  else
    self.bind.filterTypeText = L_WordsTpl:getValue("ui_spirit_auto_put")
  end
  self:refreshOptionList()
end

function this:refreshOptionList()
  local optionData = {}
  for k, quality in ipairs(qualities) do
    local showText = L_WordsTpl:getValue("ui_filter_quality", {
      [0] = L_RarityTpl:getName(L_RarityTpl:getTplById(quality))
    })
    local isCurrent = self.filterQuality == quality
    table.insert(optionData, {
      quality = quality,
      txt_name = showText,
      go_icon = false,
      img_icon = nil,
      go_active = isCurrent
    })
    if isCurrent then
      self.bind.currentFilterText = showText
    end
  end
  self.bind.optionList:clear()
  self.bind.optionList:insert_array(optionData)
end

function this:refreshExp()
  local currSpData = L_SpiritronStore:getSpiritronItem(self.spiritGuid)
  local item = L_ItemTplManager:getSpiritronItem(currSpData.spiritronId)
  local cExp, needCost = self:calculateExp()
  local afterExp = spiritronLevelTpl:getExpAll(spiritronLevelTpl:getTplById(currSpData.spiritronLv, item.quality)) + currSpData.exp + cExp
  local afterTpl = spiritronLevelTpl:getTplByExp(afterExp, item.quality)
  local afterLevel = spiritronLevelTpl:getLv(afterTpl)
  local afterNeedExp = spiritronLevelTpl:getExp(afterTpl)
  local exp = afterExp - spiritronLevelTpl:getExpAll(spiritronLevelTpl:getTplById(afterLevel, item.quality))
  self.showLv = afterLevel
  self.bind.upgradePartActive = currSpData.spiritronLv < self:getMaxLv()
  self.bind.maxPartActive = currSpData.spiritronLv == self:getMaxLv()
  self.bind.currentExpBarActive = afterLevel == currSpData.spiritronLv
  self.bind.addExpBarActive = 0 < cExp
  if afterLevel > currSpData.spiritronLv then
    self.bind.levelText = L_GameUtil.fillColor(afterLevel, L_Const.colorHtml.blue005)
    self.bind.levelLimitText = "/" .. tostring(self:getMaxLv())
    self.bind.currentExpBar = 0
    if self.expOverFlow then
      afterNeedExp = spiritronLevelTpl:getExp(spiritronLevelTpl:getTplById(afterLevel - 1, item.quality))
      self.bind.expText = string.format("%s/%s", math.floor(afterNeedExp), afterNeedExp)
      self.bind.addExpBar = 1
    else
      self.bind.expText = string.format("%s/%s", math.floor(exp), afterNeedExp)
      self.bind.addExpBar = exp / afterNeedExp
    end
    self.modules.moduleSpiritProperty:setCampareLevel(self.spiritGuid, self.heroGuid, self.isPreview, afterLevel)
  else
    self.bind.levelText = tostring(currSpData.spiritronLv)
    self.bind.levelLimitText = "/" .. tostring(L_SpiritronManager:getMaxLevel(self.spiritGuid))
    local curExp, curNeedExp = self:getCurrentLevelExp()
    self.bind.currentExpBar = curExp / curNeedExp
    self.bind.addExpBar = exp / afterNeedExp
    self.bind.expText = string.format("%s/%s", math.floor(exp), afterNeedExp)
    self.modules.moduleSpiritProperty:initModule(self.spiritGuid, self.heroGuid, self.isPreview)
  end
  if self.bind.maxPartActive then
    self.bind.addExpBarActive = true
    self.bind.addExpBar = 1
    self.bind.expText = "MAX"
  end
  local moduleBtn = self.modules.levelUpBtn
  moduleBtn:setData({
    txtName = L_WordsTpl:getValue("ui_spirit_level_up"),
    callback = function()
      self:onClickLevelUp()
    end,
    itemType = L_Const.resType.currency,
    itemId = L_Const.currencyType.gold,
    itemNum = needCost
  })
end

function this:calculateExp()
  local addExp, needCost, expOverFlow, overExp = L_SpiritronManager:getLevelUpSelectItemExp(self.selectItems, self.spiritGuid)
  self.expOverFlow = expOverFlow
  self.overExp = overExp
  self.currencyEnough = needCost <= L_PlayerStore:getCurrencyNum(L_Const.currencyType.gold)
  return addExp, needCost
end

function this:getItemUnitExp(itemId)
  return commonItemTpl:getUseFunction(commonItemTpl:getTplById(itemId))[1]
end

function this:getCurrentLevelExp()
  local currSpData = L_SpiritronStore:getSpiritronItem(self.spiritGuid)
  local currSpItemConf = L_ItemTplManager:getSpiritronItem(currSpData.spiritronId)
  local levelTpl = spiritronLevelTpl:getTplById(currSpData.spiritronLv, currSpItemConf.quality)
  local currentNeedExp = spiritronLevelTpl:getExp(levelTpl)
  return currSpData.exp, currentNeedExp
end

function this:getLevelExp(level)
  local currSpData = L_SpiritronStore:getSpiritronItem(self.spiritGuid)
  local currSpItemConf = L_ItemTplManager:getSpiritronItem(currSpData.spiritronId)
  local levelTpl = spiritronLevelTpl:getTplById(level, currSpItemConf.quality)
  local currentNeedExp = spiritronLevelTpl:getExp(levelTpl)
  return currSpData.exp, currentNeedExp
end

function this:getMaxLv()
  return L_SpiritronManager:getMaxLevel(self.spiritGuid)
end

return this
