local this = class("accessoryManager")
local _accessoryTpl = L_GameTpl:getAccessoryTpl()
local _accessorySetTpl = L_GameTpl:getAccessorySetTpl()
local _battleInfoTpl = L_GameTpl:getBattleInfoTpl()
local _skillLevelTpl = L_GameTpl:getSkillLevelTpl()
local _skillsubAttrupTpl = L_GameTpl:getSkillsubAttrupTpl()
local _skillTpl = L_GameTpl:getSkillTpl()
local _accessoryMainTpl = L_GameTpl:getAccessoryMainTpl()
local _accessorySubTpl = L_GameTpl:getAccessorySubTpl()
local _accessoryLevelTpl = L_GameTpl:getAccessoryLevelTpl()
local _accessoryInterimTpl = L_GameTpl:getAccessoryInterimTpl()

function this:removeAccessory(guid, callback)
  if math.isEmpty(guid) then
    return
  end
  local serverData = L_AccessoryStore:getAccessory(guid)
  local item = L_ItemManager:parseAccessoryItem(serverData.accessoryId)
  if not math.isEmpty(serverData.wearHero) then
    local data = {
      guid = guid,
      hero_id = serverData.wearHero,
      type = item.type
    }
    L_AccessoryStore:req_removeAccessory(data, function()
      if callback then
        callback()
      end
    end)
  end
end

function this:equipAccessory(heroGuid, guid, callback)
  if L_BattleDataManager:checkPlayerBattle() then
    L_FlyMsgManager:showNormalMsg(L_BattleDataManager:getBattleBlockTips(L_Const.BattleBlockType.EquipmentSwitchEntrance))
    return
  end
  local item = L_ItemManager:parseAccessoryItem(L_AccessoryStore:getAccessory(guid).accessoryId)
  local heroAccessory = L_HeroStore:getHeroAccessoryGuidList(L_HeroStore:getHero(heroGuid))
  local data = {
    hero_id = heroGuid,
    ornament_guid = guid,
    oldGuid = heroAccessory[item.type]
  }
  local func = function()
    L_AccessoryStore:req_equipAccessory(data, function()
      if callback then
        callback()
      end
    end)
  end
  local serverData = L_AccessoryStore:getAccessory(guid)
  if not math.isEmpty(serverData.wearHero) then
    local data_tip = {
      txtContent = string.format(L_WordsTpl:getValue("notice_accessory_equipped")),
      confirmCallback = func
    }
    L_GameUtil.showCommonTip(data_tip)
    return
  end
  func()
end

function this:setAccessoryLock(guid, callback)
  local serverData = L_AccessoryStore:getAccessory(guid)
  local data = {
    guid = guid,
    lock = not serverData.lock
  }
  L_AccessoryStore:req_setLockAccessory(data, function()
    if callback then
      callback()
    end
  end)
end

function this:req_StrengthAccessory(data, callback)
  L_AccessoryStore:req_upgradeAccessory(data, function()
    L_AudioUtil.playSESound("level_up")
    if callback then
      callback()
    end
  end)
end

function this:req_BreakAccessory(data, callback)
  local uid = data.u32
  local accessoryItem = L_AccessoryStore:getAccessory(uid)
  if accessoryItem.lock then
    L_FlyMsgManager:showNormalMsg(L_WordsTpl:getValue("locked_not_allow_resolve"))
    return
  end
  L_AccessoryStore:req_breakAccessory(data, function()
    if callback then
      callback()
    end
  end)
end

function this:getAccessoryListAttDic(accessoryList)
  local serverDataList = {}
  for _, v in pairs(accessoryList) do
    if not math.isEmpty(v) then
      local serverData = L_AccessoryStore:getAccessory(v)
      table.insert(serverDataList, serverData)
    end
  end
  return self:_getAccessoryListAttDic(serverDataList)
end

