-- 英雄神威灵装系统

--db
--[=[
    heroGrid.artifacts = {
        isActive = nil, -- 是否激活,激活后为true
        level = 0, -- 当前等级
        star = 0,  -- 当前星级
        effectArr = { --特效
            {idx = 1, isLock = 0, lv = 0}
        },

        effectArrTemp = { --新洗练出且未替换的特效
            {idx = 1, lv = 0}
        },

        beSkillArr = { --被动技能
            {idx = 1, isLock = 0}
        },

        beSkillArrTemp = { --新洗练出且未替换的被动技能
            {idx = 1}
        },
    }
]=]--

local Msg = require("core.Msg")
local BagLogic = require("bag.BagLogic")
local HeroLogic = require("hero.HeroLogic")
local ObjHuman = require("core.ObjHuman")
local Grid = require("bag.Grid")
local RoleAttr = require("role.RoleAttr")
local RoleDefine = require("role.RoleDefine")
local HeroArtifactsConfig = require("excel.heroArtifacts")
local Util = require("common.Util")
local Lang = require("common.Lang")
local Broadcast = require("broadcast.Broadcast")
local TalismanLogic = require("talisman.TalismanLogic")

local GiftLogic

local LOGTAG = "Artifacts" --日志标识


-- 获取来自秘宝的属性倍数加成
local function getAttrMulFromTalisman(human)
    local attrMul = TalismanLogic.getTalismanAdd(human, TalismanLogic.OTHER_EFFECT_TBL.HeroArtifacts_LvAttr_Mul)
    attrMul = attrMul / 100
    return attrMul
end


local function initArtifactsData(heroGrid)
    heroGrid.artifacts = {
        level = 0,
        star = 0
    }
end

local function getArtifactsData(heroGrid)
    return heroGrid.artifacts
end

local function updateArtifactsState(heroGrid, state)
    local artifactsData = getArtifactsData(heroGrid)
    if not artifactsData then
        initArtifactsData(heroGrid)
        artifactsData = getArtifactsData(heroGrid)
    end

    artifactsData.isActive = state
end

local function upGradeArtifactsLv(heroGrid, addVal)
    local artifactsData = getArtifactsData(heroGrid)
    if not artifactsData then
        initArtifactsData(heroGrid)
        artifactsData = getArtifactsData(heroGrid)
    end

    artifactsData.level = artifactsData.level + addVal
end

local function upGradeArtifactsStar(heroGrid, addVal)
    local artifactsData = getArtifactsData(heroGrid)
    if not artifactsData then
        initArtifactsData(heroGrid)
        artifactsData = getArtifactsData(heroGrid)
    end

    artifactsData.star = artifactsData.star + addVal
end

local function resetArtifactsData(heroGrid)
    local artifactsData = getArtifactsData(heroGrid)
    artifactsData.level = 0
    artifactsData.star = 0
    artifactsData.isActive = nil
    artifactsData.effectArr = nil
    artifactsData.effectArrTemp = nil
    artifactsData.beSkillArr = nil
    artifactsData.beSkillArrTemp = nil
end



-- 是否开启
local function isOpen(heroGrid)
    local varCfg = HeroArtifactsConfig.Var[1]
    if heroGrid.star < varCfg.openStarCond then
        return false
    end

    return true
end

-- 是否激活
local function isActivate(heroGrid)
    local artifactsData = getArtifactsData(heroGrid)
    return artifactsData and artifactsData.isActive
end

-- 计算当前等级/星级的属性总加成
local function calcAttrs(conf, currentStage)
    local attrList = {}
    for i=1, currentStage do
        local t = conf[i]
        local attrArr = t and t.attrArr
        for _, attrInfo in ipairs(attrArr or {}) do
            local attrId, attrVal = attrInfo[1],attrInfo[2]
            attrList[attrId] = (attrList[attrId] or 0) + attrVal
        end
    end

    return attrList
end

-- 获取神威灵装激活消耗
local function getActivateCost()
    local varCfg = HeroArtifactsConfig.Var[1]
    local activateCostTb = varCfg.activateCost
    return activateCostTb[1][1],activateCostTb[1][2]
end

-- 获取等级/星级下一阶段的消耗
local function getNextStageCost(currentStage, tp, isMax)
    local varCfg = HeroArtifactsConfig.Var[1]
    local itemId = varCfg.upGradeLvCostId
    local itemCnt = 0

    local upGradeCfg = HeroArtifactsConfig.UpGradeLv
    if tp == 2 then
        itemId = varCfg.upGradeStarCostId
        upGradeCfg = HeroArtifactsConfig.UpGradeStar
    end

    if not isMax then
        local nextStageCfg = upGradeCfg[currentStage+1]
        itemCnt = nextStageCfg.costCnt
    end

    return itemId, itemCnt
end

-- 获取升到当前等级/星级的总消耗
local function getTaotalStageCost(currentStage, tp)
    local varCfg = HeroArtifactsConfig.Var[1]
    local itemId = varCfg.upGradeLvCostId
    local itemCnt = 0

    local upGradeCfg = HeroArtifactsConfig.UpGradeLv
    if tp == 2 then
        itemId = varCfg.upGradeStarCostId
        upGradeCfg = HeroArtifactsConfig.UpGradeStar
    end

    for i=1, currentStage do
        local stageCfg = upGradeCfg[i]
        itemCnt = itemCnt + stageCfg.costCnt
    end

    return itemId, itemCnt
end

-- 填充激活灵装协议结构数据
local function populateActivateCostMsg(net)
    -- local varCfg = HeroArtifactsConfig.Var[1]
    -- local activateCostTb = varCfg.activateCost
    -- net[0] = #activateCostTb

    -- for k,v in ipairs(activateCostTb) do
    --     Grid.makeItem(net[k], v[1], v[2])
    -- end
    local itemId, itemCnt = getActivateCost()
    Grid.makeItem(net, itemId, itemCnt)
