local this = class("moduleSpiritMaterialBag", G_UIModuleBase)

function this.bind()
  return {
    materialList = {
      moduleName = "pages/heroPanel/spirit/cellReplaceSpirit"
    },
    selectedTip = {
      moduleName = "pages/bag/moduleBagTip"
    },
    materialListActive = true,
    emptyActive = false,
    selectedTipActive = false,
    module_sortFilter = L_Const.ModuleInfo.SortFilterModule
  }
end

function this.methods()
  return {
    onClick_mask = function(self, bind)
      if self.bind.selectedTipActive then
        self.bind.selectedTipActive = false
        return
      end
      L_UI:close(self.pageName)
    end,
    materialList = {
      onClick_reduce = function(self, bind)
        self:changeSelectNum(bind, true)
      end,
      onClick_item = function(self, bind)
        if self.bagType == L_Const.spiritMaterialBagType.level then
          self:onClickLevelItem(bind)
        end
        if self.bagType == L_Const.spiritMaterialBagType.star then
          self:onClickStarItem(bind)
        end
        if not L_DeviceTpl:getIsPc() then
          return
        end
        self:setBagTip(bind)
      end,
      onPointEnter_item = function(self, bind)
      end,
      onPointExit_item = function(self, bind)
      end,
      onLongClick = function(self, bind)
        if L_DeviceTpl:getIsPc() then
          return
        end
        self:setBagTip(bind)
      end
    }
  }
end

function this:validateSelectFunc()
  if self.bagType == L_Const.spiritMaterialBagType.level then
    local _, _, overflow = L_SpiritronManager:getLevelUpSelectItemExp(self.selectItems, self.spiritGuid)
    return overflow
  end
  if self.bagType == L_Const.spiritMaterialBagType.star then
    local _, _, overflow = L_SpiritronManager:getStarUpSelectItem(self.selectItems, self.spiritGuid)
    return overflow
  end
  return false
end

function this:changeSelectNum(bindItem, isReduce)
  if self.bagType == L_Const.spiritMaterialBagType.level then
    self:changeLevelSelectNum(bindItem, isReduce)
  end
  if self.bagType == L_Const.spiritMaterialBagType.star then
    self:changeStarSelectNum(bindItem, isReduce)
  end
end

function this:getCheckId(item)
  if item.itemType == L_Const.resType.commonItem then
    return item.itemId
  end
  if item.itemType == L_Const.resType.spiritron then
    return item.guid
  end
end

function this:getSelectedItem(itemType, id)
  for k, v in ipairs(self.selectItems) do
    local itemId = v.itemId or v.guid
    if v.itemType == L_Const.resType.spiritron then
      itemId = v.guid
    end
    if v.itemType == itemType and itemId == id then
      return v, k
    end
  end
end

function this:setBagTip(bind)
  self.modules.selectedTip:reset()
  self:resetChooseStates()
  self.bind.selectedTipActive = true
  if bind.itemType == L_Const.resType.commonItem then
    self.modules.selectedTip:setData(L_BagConst.bagTag.develop, bind.itemId, {hideFuncBtn = true})
  end
  if bind.itemType == L_Const.resType.spiritron then
    self.modules.selectedTip:setData(L_BagConst.bagTag.spiritron, bind.guid, {hideFuncBtn = true})
  end
  self.bind.materialList:getItemCls(bind.index):setActveState(true)
  self.showTips = true
end

function this:initModule(options)
  self.bagType = L_Const.spiritMaterialBagType.level
  if options then
    self.selectItems = options.selectItems
    self.pageCloseCallback = options.pageCloseCallback
    self.onSelectItem = options.onSelectItem
    self.spiritGuid = options.spiritGuid
    self.bagType = options.bagType
  end
  if not self.selectItems then
    self.selectItems = {}
  end
  self:updateFilter()
  self:initMaterialList()
end

function this:open(options)
  L_SpiritronStore:listenCallFunc(L_SpiritronStore.event.spiritLockStatusChange, self.refreshOneSpirit, self)
end

function this:close(options)
  L_SpiritronStore:unListenCallFunc(L_SpiritronStore.event.spiritLockStatusChange, self.refreshOneSpirit)