function this:getAccessoryListAttDic_trial(accessoryList)
  local serverDataList = {}
  for _, v in pairs(accessoryList) do
    if not math.isEmpty(v) then
      local tpl_trial = _accessoryInterimTpl:getTplById(v)
      local serverData = {}
      serverData.accessoryId = _accessoryInterimTpl:getConfigId(tpl_trial)
      serverData.level = _accessoryInterimTpl:getLevel(tpl_trial)
      serverData.group = _accessoryInterimTpl:getMainAttrGroup(tpl_trial)
      serverData.infos = {}
      for _, subId in pairs(_accessoryInterimTpl:getAccessorySub(tpl_trial)) do
        local tpl_sub = _accessorySubTpl:getTplById(subId)
        table.insert(serverData.infos, {
          type = _accessorySubTpl:getType(tpl_sub),
          key = _accessorySubTpl:getParameter(tpl_sub),
          val = _accessorySubTpl:getMaxValue(tpl_sub)
        })
      end
      table.insert(serverDataList, serverData)
    end
  end
  return self:_getAccessoryListAttDic(serverDataList)
end

function this:_getAccessoryListAttDic(serverDataList)
  local attDic = {}
  for _, serverData in pairs(serverDataList) do
    local mergeAtt = self:getMergeAttDic(serverData)
    for id, value in pairs(mergeAtt) do
      attDic[id] = (attDic[id] or 0) + value
    end
  end
  local suitAtt = self:_getActiveSuitAtt(serverDataList)
  for _, suit_skills in pairs(suitAtt) do
    for index, skillId in pairs(suit_skills) do
      local tpl_skill = _skillTpl:getTplById(skillId)
      local skillType = _skillTpl:getSkillType(tpl_skill)
      if skillType == L_Const.skillFuncType.number then
        local tpl_skillLevel = _skillLevelTpl:getTplByIdAndLevel(skillId)
        local subSkillId = _skillLevelTpl:getSubSkillId(tpl_skillLevel)
        local tpl_skillSub = _skillsubAttrupTpl:getTplById(subSkillId)
        local attDic_tmp = _skillsubAttrupTpl:getAttributeList(tpl_skillSub)
        for k2, v2 in pairs(attDic_tmp) do
          attDic[k2] = (attDic[k2] or 0) + v2
        end
      end
    end
  end
  return attDic
end

function this:getMergeAttDic(serverData)
  local attDic = {}
  local packAtt = self:getPackAtt(serverData)
  local main_att = packAtt.mainAtt
  for __, mainAttId in ipairs(main_att.attId) do
    attDic[mainAttId] = (attDic[mainAttId] or 0) + main_att.value
  end
  local sub_att = packAtt.subAtt
  for _, v2 in pairs(sub_att) do
    if not v2.lock and not v2.isSkill then
      attDic[v2.attId] = (attDic[v2.attId] or 0) + v2.value
    end
  end
  return attDic
end

function this:_getActiveSuitAtt(serverDataList)
  local accessorySetTpl = L_GameTpl:getAccessorySetTpl()
  local accessoryTpl = L_GameTpl:getAccessoryTpl()
  local suitNum = {}
  for _, v in pairs(serverDataList) do
    if not math.isEmpty(v.accessoryId) then
      local suitId = accessoryTpl:getSetId(accessoryTpl:getTplById(v.accessoryId))
      if not math.isEmpty(suitId) then
        suitNum[suitId] = suitNum[suitId] and suitNum[suitId] + 1 or 1
      end
    end
  end
  local res = {}
  for suitId, num in pairs(suitNum) do
    local tpl_accessorySet = accessorySetTpl:getTplById(suitId)
    local suitSkill = accessorySetTpl:getSkill(tpl_accessorySet)
    for _, set in pairs(suitSkill) do
      local suitIndex = set[1]
      local skillId = set[2]
      if num >= suitIndex then
        res[suitId] = res[suitId] or {}
        res[suitId][suitIndex] = skillId
      end
    end
  end
  return res, suitNum
end