end

-- 填充灵装当前等级/星级总加成属性协议结构数据
local function populateTotalAttrMsg(human, net, n, tp)
    local t
    local attrMul = 1
    if tp == 1 then
        t = HeroArtifactsConfig.UpGradeLv
        attrMul = getAttrMulFromTalisman(human)
        attrMul = 1 + attrMul
    else
        t = HeroArtifactsConfig.UpGradeStar
    end

    local stage = n
    if n <= 0 then
        stage = 1
    end

    local attrList = calcAttrs(t, stage)

    net[0] = 0
    local len = 0
    for attrId, attrVal in pairs(attrList) do
        len = len + 1
        net[0] = len
        net[len].key = attrId
        net[len].value = (n <= 0 and 0 or attrVal) * attrMul
    end
end

-- 填充灵装下一等级/星级加成属性协议结构数据
local function populateNextAttrMsg(human, net, n, tp, isMax)
    local t
    local attrMul = 1
    if tp == 1 then
        t = HeroArtifactsConfig.UpGradeLv
        attrMul = getAttrMulFromTalisman(human)
        attrMul = 1 + attrMul
    else
        t = HeroArtifactsConfig.UpGradeStar
    end

    net[0] = 0
    local cfg = t[n]
    local attrArrCfg = cfg and cfg.attrArr
    for k,v in ipairs(attrArrCfg or {}) do
        net[0] = k
        net[k].key = v[1]
        net[k].value = (isMax and 0 or v[2]) * attrMul
    end
end

-- 判断属性是否是绝对值属性
local function isAbsAttr(attrId)
    return RoleDefine.isAbsAttr(attrId)
end

-- 填充灵装特效协议结构数据
local function populateEffectMsg(net, arr)
    for k, v in ipairs(arr) do
        net[0] = k
        local cfg = HeroArtifactsConfig.EffectList[v.idx]
        net[k].idx = v.idx
        net[k].name = cfg.name
        net[k].desc = cfg.desc
        net[k].isLock = v.isLock or 0
        net[k].isActivate = 1
        net[k].activateStarCond = 1
        net[k].level = v.lv

        local attrVal = cfg.effectAttrValArr[v.lv] or 0
        if not isAbsAttr(cfg.effectAttrId) then
            attrVal = attrVal / 100
        end
        net[k].desc = Util.format(cfg.desc, attrVal)
    end
end

-- 填充灵装被动技能协议结构数据
local function populateBeSkillMsg(net, arr)
    local varCfg = HeroArtifactsConfig.Var[1]
    for i, activateBeSkillStar in ipairs(varCfg.activateBeSkillStarList) do
        net[0] = i
        net[i].idx = i
        net[i].name = ""
        net[i].desc = ""
        net[i].isLock = 0
        net[i].isActivate = 0
        net[i].activateStarCond = activateBeSkillStar
        net[i].level = 0
        if arr and arr[i] then
            local beSkillData = arr[i]
            local cfg = HeroArtifactsConfig.BeSkillList[beSkillData.idx]
            net[i].idx = beSkillData.idx
            net[i].name = cfg.name
            net[i].desc = cfg.desc
            net[i].isLock = beSkillData.isLock or 0
            net[i].isActivate = 1
        end
    end
end

-- 计算特效/被动技能的锁定数量
local function calcLockNum(arr)
    local lockNum = 0
    for _, v in ipairs(arr or {}) do
        if v.isLock and v.isLock == 1 then
            lockNum = lockNum + 1
        end
    end

    return lockNum
end

-- 计算特效/被动技能洗练需要消耗的道具
local function calcRefineCost(data, costIdArr, costNumArr)
    if not costIdArr or not costNumArr then
        return
    end

    if #costIdArr ~= #costNumArr then
        return
    end

    local lockNum = calcLockNum(data)
    lockNum = lockNum + 1

    local itemList = {}
    for i=1, #costIdArr do
        local itemId = costIdArr[i]
        local itemCntArr = costNumArr[i]
        local itemCnt = itemCntArr and itemCntArr[lockNum]
        if not itemId or not itemCnt then
            return
        end

        itemList[itemId] = (itemList[itemId] or 0) + itemCnt
    end

    return itemList
end

-- 生成要排除的特效/被动技能列表
local function genExcludeList(arr)
    if not arr then
        return
    end

    local excludeList = {}
    for _, v in ipairs(arr) do
        excludeList[v.idx] = true
    end

    return excludeList
end

