-- 收纳箱(回收道具)

--db
--[=[
    human.db.recycleData = {
        level = nil,
        exp = nil,
    }
]=]--

local Msg = require("core.Msg")
local Lang = require("common.Lang")
local Broadcast = require("broadcast.Broadcast")
local Util = require("common.Util")
local BagLogic = require("bag.BagLogic")
local RoleAttr = require("role.RoleAttr")
local RoleDefine = require("role.RoleDefine")
local ObjHuman = require("core.ObjHuman")
local RecycleConfig = require("excel.recycleItem").RecycleLvList
local ItemConfig = require("excel.item").item
-- local RoleSystemLogic = require("roleSystem.RoleSystemLogic")
-- local RoleSystemDefine = require("roleSystem.RoleSystemDefine")

local LOG_TAG = "RecycleItem" -- 本系统的日志标识
local OPEN_COND_LV = 150 -- 开启功能需要的等级

local function initRecycleData(human)
    human.db.recycleData = { level = 0, exp = 0 }
end

local function getRecycleData(human)
    return human.db.recycleData
end

local function updateRecycleData(human, newLv, newExp)
    local recycleData = getRecycleData(human)
    if not recycleData then
        initRecycleData(human)
        recycleData = getRecycleData(human)
    end

    recycleData.level = newLv
    recycleData.exp = newExp
end


-- 是否开启本系统
local function isOpen(human)
    -- return RoleSystemLogic.isOpen(human, RoleSystemDefine.ROLE_SYS_ID_2031) -- 待修改
    return human.db.lv >= OPEN_COND_LV
end
-- 计算当前等级加成属性
local function calcCurrentLvAttrs(currentLevel)
    if not currentLevel or currentLevel <= 0 then
        return
    end

    local attrs = {}
    for i=1, currentLevel do
        local cfg = RecycleConfig[i]
        if cfg and cfg.attrs then
            for _,v in ipairs(cfg.attrs) do
                local attrId = v[1]
                local attrVal = v[2]
                attrs[attrId] = (attrs[attrId] or 0) + attrVal
            end
        end
    end

    return attrs
end
-- 重算战力
local function updatePower(human)
    RoleAttr.cleanHeroAttrCache(human)
    RoleAttr.doCalc(human)
    ObjHuman.sendAttr(human, RoleDefine.ZHANDOULI)
end
-- 计算出新的等级和经验
local function calcLv(human, addExp)
    local recycleData = getRecycleData(human)
    local currentLevel = recycleData and recycleData.level or 0
    local currentExp = recycleData and recycleData.exp or 0

    currentExp = currentExp + addExp
    local newLv = currentLevel

    for i=currentLevel+1, #RecycleConfig do
        local cfg = RecycleConfig[i]
        if currentExp < cfg.exp then
            break
        end

        currentExp = currentExp - cfg.exp
        newLv = i

        if currentExp <= 0 then
            break
        end
    end

    return newLv, currentExp
end


local function populateCurrentLvAttrs(net, currentLevel)
    local isZero = false
    if currentLevel <= 0 then
        currentLevel = 1
        isZero = true
    end

    local len = 0
    net[0] = len

    local attrs = calcCurrentLvAttrs(currentLevel)
    for attrId, attrVal in pairs(attrs or {}) do
        len = len + 1
        net[0] = len
        net[len].key = attrId
        net[len].value = isZero and 0 or attrVal
    end

end

local function populateNextLvAttrs(net, nextLv)
    local isMax = false
    local maxLv = #RecycleConfig
    if maxLv <= nextLv then
        nextLv = maxLv
        isMax = true
    end

    net[0] = 0
    local cfg = RecycleConfig[nextLv]

    if cfg and cfg.attrs then
        net[0] = #cfg.attrs
        for k,v in ipairs(cfg.attrs) do
            net[k].key = v[1]
            net[k].value = isMax and 0 or v[2]
        end
    end

end

-- local function populateRecycleItem(net, human)
--     net[0] = 0

--     local bagData = BagLogic.GetBagData(human)
--     if not bagData then
--         return
--     end

--     local len = 0
--     for itemId in pairs(bagData) do
--         local itemCfg = ItemConfig[itemId]
--         if itemCfg and itemCfg.val and itemCfg.val > 0 then
--             len = len + 1
--             net[0] = len
--             net[len].id = itemId
--             net[len].recycleVal = itemCfg.val
--         end
--     end
-- end



