local this = class("bagManager")
local _foodTpl = L_GameTpl:getFoodTpl()
local _commonItemTpl = L_GameTpl:getCommonItemTpl()
local _commonItemUseTypeTpl = L_GameTpl:getCommonItemUseTypeTpl()
local staminaId = 100000
local bagUseFuncMap = {
  [L_BagConst.bagUseType.fixGift] = "pageBagUseGift",
  [L_BagConst.bagUseType.randomGift] = "pageBagUseGift",
  [L_BagConst.bagUseType.selectGift] = "pageBagUseGift",
  [L_BagConst.bagUseType.hp] = "pageBagUseFood",
  [L_BagConst.bagUseType.starHealingAndHp] = "pageBagUseFood",
  [L_BagConst.bagUseType.starHealing] = "pageBagUseFood",
  [L_BagConst.bagUseType.resurrection] = "pageBagUseFood",
  [L_BagConst.bagUseType.buff] = "pageBagUseFood",
  [L_BagConst.bagUseType.fish] = "pageBagUseExchange",
  [L_BagConst.bagUseType.staminaRestore] = "pageStamina"
}

function this:reqUseItem(itemId, itemNum, args, callback)
  local data = {
    itemid = itemId,
    num = itemNum or 1,
    args = args
  }
  L_BagStore:req_useItem(data, function(rspData, errCode)
    if errCode == L_Const.errorCode.ErrCodeSucc then
      local tpl = _commonItemTpl:getTplById(itemId)
      local type = _commonItemTpl:getUseType(tpl)
      if type == L_BagConst.bagUseType.foodBook then
        L_FlyMsgManager:showNormalMsgByKey("notice_bag_cookbook", {
          [0] = _commonItemTpl:getName(tpl)
        })
      end
      local itemList = rspData.rewards
      if not table.isEmpty(itemList) then
        L_RewardManager:showPage(itemList, rspData.src)
      end
      if rspData.seq ~= nil and rspData.seq ~= 0 then
        local commonItemTpl = L_GameTpl:getCommonItemTpl()
        local itemType = commonItemTpl:getType(commonItemTpl:getTplById(itemId))
        local dnaTpl = L_GameTpl:getDnaTpl()
        local skillLevelTpl = L_GameTpl:getSkillLevelTpl()
        local dnaName
        local petId = args[1]
        local targetGene = L_PetStore:getPetGene(petId, rspData.seq)
        if itemType == 406 then
          dnaName = dnaTpl:getName(dnaTpl:getTplById(rspData.seq))
          L_UI:open("pageGeneLvUp", {gene = targetGene})
        elseif itemType == 408 then
          dnaName = dnaTpl:getName(dnaTpl:getTplById(rspData.seq))
          local petSkillTpl = skillLevelTpl:getTplByIdAndLevel(rspData.seq, 1)
          if petSkillTpl ~= nil then
            L_UI:open("pageGeneReward", {gene = targetGene})
          end
        end
      end
      if callback then
        callback()
      end
    else
      local errorCodeTpl = L_GameTpl:getErrorCodeTpl()
      local tpl_errCode = errorCodeTpl:getTplById(errCode)
      L_FlyMsgManager:showNormalMsg(errorCodeTpl:getName(tpl_errCode))
    end
  end)
end

function this:reqExchangeItem(params, callback, disableRewardPage)
  local data = {
    item_id = params.itemId,
    item_type = params.itemType or L_Const.resType.commonItem,
    item_num = params.itemNum or 1,
    args = params.args
  }
  L_BagStore:req_CSProtoExchangeItem(data, function(rspData, errCode)
    if errCode == L_Const.errorCode.ErrCodeSucc then
      local itemList = rspData.rewards or {}
      if not disableRewardPage and not table.isEmpty(itemList) then
        L_RewardManager:showPage(itemList, rspData.src)
      end
      if callback then
        callback(itemList)
      end
    end
  end)
end

function this:reqSetSnackBag(data, callback)
  L_SnackBagStore:req_CSProtoOperateSnackBag(data, function(rspData, errCode)
    if errCode == L_Const.errorCode.ErrCodeSucc and callback then
      callback()
    end
  end)
end