-- 随机一个特效/被动技能
local function randEffect(conf, excludeList)
    local totalWeight = 0
    local arr = {}

    for k,v in ipairs(conf) do
        if not excludeList or not excludeList[k] then
            totalWeight = totalWeight + v.weight
            arr[#arr+1] = {weight = v.weight, idx = k}
        end
    end

    local weight = 0
    local randVal = math.random(1, totalWeight)
    for _, v in ipairs(arr) do
        weight = weight + v.weight
        if randVal <= weight then
            return v.idx
        end
    end
end

-- 随机一个特效的等级
local function randEffectLv()
    local totalWeight = 0
    for k,v in ipairs(HeroArtifactsConfig.EffectLvProb) do
        totalWeight = totalWeight + v.weight
    end

    local weight = 0
    local randVal = math.random(1, totalWeight)
    for _, v in ipairs(HeroArtifactsConfig.EffectLvProb) do
        weight = weight + v.weight
        if randVal <= weight then
            return v.level
        end
    end
end

-- 更新战力
local function updatePower(human)
    RoleAttr.cleanHeroAttrCache(human)
    ObjHuman.doCalc(human)
    ObjHuman.sendAttr(human, RoleDefine.ZHANDOULI)
end

-- 更新英雄属性
local function updateHeroAttr(human, heroID, heroIndex)
    HeroLogic.sendHeroBagDynamic(human, heroID, heroIndex)
end

-- 刷新红点
local function updateRedDot(human, heroGrid)
    HeroLogic.refreshDot(human, heroGrid.uuid)
end

-- 刷新战力, 红点, 英雄属性
local function updatePowerAndRedDot(human, heroGrid, heroID, heroIndex)
    -- 更新战力
    updatePower(human)

    -- 刷新红点
    updateRedDot(human, heroGrid)

    -- 刷新英雄属性
    updateHeroAttr(human, heroID, heroIndex)
end

-- 能否升级
local function isCanUpGradeLv(human, heroGrid)
    local artifactsData = getArtifactsData(heroGrid)
    local currentLevel = artifactsData and artifactsData.level or 0
    local maxLevel = HeroArtifactsConfig.UpGradeLv[#HeroArtifactsConfig.UpGradeLv].level

    if currentLevel < maxLevel then
        local itemId, itemCnt = getNextStageCost(currentLevel, 1)
        if BagLogic.getItemCnt(human, itemId) >= itemCnt then
            return true
        end
    end

    return false
end

-- 能否升星
local function isCanUpGradeStar(human, heroGrid)
    local artifactsData = getArtifactsData(heroGrid)
    local currentStar = artifactsData and artifactsData.star or 0
    local maxStar = HeroArtifactsConfig.UpGradeStar[#HeroArtifactsConfig.UpGradeStar].star

    if currentStar < maxStar then
        local itemId, itemCnt = getNextStageCost(currentStar, 2)
        if BagLogic.getItemCnt(human, itemId) >= itemCnt then
            return true
        end
    end

    return false
end




-- 获取神威灵装的被动技能
function GetArtifactsBeSkillList(heroGrid)
    if not heroGrid or not heroGrid.artifacts then
        return
    end

    local beSkillArr = heroGrid.artifacts.beSkillArr
    if not beSkillArr then
        return
    end

    local skillArr
    for _, skillInfo in ipairs(beSkillArr) do
        local cfgIdx = skillInfo.idx
        local skillCfg = HeroArtifactsConfig.BeSkillList[cfgIdx]
        if skillCfg and skillCfg.skillType == 2 then
            skillArr = skillArr or {}
            skillArr[#skillArr+1] = skillCfg.skillId
        end
    end

    return skillArr
end

-- 获取神威灵装对符文/战意的属性加成列表
function GetFuwenStrengthenAttrList(heroGrid)
    if not heroGrid or not heroGrid.artifacts then
        return
    end

    local beSkillArr = heroGrid.artifacts.beSkillArr
    if not beSkillArr then
        return
    end

    local skillId_2_Attr = nil

    for _, skillInfo in ipairs(beSkillArr) do
        local skillCfg = HeroArtifactsConfig.BeSkillList[skillInfo.idx]
        if skillCfg and skillCfg.skillType == 1 and next(skillCfg.attr) then
            local attrArr = {}
            for i, attrInfo in ipairs(skillCfg.attr) do
                attrArr[i] = {attrInfo[1], attrInfo[2]}
            end

            skillId_2_Attr = skillId_2_Attr or {}

            for _, fuwenSkillId in ipairs(skillCfg.fuwenSkillIdArr) do
                skillId_2_Attr[fuwenSkillId] = attrArr
            end
        end
    end

    return skillId_2_Attr
end

-- 获取神威灵装对符文/战意的强化技能列表
function GetFuwenStrengthenSkillList(heroGrid)
    if not heroGrid or not heroGrid.artifacts then
        return
    end

    local beSkillArr = heroGrid.artifacts.beSkillArr
    if not beSkillArr then
        return
    end

    local skillId_2_strengthenSkillId = nil

    for _, skillInfo in ipairs(beSkillArr) do
        local skillCfg = HeroArtifactsConfig.BeSkillList[skillInfo.idx]
        if skillCfg and skillCfg.skillType == 1 and next(skillCfg.strengthenSkillIdArr) then
            skillId_2_strengthenSkillId = skillId_2_strengthenSkillId or {}
            for i, fuwenSkillId in ipairs(skillCfg.fuwenSkillIdArr) do
                skillId_2_strengthenSkillId[fuwenSkillId] = skillCfg.strengthenSkillIdArr[i]
            end
        end
    end

    return skillId_2_strengthenSkillId
end

-- 神威灵装加成
function doCalcHero(human, heroGrid, addAttrs)
    if not heroGrid or not heroGrid.artifacts then
        return
    end

    local artifactsData = heroGrid.artifacts

    if artifactsData.level > 0 then
        local attrMul = getAttrMulFromTalisman(human)
        attrMul = 1 + attrMul

        local attrList = calcAttrs(HeroArtifactsConfig.UpGradeLv, artifactsData.level)
        for attrId, attrVal in pairs(attrList) do
            RoleAttr.updateValue(attrId, attrVal * attrMul, addAttrs)
        end
    end

    if artifactsData.star > 0 then
        local attrList = calcAttrs(HeroArtifactsConfig.UpGradeStar, artifactsData.star)
        for attrId, attrVal in pairs(attrList) do
            RoleAttr.updateValue(attrId, attrVal, addAttrs)
        end
    end

    -- 特效
    if artifactsData.effectArr then
        for _, effectInfo in ipairs(artifactsData.effectArr) do
            local effectCfg = HeroArtifactsConfig.EffectList[effectInfo.idx]
            if effectCfg then
                local effectLv = effectInfo.lv
                local attrId = effectCfg.effectAttrId
                local attrVal = effectCfg.effectAttrValArr[effectLv] or 0
                RoleAttr.updateValue(attrId, attrVal, addAttrs)
            end
        end
    end
end

-- 红点判断
function isArtifactsDot(human, heroGrid)
    if not isOpen(heroGrid) then
        return false
    end

    if not isActivate(heroGrid) then
        local varCfg = HeroArtifactsConfig.Var[1]
        local activateCostTb = varCfg.activateCost
        local itemId, itemCnt = activateCostTb[1][1], activateCostTb[1][2]
        if BagLogic.getItemCnt(human, itemId) >= itemCnt then
            return true
        end

        return false
    end

    if isCanUpGradeLv(human, heroGrid) then
        return true
    end

    if isCanUpGradeStar(human, heroGrid) then
        return true
    end

    return false
end

-- 返还材料计算
function CalcReturnItem(human, heroGrid)
    if not isOpen(heroGrid) then
        return
    end

    if not isActivate(heroGrid) then
        return
    end

    local artifactsData = getArtifactsData(heroGrid)

    local itemList = {}
    local itemId, itemCnt = getActivateCost()
    itemList[itemId] = (itemList[itemId] or 0) + itemCnt

    if artifactsData and artifactsData.level > 0 then
        itemId, itemCnt = getTaotalStageCost(artifactsData.level, 1)
        itemList[itemId] = (itemList[itemId] or 0) + itemCnt
    end

    if artifactsData and artifactsData.star > 0 then
        itemId, itemCnt = getTaotalStageCost(artifactsData.star, 2)
        itemList[itemId] = (itemList[itemId] or 0) + itemCnt
    end

    return itemList
end

-- 重置神威灵装数据
function ResetArtifactsData(human, heroGrid)
    if not isOpen(heroGrid) then
        return
    end

    if not isActivate(heroGrid) then
        return
    end

    resetArtifactsData(heroGrid)
end




-- 神威灵装基础信息查询
function HeroArtifacts_Base_Query(human, heroID, heroIndex)
    local heroGrid = HeroLogic.getHeroGrid(human, heroID, heroIndex)
    if not heroGrid then
        return Broadcast.sendErr(human, Lang.FUWEN_HERO_GRID_ERR)
    end

    if not isOpen(heroGrid) then
        return Broadcast.sendErr(human, Lang.HEROPUB_STAR_NOT_ENOUGH)
    end

    local artifactsData = getArtifactsData(heroGrid)
    local currentLevel = artifactsData and artifactsData.level or 0
    local currentStar = artifactsData and artifactsData.star or 0

    local msgRet = Msg.gc.GC_HEROARTIFACTS_BASE_QUERY
    msgRet.artifactsLv = currentLevel
    msgRet.artifactsStar = currentStar
    msgRet.nowLevelAttrs[0] = 0
    msgRet.nowStarAttrs[0] = 0
    msgRet.effectArr[0] = 0
    msgRet.beSkillArr[0] = 0
    msgRet.isActivate = 0
    msgRet.redDotArr[0] = 2
    msgRet.redDotArr[1] = 0
    msgRet.redDotArr[2] = 0

    populateActivateCostMsg(msgRet.ActivateCost)
    populateTotalAttrMsg(human, msgRet.nowLevelAttrs, currentLevel, 1)
    populateTotalAttrMsg(human, msgRet.nowStarAttrs, currentStar, 2)

    if artifactsData and artifactsData.effectArr then
        populateEffectMsg(msgRet.effectArr, artifactsData.effectArr)
    end

    populateBeSkillMsg(msgRet.beSkillArr, artifactsData and artifactsData.beSkillArr)

    if isActivate(heroGrid) then
        msgRet.isActivate = 1

        if isCanUpGradeLv(human, heroGrid) then
            msgRet.redDotArr[1] = 1
        end

        if isCanUpGradeStar(human, heroGrid) then
            msgRet.redDotArr[2] = 1
        end
    end

    Msg.send(msgRet, human.fd)
end

-- 激活神威灵装
function HeroArtifacts_Activate(human, heroID, heroIndex)
    local heroGrid = HeroLogic.getHeroGrid(human, heroID, heroIndex)
    if not heroGrid then
        return Broadcast.sendErr(human, Lang.FUWEN_HERO_GRID_ERR)
    end

    if not isOpen(heroGrid) then
        return Broadcast.sendErr(human, Lang.HEROPUB_STAR_NOT_ENOUGH)
    end

    if isActivate(heroGrid) then
        return Broadcast.sendErr(human, Lang.BINGSHU_LEARN_ERR_HAD)
    end

    local itemId, itemCnt = getActivateCost()
    if BagLogic.getItemCnt(human, itemId) < itemCnt then
        return Broadcast.sendErr(human, Lang.COMMON_ITEM_NOT_ENOUGH)
    end

    BagLogic.delItem(human, itemId, itemCnt, LOGTAG)

    updateArtifactsState(heroGrid, true)

    HeroArtifacts_Base_Query(human, heroID, heroIndex)

    updateHeroAttr(human, heroID, heroIndex)

    -- 弹窗礼包
    GiftLogic = GiftLogic or require("topup.GiftLogic")
    GiftLogic.trigger(human, GiftLogic.GIFT_ARTIFACTS_OPEN, {currentVal = 0}, GiftLogic.GIFT_SEC_TYPE3)
end

-- 神威灵装升级信息查询
function HeroArtifacts_Lv_Query(human, heroID, heroIndex)
    local heroGrid = HeroLogic.getHeroGrid(human, heroID, heroIndex)
    if not heroGrid then
        return Broadcast.sendErr(human, Lang.FUWEN_HERO_GRID_ERR)
    end

    if not isOpen(heroGrid) then
        return Broadcast.sendErr(human, Lang.HEROPUB_STAR_NOT_ENOUGH)
    end

    if not isActivate(heroGrid) then
        return Broadcast.sendErr(human, Lang.HERO_AF_NOT_ACTIVATE)
    end

    local artifactsData = getArtifactsData(heroGrid)
    local UpGradeLvCfg = HeroArtifactsConfig.UpGradeLv

    local currentLevel = artifactsData and artifactsData.level or 0
    local maxLevel = UpGradeLvCfg[#UpGradeLvCfg].level
    local isMax = currentLevel >= maxLevel
    local nextLevel = isMax and maxLevel or currentLevel + 1

    local msgRet = Msg.gc.GC_HEROARTIFACTS_LV_QUERY
    msgRet.artifactsLv = currentLevel
    msgRet.artifactsLvMax = maxLevel
    populateTotalAttrMsg(human, msgRet.nowLevelAttrs, currentLevel, 1)
    populateNextAttrMsg(human, msgRet.nextLevelAttrs, nextLevel, 1, isMax)

    local itemId, itemCnt = getNextStageCost(currentLevel, 1, isMax)
    Grid.makeItem(msgRet.cost, itemId, itemCnt)

    Msg.send(msgRet, human.fd)
end

-- 神威灵装升级
function HeroArtifacts_UpGrade_Level(human, heroID, heroIndex)
    local heroGrid = HeroLogic.getHeroGrid(human, heroID, heroIndex)
    if not heroGrid then
        return Broadcast.sendErr(human, Lang.FUWEN_HERO_GRID_ERR)
    end

    if not isOpen(heroGrid) then
        return Broadcast.sendErr(human, Lang.HEROPUB_STAR_NOT_ENOUGH)
    end

    if not isActivate(heroGrid) then
        return Broadcast.sendErr(human, Lang.HERO_AF_NOT_ACTIVATE)
    end

    local artifactsData = getArtifactsData(heroGrid)
    local currentLevel = artifactsData and artifactsData.level or 0

    local UpGradeLvCfg = HeroArtifactsConfig.UpGradeLv
    local maxLevel = UpGradeLvCfg[#UpGradeLvCfg].level

    if currentLevel >= maxLevel then
        return Broadcast.sendErr(human, Lang.HERO_AF_LV_MAX)
    end

    local itemId, itemCnt = getNextStageCost(currentLevel, 1)
    if BagLogic.getItemCnt(human, itemId) < itemCnt then
        return Broadcast.sendErr(human, Lang.COMMON_ITEM_NOT_ENOUGH)
    end
    BagLogic.delItem(human, itemId, itemCnt, LOGTAG)

    upGradeArtifactsLv(heroGrid, 1)

    HeroArtifacts_Lv_Query(human, heroID, heroIndex)

    updatePowerAndRedDot(human, heroGrid, heroID, heroIndex)

    HeroArtifacts_Base_Query(human, heroID, heroIndex)
end

-- 神威灵装升星信息查询
function HeroArtifacts_Star_Query(human, heroID, heroIndex)
    local heroGrid = HeroLogic.getHeroGrid(human, heroID, heroIndex)
    if not heroGrid then
        return Broadcast.sendErr(human, Lang.FUWEN_HERO_GRID_ERR)
    end

    if not isOpen(heroGrid) then
        return Broadcast.sendErr(human, Lang.HEROPUB_STAR_NOT_ENOUGH)
    end

    if not isActivate(heroGrid) then
        return Broadcast.sendErr(human, Lang.HERO_AF_NOT_ACTIVATE)
    end

    local artifactsData = getArtifactsData(heroGrid)
    local upGradeStarCfg = HeroArtifactsConfig.UpGradeStar

    local currentStar = artifactsData and artifactsData.star or 0
    local maxStar = upGradeStarCfg[#upGradeStarCfg].star
    local isMax = currentStar >= maxStar
    local nextStar = isMax and maxStar or currentStar + 1

    local msgRet = Msg.gc.GC_HEROARTIFACTS_STAR_QUERY
    msgRet.artifactsStar = currentStar
    msgRet.artifactsStarMax = maxStar
    populateTotalAttrMsg(human, msgRet.nowStarAttrs, currentStar, 2)
    populateNextAttrMsg(human, msgRet.nextStarAttrs, nextStar, 2, isMax)

    local itemId, itemCnt = getNextStageCost(currentStar, 2, isMax)
    Grid.makeItem(msgRet.cost, itemId, itemCnt)

    msgRet.effectArr[0] = 0
    if artifactsData and artifactsData.effectArr then
        populateEffectMsg(msgRet.effectArr, artifactsData.effectArr)
    end

    populateBeSkillMsg(msgRet.beSkillArr, artifactsData and artifactsData.beSkillArr)

    Msg.send(msgRet, human.fd)
end

-- 神威灵装升星
function HeroArtifacts_UpGrade_Star(human, heroID, heroIndex)
    local heroGrid = HeroLogic.getHeroGrid(human, heroID, heroIndex)
    if not heroGrid then
        return Broadcast.sendErr(human, Lang.FUWEN_HERO_GRID_ERR)
    end

    if not isOpen(heroGrid) then
        return Broadcast.sendErr(human, Lang.HEROPUB_STAR_NOT_ENOUGH)
    end

    if not isActivate(heroGrid) then
        return Broadcast.sendErr(human, Lang.HERO_AF_NOT_ACTIVATE)
    end

    local artifactsData = getArtifactsData(heroGrid)
    local currentStar = artifactsData and artifactsData.star or 0

    local upGradeStarCfg = HeroArtifactsConfig.UpGradeStar
    local maxStar = upGradeStarCfg[#upGradeStarCfg].star

    if currentStar >= maxStar then
        return Broadcast.sendErr(human, Lang.HERO_AF_LV_STAR)
    end

    local itemId, itemCnt = getNextStageCost(currentStar, 2)
    if BagLogic.getItemCnt(human, itemId) < itemCnt then
        return Broadcast.sendErr(human, Lang.COMMON_ITEM_NOT_ENOUGH)
    end
    BagLogic.delItem(human, itemId, itemCnt, LOGTAG)

    -- 更新英雄星级
    upGradeArtifactsStar(heroGrid, 1)

    local nextStar = currentStar + 1
    local varCfg = HeroArtifactsConfig.Var[1]

    -- 激活新的特效
    if table.find(varCfg.activateEffectStarList, nextStar) then
        local excludeList = nil
        if artifactsData.effectArr then
            excludeList = genExcludeList(artifactsData.effectArr)
        end

        local effectIdx = randEffect(HeroArtifactsConfig.EffectList, excludeList)
        if not effectIdx then
            return Broadcast.sendErr(human, Lang.COMMON_COMFIG_ERROR)
        end

        local effectLv = randEffectLv()
        if not effectLv then
            return Broadcast.sendErr(human, Lang.COMMON_COMFIG_ERROR)
        end

        artifactsData.effectArr = artifactsData.effectArr or {}
        table.insert(artifactsData.effectArr, {idx = effectIdx, lv = effectLv})

        -- 处理新获得特效后，可能导致洗练界面两边数量不一致的情况
        if artifactsData.effectArrTemp then
            table.insert(artifactsData.effectArrTemp, {idx = effectIdx, lv = effectLv})
        end
    end

    -- 激活新的被动技能
    if table.find(varCfg.activateBeSkillStarList, nextStar) then
        local excludeList = nil
        if artifactsData.beSkillArr then
            excludeList = genExcludeList(artifactsData.beSkillArr)
        end

        local beSkillIdx = randEffect(HeroArtifactsConfig.BeSkillList, excludeList)
        if not beSkillIdx then
            return Broadcast.sendErr(human, Lang.COMMON_COMFIG_ERROR)
        end

        artifactsData.beSkillArr = artifactsData.beSkillArr or {}
        table.insert(artifactsData.beSkillArr, {idx = beSkillIdx} )

        -- 处理新获得被动技能后，可能导致洗练界面两边数量不一致的情况
        if artifactsData.beSkillArrTemp then
            table.insert(artifactsData.beSkillArrTemp, {idx = beSkillIdx} )
        end
    end

    HeroArtifacts_Star_Query(human, heroID, heroIndex)

    updatePowerAndRedDot(human, heroGrid, heroID, heroIndex)

    HeroArtifacts_Base_Query(human, heroID, heroIndex)

    -- 弹窗礼包
    GiftLogic = GiftLogic or require("topup.GiftLogic")
    GiftLogic.trigger(human, GiftLogic.GIFT_ARTIFACTS_UPGRADE_STAR, {currentVal = nextStar}, GiftLogic.GIFT_SEC_TYPE3)
end

-- 神威灵装特效洗练信息查询
function HeroArtifacts_EffectRefine_Query(human, heroID, heroIndex)
    local heroGrid = HeroLogic.getHeroGrid(human, heroID, heroIndex)
    if not heroGrid then
        return Broadcast.sendErr(human, Lang.FUWEN_HERO_GRID_ERR)
    end

    if not isOpen(heroGrid) then
        return Broadcast.sendErr(human, Lang.HEROPUB_STAR_NOT_ENOUGH)
    end

    if not isActivate(heroGrid) then
        return Broadcast.sendErr(human, Lang.HERO_AF_NOT_ACTIVATE)
    end

    local artifactsData = getArtifactsData(heroGrid)
    local msgRet = Msg.gc.GC_HEROARTIFACTS_EFFECT_REFINE_QUERY
    msgRet.effectArr[0] = 0
    msgRet.effectArrTemp[0] = 0

    if artifactsData and artifactsData.effectArr then
        populateEffectMsg(msgRet.effectArr, artifactsData.effectArr)
    end

    if artifactsData and artifactsData.effectArrTemp then
        populateEffectMsg(msgRet.effectArrTemp, artifactsData.effectArrTemp)
    end

    msgRet.cost[0] = 0

    local varCfg = HeroArtifactsConfig.Var[1]
    local itemList = calcRefineCost(artifactsData and artifactsData.effectArr, varCfg.lockEffectCostIdList, varCfg.lockEffectCostNumList)
    if not itemList then
        return Broadcast.sendErr(human, Lang.DATA_ERR)
    end

    local len = 0
    for itemId, itemCnt in pairs(itemList) do
        len = len + 1
        msgRet.cost[0] = len
        Grid.makeItem(msgRet.cost[len], itemId, itemCnt)
    end

    Msg.send(msgRet, human.fd)
end

-- 锁定/解锁神威灵装特效
function HeroArtifacts_Effect_Lock(human, heroID, heroIndex, effectIdxArr)
    local heroGrid = HeroLogic.getHeroGrid(human, heroID, heroIndex)
    if not heroGrid then
        return Broadcast.sendErr(human, Lang.FUWEN_HERO_GRID_ERR)
    end

    if not isOpen(heroGrid) then
        return Broadcast.sendErr(human, Lang.HEROPUB_STAR_NOT_ENOUGH)
    end

    if not isActivate(heroGrid) then
        return Broadcast.sendErr(human, Lang.HERO_AF_NOT_ACTIVATE)
    end

    local artifactsData = getArtifactsData(heroGrid)
    if not artifactsData or not artifactsData.effectArr then
        return Broadcast.sendErr(human, Lang.HERO_AF_NO_EFFECT)
    end

    if artifactsData.effectArrTemp then
        return Broadcast.sendErr(human, Lang.HERO_AF_NEED_HANDLE_REFINE)
    end

    if effectIdxArr[0] >= #artifactsData.effectArr then
        return Broadcast.sendErr(human, Lang.HERO_AF_CANNOT_LOCK)
    end

    local lockIdxArr = {}
    for i=1,effectIdxArr[0] do
        lockIdxArr[i] = effectIdxArr[i]
    end

    for _, v in ipairs(artifactsData.effectArr) do
        if table.find(lockIdxArr, v.idx) then
            v.isLock = 1
        else
            v.isLock = 0
        end
    end

    HeroArtifacts_EffectRefine_Query(human, heroID, heroIndex)
end

-- 洗练神威灵装特效
function HeroArtifacts_EffectRefine_Do(human, heroID, heroIndex)
    local heroGrid = HeroLogic.getHeroGrid(human, heroID, heroIndex)
    if not heroGrid then
        return Broadcast.sendErr(human, Lang.FUWEN_HERO_GRID_ERR)
    end

    if not isOpen(heroGrid) then
        return Broadcast.sendErr(human, Lang.HEROPUB_STAR_NOT_ENOUGH)
    end

    if not isActivate(heroGrid) then
        return Broadcast.sendErr(human, Lang.HERO_AF_NOT_ACTIVATE)
    end

    local artifactsData = getArtifactsData(heroGrid)
    if not artifactsData or not artifactsData.effectArr then
        return Broadcast.sendErr(human, Lang.HERO_AF_NO_EFFECT)
    end

    local varCfg = HeroArtifactsConfig.Var[1]
    local itemList = calcRefineCost(artifactsData.effectArr, varCfg.lockEffectCostIdList, varCfg.lockEffectCostNumList)
    if not itemList then
        return Broadcast.sendErr(human, Lang.DATA_ERR)
    end

    for itemId, itemCnt in pairs(itemList) do
        if BagLogic.getItemCnt(human, itemId) < itemCnt then
            return Broadcast.sendErr(human, Lang.COMMON_ITEM_NOT_ENOUGH)
        end
    end

    for itemId, itemCnt in pairs(itemList) do
        BagLogic.delItem(human, itemId, itemCnt, LOGTAG)
    end

    artifactsData.effectArrTemp = Util.copyTable(artifactsData.effectArr)

    for _, effctInfo in ipairs(artifactsData.effectArrTemp) do
        if not effctInfo.isLock or effctInfo.isLock == 0 then
            local excludeList = genExcludeList(artifactsData.effectArrTemp)
            local effectIdx = randEffect(HeroArtifactsConfig.EffectList, excludeList)
            effctInfo.idx = effectIdx
            local effectLv = randEffectLv()
            effctInfo.lv = effectLv
        end
    end

    HeroArtifacts_EffectRefine_Query(human, heroID, heroIndex)
end

-- 处理洗练出的神威灵装特效
-- opType: 0-放弃，1-替换
function HeroArtifacts_EffectRefine_Handle(human, heroID, heroIndex, opType)
    local heroGrid = HeroLogic.getHeroGrid(human, heroID, heroIndex)
    if not heroGrid then
        return Broadcast.sendErr(human, Lang.FUWEN_HERO_GRID_ERR)
    end

    if not isOpen(heroGrid) then
        return Broadcast.sendErr(human, Lang.HEROPUB_STAR_NOT_ENOUGH)
    end

    if not isActivate(heroGrid) then
        return Broadcast.sendErr(human, Lang.HERO_AF_NOT_ACTIVATE)
    end

    if opType ~= 0 and opType ~= 1 then
        return Broadcast.sendErr(human, Lang.COMMON_ARGUMENT_ERROR)
    end

    local artifactsData = getArtifactsData(heroGrid)
    if not artifactsData or not artifactsData.effectArrTemp then
        return Broadcast.sendErr(human, Lang.HERO_AF_NO_REFINE_EFFECT)
    end

    if opType == 1 then
        for i, v in ipairs(artifactsData.effectArrTemp) do
            artifactsData.effectArr[i].idx = v.idx
            artifactsData.effectArr[i].lv = v.lv
        end
    end

    artifactsData.effectArrTemp = nil

    HeroArtifacts_EffectRefine_Query(human, heroID, heroIndex)

    updatePower(human)

    updateHeroAttr(human, heroID, heroIndex)
end

-- 神威灵装被动技能洗练信息查询
function HeroArtifacts_BeSkillRefine_Query(human, heroID, heroIndex)
    local heroGrid = HeroLogic.getHeroGrid(human, heroID, heroIndex)
    if not heroGrid then
        return Broadcast.sendErr(human, Lang.FUWEN_HERO_GRID_ERR)
    end

    if not isOpen(heroGrid) then
        return Broadcast.sendErr(human, Lang.HEROPUB_STAR_NOT_ENOUGH)
    end

    if not isActivate(heroGrid) then
        return Broadcast.sendErr(human, Lang.HERO_AF_NOT_ACTIVATE)
    end

    local artifactsData = getArtifactsData(heroGrid)
    local msgRet = Msg.gc.GC_HEROARTIFACTS_BESKILL_REFINE_QUERY
    msgRet.beSkillArr[0] = 0
    msgRet.beSkillArrTemp[0] = 0

    if artifactsData and artifactsData.beSkillArr then
        populateBeSkillMsg(msgRet.beSkillArr, artifactsData.beSkillArr)
    end

    if artifactsData and artifactsData.beSkillArrTemp then
        populateBeSkillMsg(msgRet.beSkillArrTemp, artifactsData.beSkillArrTemp)
    end

    msgRet.cost[0] = 0

    local varCfg = HeroArtifactsConfig.Var[1]
    local itemList = calcRefineCost(artifactsData and artifactsData.beSkillArr, varCfg.lockBeSkillCostIdList, varCfg.lockBeSkillCostNumList)
    if not itemList then
        return Broadcast.sendErr(human, Lang.DATA_ERR)
    end

    local len = 0
    for itemId, itemCnt in pairs(itemList) do
        len = len + 1
        msgRet.cost[0] = len
        Grid.makeItem(msgRet.cost[len], itemId, itemCnt)
    end

    Msg.send(msgRet, human.fd)
end

-- 锁定/解锁神威灵装被动技能
function HeroArtifacts_BeSkill_Lock(human, heroID, heroIndex, beSkillIdxArr)
    local heroGrid = HeroLogic.getHeroGrid(human, heroID, heroIndex)
    if not heroGrid then
        return Broadcast.sendErr(human, Lang.FUWEN_HERO_GRID_ERR)
    end

    if not isOpen(heroGrid) then
        return Broadcast.sendErr(human, Lang.HEROPUB_STAR_NOT_ENOUGH)
    end

    if not isActivate(heroGrid) then
        return Broadcast.sendErr(human, Lang.HERO_AF_NOT_ACTIVATE)
    end

    local artifactsData = getArtifactsData(heroGrid)
    if not artifactsData or not artifactsData.beSkillArr then
        return Broadcast.sendErr(human, Lang.HERO_AF_NO_BESKILL)
    end

    if artifactsData.beSkillArrTemp then
        return Broadcast.sendErr(human, Lang.HERO_AF_NEED_HANDLE_REFINE)
    end

    if beSkillIdxArr[0] >= #artifactsData.beSkillArr then
        return Broadcast.sendErr(human, Lang.HERO_AF_CANNOT_LOCK)
    end

    local lockIdxArr = {}
    for i=1,beSkillIdxArr[0] do
        lockIdxArr[i] = beSkillIdxArr[i]
    end

    for _, v in ipairs(artifactsData.beSkillArr) do
        if table.find(lockIdxArr, v.idx) then
            v.isLock = 1
        else
            v.isLock = 0
        end
    end

    HeroArtifacts_BeSkillRefine_Query(human, heroID, heroIndex)
end

-- 洗练神威灵装被动技能
function HeroArtifacts_BeSkillRefine_Do(human, heroID, heroIndex)
    local heroGrid = HeroLogic.getHeroGrid(human, heroID, heroIndex)
    if not heroGrid then
        return Broadcast.sendErr(human, Lang.FUWEN_HERO_GRID_ERR)
    end

    if not isOpen(heroGrid) then
        return Broadcast.sendErr(human, Lang.HEROPUB_STAR_NOT_ENOUGH)
    end

    if not isActivate(heroGrid) then
        return Broadcast.sendErr(human, Lang.HERO_AF_NOT_ACTIVATE)
    end

    local artifactsData = getArtifactsData(heroGrid)
    if not artifactsData or not artifactsData.beSkillArr then
        return Broadcast.sendErr(human, Lang.HERO_AF_NO_BESKILL)
    end

    local varCfg = HeroArtifactsConfig.Var[1]
    local itemList = calcRefineCost(artifactsData.beSkillArr, varCfg.lockBeSkillCostIdList, varCfg.lockBeSkillCostNumList)
    if not itemList then
        return Broadcast.sendErr(human, Lang.DATA_ERR)
    end

    for itemId, itemCnt in pairs(itemList) do
        if BagLogic.getItemCnt(human, itemId) < itemCnt then
            return Broadcast.sendErr(human, Lang.COMMON_ITEM_NOT_ENOUGH)
        end
    end

    for itemId, itemCnt in pairs(itemList) do
        BagLogic.delItem(human, itemId, itemCnt, LOGTAG)
    end

    artifactsData.beSkillArrTemp = Util.copyTable(artifactsData.beSkillArr)

    for _, beSkillInfo in ipairs(artifactsData.beSkillArrTemp) do
        if not beSkillInfo.isLock or beSkillInfo.isLock == 0 then
            local excludeList = genExcludeList(artifactsData.beSkillArrTemp)
            local beSkillIdx = randEffect(HeroArtifactsConfig.BeSkillList, excludeList)
            beSkillInfo.idx = beSkillIdx
        end
    end

    HeroArtifacts_BeSkillRefine_Query(human, heroID, heroIndex)
end

-- 处理洗练出的神威灵装被动技能
-- opType: 0-放弃，1-替换
function HeroArtifacts_BeSkillRefine_Handle(human, heroID, heroIndex, opType)
    local heroGrid = HeroLogic.getHeroGrid(human, heroID, heroIndex)
    if not heroGrid then
        return Broadcast.sendErr(human, Lang.FUWEN_HERO_GRID_ERR)
    end

    if not isOpen(heroGrid) then
        return Broadcast.sendErr(human, Lang.HEROPUB_STAR_NOT_ENOUGH)
    end

    if not isActivate(heroGrid) then
        return Broadcast.sendErr(human, Lang.HERO_AF_NOT_ACTIVATE)
    end

    if opType ~= 0 and opType ~= 1 then
        return Broadcast.sendErr(human, Lang.COMMON_ARGUMENT_ERROR)
    end

    local artifactsData = getArtifactsData(heroGrid)
    if not artifactsData or not artifactsData.beSkillArrTemp then
        return Broadcast.sendErr(human, Lang.HERO_AF_NO_REFINE_BESKILL)
    end

    if opType == 1 then
        for i, v in ipairs(artifactsData.beSkillArrTemp) do
            artifactsData.beSkillArr[i].idx = v.idx
        end
    end
    artifactsData.beSkillArrTemp = nil

    HeroArtifacts_BeSkillRefine_Query(human, heroID, heroIndex)

    updatePower(human)

    updateHeroAttr(human, heroID, heroIndex)
end