-- 外部调用, 统计收纳箱加成属性
function doCalcHero(human, addAttrs)
    if not human then
        return
    end

    local recycleData = getRecycleData(human)
    if not recycleData then
        return
    end

    local currentLevel = recycleData and recycleData.level or 0
    if currentLevel <= 0 then
        return
    end

    local attrs = calcCurrentLvAttrs(currentLevel)
    for attrId, attrVal in pairs(attrs or {}) do
        RoleAttr.updateValue(attrId, attrVal, addAttrs)
    end
end



-- 查询部分信息
function RecycleItem_Query(human)
    if not isOpen(human) then
        return Broadcast.sendErr(human, Lang.COMMOM_NOT_ENABLED)
    end

    local recycleData = getRecycleData(human)
    local currentLevel = recycleData and recycleData.level or 0
    local currentExp = recycleData and recycleData.exp or 0
    local maxLevel = #RecycleConfig
    local nextLvExp = 0

    if currentLevel < maxLevel then
        local nextLvCfg = RecycleConfig[currentLevel + 1]
        nextLvExp = nextLvCfg.exp
    end

    local msgRet = Msg.gc.GC_RECYCLE_QUERY
    msgRet.currentLevel = currentLevel
    msgRet.maxLevel = maxLevel
    msgRet.currentExp = currentExp
    msgRet.nextLvExp = nextLvExp

    populateCurrentLvAttrs(msgRet.currentLvAttrs, currentLevel)
    populateNextLvAttrs(msgRet.nextLvAttrs, currentLevel+1)
    -- populateRecycleItem(msgRet.recycleList, human)

    Msg.send(msgRet, human.fd)
end

-- 查询可回收道具列表
function RecycleItem_RecycleItemListQuery(human)
    if not isOpen(human) then
        return Broadcast.sendErr(human, Lang.COMMOM_NOT_ENABLED)
    end

    local msgRet = Msg.gc.GC_RECYCLE_GET_RECYCLE_LIST
    msgRet.recycleList[0] = 0
    msgRet.isStart = 1
    msgRet.isEnd = 0

    local bagData = BagLogic.GetBagData(human)
    if not bagData then
        msgRet.isEnd = 1
        return Msg.send(msgRet, human.fd)
    end

    local itemArr = {}
    for itemId in pairs(bagData) do
        local itemCfg = ItemConfig[itemId]
        if itemCfg and itemCfg.val and itemCfg.val > 0 then
            itemArr[#itemArr+1] = {itemId, itemCfg.val}
        end
    end

    local itemNum = #itemArr
    if itemNum == 0 then
        msgRet.isEnd = 1
        return Msg.send(msgRet, human.fd)
    end

    local len = 0
    local onceMsgLen = 50

    for _, itemInfo in ipairs(itemArr) do
        len = len + 1
        msgRet.recycleList[0] = len
        msgRet.recycleList[len].id = itemInfo[1]
        msgRet.recycleList[len].recycleVal = itemInfo[2]

        if len >= onceMsgLen then
            itemNum = itemNum - len
            if itemNum <= 0 then
                msgRet.isEnd = 1
                return Msg.send(msgRet, human.fd)
            end

            Msg.send(msgRet, human.fd)
            len = 0
            msgRet.isStart = 0
        end
    end

    if len > 0 then
        msgRet.isEnd = 1
        Msg.send(msgRet, human.fd)
    end
end

-- 回收道具
function RecycleItem_Recycle_Do(human, recycleItemStr)
    if not isOpen(human) then
        return Broadcast.sendErr(human, Lang.COMMOM_NOT_ENABLED)
    end

    local itemList = Util.parseKVString(recycleItemStr, "|", "-", Util.TONUMBER_ALL)
    if not next(itemList) then
        return Broadcast.sendErr(human, Lang.COMMON_ARGUMENT_ERROR)
    end

    local recycleData = getRecycleData(human)
    local currentLevel = recycleData and recycleData.level or 0
    local maxLevel = #RecycleConfig
    if currentLevel >= maxLevel then
        return Broadcast.sendErr(human, Lang.COMMON_MAXLEVEL)
    end

    local totalExp = 0
    for itemId, itemCnt in pairs(itemList) do
        local itemCfg = ItemConfig[itemId]
        if not itemCfg or not itemCfg.val or itemCfg.val <= 0 then
            return Broadcast.sendErr(human, Lang.ITEM_CANNOT_RECYCLE)
        end

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

        totalExp = totalExp + itemCfg.val * itemCnt
    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
        BagLogic.delItem(human, itemId, itemCnt, LOG_TAG)
    end

    -- 更新等级, 经验
    local newLv, newExp = calcLv(human, totalExp)
    updateRecycleData(human, newLv, newExp)

    -- 更新战力
    updatePower(human)

    -- 更新UI界面数据
    RecycleItem_Query(human)
    RecycleItem_RecycleItemListQuery(human)
end