function this:getSuitDesc(id)
  local tpl_accessory = _accessoryTpl:getTplById(id)
  local suitId = _accessoryTpl:getSetId(tpl_accessory)
  if math.isEmpty(suitId) then
    return {}
  else
    return self:getSuitDescBySuitId(suitId)
  end
end

function this:getSuitDescBySuitId(suitId)
  local resData = {}
  resData.suit = {}
  local tpl_accessorySet = _accessorySetTpl:getTplById(suitId)
  local suitSkill = _accessorySetTpl:getSkill(tpl_accessorySet)
  for i, set in pairs(suitSkill) do
    local suitIndex = set[1]
    local skillId = set[2]
    local skillDesc = L_GameUtil.getSkillDesc(skillId)
    local formatTxt = L_WordsTpl:getValue("notice_accessory_setnumber")
    table.insert(resData.suit, {
      index = suitIndex,
      desc = string.format(string.concat(formatTxt, "%s"), suitIndex, skillDesc)
    })
  end
  table.sort(resData.suit, function(a, b)
    return a.index < b.index
  end)
  resData.name = _accessorySetTpl:getName(tpl_accessorySet)
  return resData
end

function this:getEquipListSuitBrief(accessoryList)
  local serverDataList = {}
  for _, v in pairs(accessoryList) do
    if not math.isEmpty(v) then
      local serverData = L_AccessoryStore:getAccessory(v)
      table.insert(serverDataList, serverData)
    end
  end
  local suitAtt, suitNum = self:_getActiveSuitAtt(serverDataList)
  local tmp = {}
  for suitId, suit_skillId in pairs(suitAtt) do
    local suitData = self:getSuitDescBySuitId(suitId)
    local tpl_set = _accessorySetTpl:getTplById(suitId)
    local suitSkillList = _accessorySetTpl:getSkill(tpl_set)
    local maxSuitNum = suitSkillList[#suitSkillList][1]
    table.insert(tmp, {
      txt_suitName = suitData.name,
      txt_suitValue = string.format("\227\128\144%s/%s\227\128\145", suitNum[suitId], maxSuitNum)
    })
  end
  return tmp
end

function this:getShowLevelTxt(serverData)
  if not serverData then
    return ""
  end
  return serverData.level == 0 and "" or string.concat("+", serverData.level)
end

function this:getAccessoryNum(accessoryId)
  local cnt = 0
  for i, v in pairs(L_AccessoryStore:getHeroAccessory()) do
    if accessoryId == v.accessoryId then
      cnt = cnt + 1
    end
  end
  return cnt
end

function this:getPackAtt(serverData)
  local tpl = _accessoryTpl:getTplById(serverData.accessoryId)
  local tpl_main = _accessoryMainTpl:getTplByGroupIdAndLevel(serverData.group, serverData.level)
  local quality = _accessoryTpl:getRarity(tpl)
  local type = _accessoryTpl:getType(tpl)
  local res = {}
  local mainAtt = {}
  mainAtt.groupId = _accessoryMainTpl:getGroupId(tpl_main)
  mainAtt.attId = _accessoryMainTpl:getBattleInfo(tpl_main)
  mainAtt.value = _accessoryMainTpl:getValue(tpl_main)
  mainAtt.showName = _accessoryMainTpl:getBattleInfoName(tpl_main)
  res.mainAtt = mainAtt
  res.subAtt = {}
  local subAtt = serverData.infos
  local accessoryLvCfg = _accessoryLevelTpl:getTplByAccessoryIdAndLevel(serverData.accessoryId, serverData.level)
  if not accessoryLvCfg then
    errorf(string.format("\232\142\183\229\143\150\232\163\133\229\164\135\231\173\137\231\186\167\232\161\168\233\133\141\231\189\174\229\164\177\232\180\165,\232\175\183\230\163\128\230\159\165\233\133\141\231\189\174\230\152\175\229\144\166\230\173\163\231\161\174,quality:%s,level:%s,type:%s", quality, serverData.level, type))
  end
  local attNum = _accessoryLevelTpl:getUnlockEntry(accessoryLvCfg)
  for i, v in ipairs(subAtt) do
    local data = {}
    data.isSkill = v.type == L_AccessoryConst.SubAttrType.Skill
    data.lock = i > attNum
    if data.isSkill then
      data.skillId = v.key
      data.skillLevel = v.val
      data.desc = L_GameUtil.getSkillDesc(data.skillId, data.skillLevel)
    else
      data.attId = v.key
      data.value = v.val
      data.quality = v.quality
      data.desc = string.concat(_battleInfoTpl:getName(_battleInfoTpl:getTplById(data.attId)), self:_getColorfulValue(serverData.accessoryId, data.attId, data.value, data.quality))
    end
    if data.lock then
      data.desc = string.format("(+%s)%s", _accessoryLevelTpl:getLevelBySubAttIndex(quality, i), data.desc)
    end
    table.insert(res.subAtt, data)
  end
  res.level = serverData.level
  return res
end

function this:getPackAttByConfigId(cfgId)
  local tpl = _accessoryTpl:getTplById(cfgId)
  local mainAtt
  if _accessoryTpl:getMainAttr(tpl) and _accessoryTpl:getMainAttr(tpl)[1] then
    mainAtt = {}
    local mainAttGroupId = _accessoryTpl:getMainAttr(tpl)[1][1]
    local tpl_main = _accessoryMainTpl:getTplByGroupIdAndLevel(mainAttGroupId, 0)
    mainAtt.groupId = _accessoryMainTpl:getGroupId(tpl_main)
    mainAtt.attId = _accessoryMainTpl:getBattleInfo(tpl_main)
    mainAtt.value = _accessoryMainTpl:getValue(tpl_main)
    mainAtt.showName = _accessoryMainTpl:getBattleInfoName(tpl_main)
  end
  local res = {}
  res.mainAtt = mainAtt
  res.subAtt = {}
  res.level = 0
  return res
end

function this:getAccessoryGuidsById(accessoryId)
  local res = {}
  local allInfo = L_AccessoryStore:getHeroAccessory()
  for i, v in pairs(allInfo) do
    if accessoryId == v.accessoryId then
      table.insert(res, v.guid)
    end
  end
  table.sort(res, function(a, b)
    local va, vb = allInfo[a], allInfo[b]
    if va.level == vb.level then
      return va.guid < vb.guid
    end
    return va.level < vb.level
  end)
  return res
end

function this:_getColorfulValue(configId, attId, attValue, quality)
  local tpl = _accessoryTpl:getTplById(configId)
  local groupId = _accessoryTpl:getSubAttr(tpl)
  if math.isEmpty(groupId) then
    return string.concat("+", _battleInfoTpl:getShowTxt(attId, attValue))
  end
  if not quality then
    local tpl_sub = _accessorySubTpl:getTplByGroupIdAndParameter(groupId, attId)
    local maxValue = _accessorySubTpl:getMaxValue(tpl_sub)
    local minValue = _accessorySubTpl:getMinValue(tpl_sub)
    local perValue = (maxValue - minValue) / 5
    quality = math.clamp(math.floor((attValue - minValue) / perValue), 0, 4)
  end
  local showTxt = string.concat("+", _battleInfoTpl:getShowTxt(attId, attValue))
  local color = L_Const.colorHtml[L_RarityTpl:getEquipmentColorAst(L_RarityTpl:getTplById(quality))]
  return L_GameUtil.fillColor(showTxt, color)
end

function this:getSuitContainsDesc(suitId)
  local tplList = _accessoryTpl:getTplListBySuitId(suitId)
  local nameList = {}
  for i, v in ipairs(tplList) do
    table.insert(nameList, _accessoryTpl:getName(v))
  end
  local res = L_WordsTpl:getValue("ui_packageIncludes", {
    [0] = table.concat(nameList, "/")
  })
  return res
end

function this:getCurSelectHeroUid()
  return self.curSelectHeroUid
end

function this:setCurSelectHeroUid(uid)
  self.curSelectHeroUid = uid
end

return this