end

function this:refreshOneSpirit(data)
  if not data or math.isEmpty(data.spiritGuid) then
    return
  end
  for i = 1, #self.bind.materialList do
    if self.bind.materialList:getValue(i, "guid") == data.spiritGuid then
      local item = self.bind.materialList:getItemCls(i)
      item:initCell()
    end
  end
  for k, item in ipairs(self.selectItems) do
    if item.guid == data.spiritGuid then
      table.remove(self.selectItems, k)
      if self.onSelectItem then
        self.onSelectItem(self.selectItems)
        self:setSelectStates()
      end
    end
  end
end

function this:close()
  if self.pageCloseCallback then
    self.pageCloseCallback()
  end
end

function this:checkItemIsSelected(itemType, id)
  for k, v in ipairs(self.selectItems) do
    local itemId = v.itemId or v.guid
    if v.itemType == L_Const.resType.spiritron then
      itemId = v.guid
    end
    if v.itemType == itemType and itemId == id then
      return true, k
    end
  end
  return false
end

function this:initMaterialList()
  if self.bagType == L_Const.spiritMaterialBagType.level then
    self:setLevelMaterials()
  end
  if self.bagType == L_Const.spiritMaterialBagType.star then
    self:setStarMaterialList()
  end
end

function this:updateFilter()
  self:initSortFilterModule()
end

function this:initSortFilterModule()
  local callback = function()
    self:initMaterialList()
  end
  self._sortFilter = L_SortFilterManager:createSortFilter(L_SystemConst.enum.spiritUpgradeBag, callback, callback)
  self._sortFilter:bindModule(self.modules.module_sortFilter)
end

function this:setStarMaterialList()
  local spData = L_SpiritronStore:getSpiritronItem(self.spiritGuid)
  local materialListData = {}
  local index = 1
  local spiritList = L_SpiritronStore:getSpiritronList()
  for k, v in pairs(spiritList) do
    local item = L_ItemTplManager:getSpiritronItem(v.spiritronId)
    local active, selectedIndex = self:checkItemIsSelected(L_Const.resType.spiritron, v.guid)
    local selectedData = self.selectItems[selectedIndex]
    local selectNum = 1
    if selectedData then
      selectNum = selectedData.itemSelectNum
    end
    if math.isEmpty(v.spiritronHero) and v.spiritronId == spData.spiritronId and self.spiritGuid ~= v.guid then
      local data = {
        itemType = L_Const.resType.spiritron,
        guid = v.guid,
        active = v.guid == self.selectedSpiritGuid,
        star = v.star,
        quality = item.quality,
        spiritronId = v.spiritronId,
        index = index,
        selectActive = active,
        itemSelectNum = selectNum,
        id = v.spiritronId,
        itemId = v.spiritronId,
        level = v.spiritronLv
      }
      table.insert(materialListData, data)
      index = index + 1
    end
  end
  self._sortFilter:sortFilterList(materialListData)
  local spiritronTpl = L_GameTpl:getSpiritronTpl()
  local tpl = spiritronTpl:getTplById(spData.spiritronId)
  local starItems = L_Config:getConfig("game", "SPIRITRON_STAR_ITEM")
  local rarity = spiritronTpl:getRarity(tpl)
  local itemId = starItems[rarity]
  local item = L_BagStore:getItem(itemId)
  if item and item.itemNum > 0 then
    local active, selectedIndex = self:checkItemIsSelected(L_Const.resType.commonItem, itemId)
    local selectedData = self.selectItems[selectedIndex]
    local selectNum = 1
    if selectedData then
      selectNum = selectedData.itemSelectNum
    end
    table.insert(materialListData, {
      itemId = itemId,
      itemNum = item.itemNum,
      itemType = L_Const.resType.commonItem,
      index = index,
      selectActive = active,
      itemSelectNum = selectNum,
      order = 999999999999
    })
    index = index + 1
  end
  for k, v in ipairs(materialListData) do
    v.index = k
  end
  self.bind.materialList:clear()
  self.bind.materialList:insert_array(materialListData)
  self.bind.materialListActive = 0 < #materialListData
  self.bind.emptyActive = #materialListData == 0