function this:useBagItem(itemId, callback)
  local tpl = _commonItemTpl:getTplById(itemId)
  local type = _commonItemTpl:getUseType(tpl)
  if type == L_BagConst.bagUseType.capturePet then
    if L_PetManager:judgeCanCatchPet() == false then
      return
    end
    local quality = _commonItemTpl:getRarity(tpl)
    local keyString = string.format("%s_%s", L_PlayerStore:getPlayerId(), "SelectedCapturePetBall")
    C_PlayerPrefsUtility.SetInt(keyString, quality)
    L_PlayerManager:firePetCatch()
    if callback then
      callback()
    end
  else
    local pageName = bagUseFuncMap[type]
    if pageName then
      L_UI:open(pageName, {itemId = itemId})
    else
      local tpl_commonItemUseType = _commonItemUseTypeTpl:getTplById(type)
      if _commonItemUseTypeTpl:getIsMulUseType(tpl_commonItemUseType) then
        L_UI:open("pageBagUseCommon", {itemId = itemId, callback = callback})
      else
        self:reqUseItem(itemId, nil, nil, callback)
      end
    end
  end
end

function this:getMaxCanUseNum(itemId)
  if itemId == staminaId then
    local curStamina = L_PlayerStore:getCurrencyNum(L_Const.currencyType.stamina)
    local tpl_commonItem = _commonItemTpl:getTplById(staminaId)
    local staminaOne = _commonItemTpl:getUseFunction(tpl_commonItem)[1]
    local staminaLimit = tonumber(L_GameTpl:getGameConstTpl():getTplById("STAMINA_LIMIT"))
    local maxAddNum = math.ceil((staminaLimit - curStamina) / staminaOne)
    maxAddNum = math.min(maxAddNum, L_BagStore:getItemNum(itemId))
    return maxAddNum < 1 and 1 or maxAddNum
  else
    return L_BagStore:getItemNum(itemId)
  end
end

function this:getMaxCanUseNum_food(itemId, heroGuid)
  local tpl_commonItem = _commonItemTpl:getTplById(itemId)
  local tpl_food = _foodTpl:getTplById(itemId)
  local foodType = _foodTpl:getFoodType(tpl_food)
  if foodType ~= L_Const.foodType.heal and foodType ~= L_Const.foodType.attack and foodType ~= L_Const.foodType.defence then
    return 1
  end
  local foodCharge = _foodTpl:getFoodCharge(tpl_food)
  local charge = _foodTpl:getCharge(tpl_food)
  local oneItemFunc = 0
  local canAddItemNum = 0
  if heroGuid == 0 then
    if charge == 0 then
      return 1
    end
    local chargeData = L_StarHealingStore:getCharge()
    local limit = L_StarHealingStore:getMaxCharge()
    oneItemFunc = charge
    canAddItemNum = math.ceil((limit - chargeData.cur_value) / oneItemFunc)
  else
    local hp_max = L_AttributeManager:getAttValueByHeroGuid(heroGuid, L_Const.battleAtt.MAXHP)
    local hp = L_FormationStore:getFormationHeroHp(heroGuid)
    for i, v in ipairs(foodCharge) do
      if v[1] == L_Const.HPRechargeType.HPRT_VALUE then
        oneItemFunc = oneItemFunc + v[2]
      else
        oneItemFunc = v[2] / 10000 * hp_max + oneItemFunc
      end
    end
    canAddItemNum = math.ceil((hp_max - hp) / oneItemFunc)
  end
  return math.clamp(canAddItemNum, 1, L_BagStore:getItemNum(itemId))
end

function this:getStackCommonItemData(itemId)
  local tpl = _commonItemTpl:getTplById(itemId)
  local stackNum = _commonItemTpl:getStackNum(tpl)
  local bagNum = L_BagStore:getItemNum(itemId)
  return L_DataUtil.getItemStacks(L_Const.resType.commonItem, itemId, bagNum)
end

function this:getItemNumByStackIndex(itemId, stackIndex)
  if math.isEmpty(stackIndex) then
    return L_BagStore:getItemNum(itemId)
  else
    local stackData = self:getStackCommonItemData(itemId)
    return stackData[stackIndex]
  end
end

function this:getAllCapturePetBall()
  local commonItemTpl = L_GameTpl:getCommonItemTpl()
  local group = commonItemTpl:getTypeGroup(L_BagConst.bagItemType.capturePetBall)
  local list = {}
  for i, v in pairs(group) do
    local id = commonItemTpl:getId(v)
    local item = L_ItemTplManager:getCommonItem(id)
    local num = L_BagStore:getItemNum(id)
    table.insert(list, {
      name = item.name,
      icon = item.icon,
      quality = item.quality,
      desc = item.desc,
      id = id,
      num = num
    })
  end
  return list
end

function this:getCapturePetBallNum(id)
  if not table.isEmpty(L_BagStore:getItem(id)) then
    local num = L_BagStore:getItemNum(id)
    return {id = id, num = num}
  else
    return {id = id, num = 0}
  end
end

return this