end

function this:onClickStarItem(bind)
  if not L_DeviceTpl:getIsPc() then
    if not self.showTips then
      self.bind.selectedTipActive = false
      self:resetChooseStates()
    end
    self.showTips = false
  end
  if bind.selectActive then
    self:changeSelectNum(bind)
    return
  end
  if #self.selectItems >= 4 then
    L_FlyMsgManager:showNormalMsg(L_WordsTpl:getValue("ui_spirit_material_num_limit"))
    return
  end
  local _, afterStar, _ = L_SpiritronManager:getStarUpSelectItem(self.selectItems, self.spiritGuid)
  if afterStar >= L_Const.SpiritronFullStar then
    L_FlyMsgManager:showNormalMsg(L_WordsTpl:getValue("ui_spirit_star_limit"))
    return
  end
  if bind.itemType == L_Const.resType.spiritron then
    local serverData = L_SpiritronStore:getSpiritronItem(bind.guid)
    if serverData.lock then
      L_FlyMsgManager:showNormalMsg(L_WordsTpl:getValue("ui_spirit_lock_tip"))
      return
    end
  end
  if self.onSelectItem then
    table.insert(self.selectItems, {
      itemType = bind.itemType,
      guid = bind.guid,
      itemId = bind.itemId,
      itemSelectNum = bind.itemSelectNum or 0
    })
    self.onSelectItem(self.selectItems)
    self:setSelectStates()
  end
end

function this:changeStarSelectNum(bindItem, isReduce)
  local _, afterStar, _ = L_SpiritronManager:getStarUpSelectItem(self.selectItems, self.spiritGuid)
  if not isReduce and (self.overflow or afterStar >= L_Const.SpiritronFullStar) and bindItem.itemType ~= L_Const.resType.spiritron then
    L_FlyMsgManager:showNormalMsg(L_WordsTpl:getValue("ui_spirit_star_limit"))
    return
  end
  local checkId = self:getCheckId(bindItem)
  local item, index = self:getSelectedItem(bindItem.itemType, checkId)
  if bindItem.itemType == L_Const.resType.spiritron then
    table.remove(self.selectItems, index)
  end
  if bindItem.itemType == L_Const.resType.commonItem then
    if isReduce then
      if item.itemSelectNum <= 1 then
        table.remove(self.selectItems, index)
      else
        item.itemSelectNum = item.itemSelectNum - 1
      end
    elseif item.itemSelectNum < L_BagStore:getItemNum(item.itemId) then
      item.itemSelectNum = item.itemSelectNum + 1
    end
  end
  self.onSelectItem(self.selectItems)
  self:setSelectStates()
  self.overflow = self:validateSelectFunc()
end

function this:setLevelMaterials()
  local materialListData = {}
  local index = 1
  local expItems = L_Config:getConfig("game", "SPIRITRON_EXP_ITEM")
  for _, itemId in ipairs(expItems) do
    local item = L_BagStore:getItem(itemId)
    if item and item.itemNum ~= 0 then
      local active, selectedIndex = self:checkItemIsSelected(L_Const.resType.commonItem, itemId)
      local selectedData = self.selectItems[selectedIndex]
      local selectNum = 1
      if selectedData then
        selectNum = selectedData.itemSelectNum
      end
      table.insert(materialListData, {
        itemId = itemId,
        itemNum = item.itemNum,
        itemType = L_Const.resType.commonItem,
        index = index,
        selectActive = active,
        itemSelectNum = selectNum,
        order = index
      })
      index = index + 1
    end
  end
  local spiritList = L_SpiritronStore:getSpiritronList()
  local spiritronListData = {}
  for k, v in pairs(spiritList) do
    local item = L_ItemTplManager:getSpiritronItem(v.spiritronId)
    local active, selectedIndex = self:checkItemIsSelected(L_Const.resType.spiritron, v.guid)
    local selectedData = self.selectItems[selectedIndex]
    local selectNum = 1
    if selectedData then
      selectNum = selectedData.itemSelectNum
    end
    if math.isEmpty(v.spiritronHero) and self.spiritGuid ~= v.guid then
      local data = {
        itemType = L_Const.resType.spiritron,
        guid = v.guid,
        id = v.spiritronId,
        active = v.guid == self.selectedSpiritGuid,
        star = v.star,
        quality = item.quality,
        spiritronId = v.spiritronId,
        index = index,
        selectActive = active,
        itemSelectNum = selectNum,
        itemId = v.spiritronId,
        level = v.spiritronLv
      }
      table.insert(spiritronListData, data)
      index = index + 1
    end
  end
  self._sortFilter:sortFilterList(spiritronListData)
  table.fill(materialListData, spiritronListData)
  for k, v in ipairs(materialListData) do
    v.index = k
  end
  self.bind.materialList:clear()
  self.bind.materialList:insert_array(materialListData)
  self.bind.materialListActive = 0 < #materialListData
  self.bind.emptyActive = #materialListData == 0
end

function this:onClickLevelItem(bind)
  if not L_DeviceTpl:getIsPc() then
    if not self.showTips then
      self.bind.selectedTipActive = false
      self:resetChooseStates()
    end
    self.showTips = false
  end
  if bind.selectActive then
    self:changeSelectNum(bind)
    return
  end
  if #self.selectItems >= 4 then
    L_FlyMsgManager:showNormalMsg(L_WordsTpl:getValue("ui_spirit_material_num_limit"))
    return
  end
  if bind.itemType == L_Const.resType.spiritron then
    local serverData = L_SpiritronStore:getSpiritronItem(bind.guid)
    if serverData.lock then
      L_FlyMsgManager:showNormalMsg(L_WordsTpl:getValue("ui_spirit_lock_tip"))
      return
    end
  end
  local _, _, overflow = L_SpiritronManager:getLevelUpSelectItemExp(self.selectItems, self.spiritGuid)
  if overflow then
    L_FlyMsgManager:showNormalMsg(L_WordsTpl:getValue("ui_spirit_exp_limit"))
    return
  end
  if self.onSelectItem then
    table.insert(self.selectItems, {
      itemType = bind.itemType,
      guid = bind.guid,
      itemId = bind.itemId,
      itemSelectNum = bind.itemSelectNum or 0
    })
    self.onSelectItem(self.selectItems)
    self:setSelectStates()
  end
end

function this:changeLevelSelectNum(bindItem, isReduce)
  if not isReduce and self.overflow then
    L_FlyMsgManager:showNormalMsg(L_WordsTpl:getValue("ui_spirit_exp_limit"))
    return
  end
  local checkId = self:getCheckId(bindItem)
  local item, index = self:getSelectedItem(bindItem.itemType, checkId)
  if bindItem.itemType == L_Const.resType.spiritron then
    table.remove(self.selectItems, index)
  end
  if bindItem.itemType == L_Const.resType.commonItem then
    if isReduce then
      if item.itemSelectNum <= 1 then
        table.remove(self.selectItems, index)
      else
        item.itemSelectNum = item.itemSelectNum - 1
      end
    elseif item.itemSelectNum < L_BagStore:getItemNum(item.itemId) then
      item.itemSelectNum = item.itemSelectNum + 1
    end
  end
  self.onSelectItem(self.selectItems)
  self:setSelectStates()
  self.overflow = self:validateSelectFunc()
end

function this:setSelectStates()
  for i = 1, #self.bind.materialList do
    local itemType = self.bind.materialList:getValue(i, "itemType")
    local selected = false
    local index
    if itemType == L_Const.resType.commonItem then
      selected, index = self:checkItemIsSelected(itemType, self.bind.materialList:getValue(i, "itemId"))
    end
    if itemType == L_Const.resType.spiritron then
      selected, index = self:checkItemIsSelected(itemType, self.bind.materialList:getValue(i, "guid"))
    end
    if self.selectItems[index] then
      self.bind.materialList:change(i, {
        itemSelectNum = self.selectItems[index].itemSelectNum
      })
    end
    self.bind.materialList:getItemCls(i):setSelected(selected)
  end
end

function this:resetChooseStates()
  for _, module in ipairs(self.modules.materialList) do
    module:setActveState(false)
  end
end

return this
