local Msg                    = require("core.Msg")
local Broadcast              = require("broadcast.Broadcast")
local Lang                   = require("common.Lang")
local Grid                   = require("bag.Grid")
local MergeRule              = require("excel.mergeConfig").rule
local BagLogic               = require("bag.BagLogic")
local Log                    = require("common.Log")
local Util                   = require("common.Util")
local ItemLogic              = require("bag.ItemLogic")
local HeroLogic              = require("hero.HeroLogic")
local HeroExcel              = require("excel.hero")
local RoleDefine             = require("role.RoleDefine")
local ObjHuman               = require("core.ObjHuman")
local HeroGrid               = require("hero.HeroGrid")
local Json                   = require("common.Json")
local FenjieLogic            = require("hecheng.FenjieLogic")
local HeroBook               = require("hero.HeroBook")
local FuwenLogic             = require("fuwen.FuwenLogic")
local HeroEquip              = require("hero.HeroEquip")
local PaomaExcel             = require("excel.paoma")
local HeroDefine             = require("hero.HeroDefine")
local SkinLogic              = require("skin.SkinLogic")
local XingYaoGongMing        = require("xingYaoMen.XingYaoGongMing")
local SkillExcel             = require("excel.skill")
local BufferExcel            = require("excel.buffer")
local ItemDefine             = require("bag.ItemDefine")
local WarOrder               = require("shop.WarOrder")

AD_DRAW_REWARD_TYPE          = 10 --观看广告领取召唤券
QUERY_MERGE_INFO_TYPE        = 11 --获取融合信息
HATCH_SCCUESS_TYPE           = 12 -- 孵化成功
MERGE_HERO_TYPE              = 13 --融合
QUICK_HATCH_TYPE             = 14 --加速
QUERY_MERGE_BEFORE_INFO_TYPE = 15 --获取融合前信息
GET_MERGE_HERO_TYPE          = 16 --获取融合英雄
QUERY_QUICK_HATCH_ZUANSHI    = 17 --查询加速孵化需要的钻石

AD_HATCH_RESET_FREECNT       = 4  --看广告加速孵化次数


--[[
    BuyItem = {
        buyID : number   -- buy配置表id
        region : string  -- 区域 默认cn
        cost : number    -- 价格
        icon : number    -- 图标
        name : string    -- 名称
        desc : string    -- 描述
        zhekou : number  -- 折扣价
        yuanjia : number -- 原价
        ttl : number   -- 有效期
    }
    Item = {
        id : number
        count : number
    }

    Gift = {
        id : number  -- 礼包ID
        startTimeStamp : number  -- 开启时间戳(秒)
        restTime : number  -- 剩余时间(秒)
        buyItem : Buyitem  -- 礼包信息
        content : {item}  -- 礼包内容
    }

    attr = {
        key = number,   --属性类型
        value = number, -- 属性值
    }

    SkinData = {
        id = number  -- 皮肤id
        attrs = [attr]array
    }

    IconFrame = {
        id = number  -- 头像框id
        desc = string
        keepTime = number
        name = string
        camp = number
        attrs = [attr]array
    }

    Skin = {
        id : number  -- 皮肤配置ID
        buyItem ： Buyitem -- 皮肤信息
        skinData ：SkinData  -- 皮肤内容
        Iconframe : IconFrame  -- 头像框内容
    }
]]

------------------------------- CG请求 -------------------------------
--[[
    CG_WARORDER_INFO = {
        orderType = number   -- 战令类型 1 勇士之证 2 恶魔之证 3 工会之证明 4 竞技之证
    }
]]
local CG_WARORDER_INFO = 101  -- 战令信息请求
--[[
    orderType = number   -- 战令类型
]]
local CG_WARORDER_REWARD = 102 -- 战令获取奖励

--[[
    panelId = number    -- panelID
]]
local CG_SKIN_QUREY = 103    -- 皮肤活动详情查询

------------------------------- GC推送 -------------------------------
--[[
    GC_GIFT_GENERATE = {
        gift = Gift
    }
]]
local GC_GIFT_GENERATE = 50  -- 新增礼包推送
--[[
    GC_QUERY_GIFT = {
        list = {Gift}
    }
]]
local GC_QUERY_GIFT = 51    -- 登录推送礼包数据


--[[
    BuyItem = {
        BuyItem = {
        {"buyID",		1,		"int"},			-- 支付ID
        {"region",		1,		"string"},		-- 货币类型 CN/HK等
        {"cost",		1,		"double"},		-- 价格 当前价格
        {"icon",		1,		"int"},			-- 图标
        {"name",		1,		"string"}, 		-- 名称
        {"desc",		1,		"string"},	 	-- 描述
        {"isFirst",		1,		"byte"},		-- 是否首次购买
        {"doubleCnt",	1,		"byte"},		-- 双倍次数
        {"actDoubleCnt",1,		"byte"},		-- 活动双倍次数
        {"useDoubleCnt",1,		"int"},		    -- 当前消耗双倍次数
        {"buyCnt",		1,		"int"},		    -- 当前购买次数
        {"vipExp",		1,		"int"},			-- 附赠vip经验
        {"zhekou",      1,      "int"},         -- 折扣
        {"yuanjia",     1,      "int"},         -- 原价
    }
    }
    normal = {
        idx number                      等级
        process number                  等级对应所需进度
        content [ItemGrid]array         普通战令等级奖励
        upgradeContent [ItemGrid]array  升级战令等级奖励
    }
    GC_WARORDER_INFO = {
        orderType = orderType,         -- 战令类型
        normal = [normal]array,        -- 普通配置
        language = string
        buyItem = BuyItem,             -- 战令商品信息
        -- 自身的进度
        exp = orderData.exp,           -- 当前经验
        unlock = orderData.unlock,     -- 是否解锁升级版 0 表示未解锁 1 表示解锁
        finish = [number]array,        -- 已经完成的普通版等级
        upgradeFinish = [number]array, -- 已经完成的升级版等级
    }
]]
local GC_WARORDER_INFO = 52  -- 战令信息推送
--[[
    GC_WARORDER_CHANGE = {
        orderType = number            -- 战令类型
        exp =   number                -- 战令经验
        unlock = number               -- 是否解锁升级版 0 表示未解锁 1 表示解锁
        finish = [number]array        -- idx数组
        upgradeFinish = [number]array -- idx数组
        isRed = number                -- 是否红点
    }
]]
local GC_WARORDER_CHANGE = 53  -- 战令数据推送

--[[
    GC_SKIN_QUERY = {
        list = [skin]array     -- 皮肤活动详情列表
    }
]]
local GC_SKIN_QUERY = 54 -- 皮肤活动详情推送

-----------------------------------------------------------------------



local push = {
    [GC_GIFT_GENERATE] = true,
    [GC_QUERY_GIFT] = true,
    [GC_WARORDER_INFO] = true,
    [GC_WARORDER_CHANGE] = true,
    [GC_SKIN_QUERY] = true
}

local handler = {
    [CG_WARORDER_INFO] = function(human,param)
        local orderType = assert(tonumber(param),"invalid param")
        local data = WarOrder.warOrderInfo(human,orderType)
        if not data then 
            -- 参数错误，报错
            return
        end
        PushClient(human,GC_WARORDER_INFO,data)
    end,
    [CG_WARORDER_REWARD] = function(human,param)
        local orderType = assert(tonumber(param),"invalid param")
        local data = WarOrder.warOrderReward(human,orderType)
        if not data then 
            -- 参数错误，报错
            return
        end
        PushClient(human,GC_WARORDER_CHANGE,data)
    end,
    [CG_SKIN_QUREY] = function(human,param)
        local panelId = assert(tonumber(param),"invalid param")
        local heroSkinLogic = require"present.HeroSkinLogic"
        -- local data = heroSkinLogic.query(human,panelId)
        -- if not data then 
        --     return
        -- end
        -- PushClient(human,GC_SKIN_QUERY,data)
        heroSkinLogic.query(human,panelId)
    end,
}

--[[function NewProto(human, type, paramJson)
    -- print("newProto:",type,param)
    -- local msgRet = Msg.gc.GC_ROLE_CHANGE_BASEINFO
    -- msgRet.ret = type
    -- msgRet.tip = "test data"
    -- Msg.send(msgRet,human.fd)
    local f = assert(handler[type],"invalid proto type")
    --local param  = Json.Decode(paramJson)
    return f(human,paramJson)
end]]

-- 主动推送给客户端
function PushClient(human,type,data) 
    if not push[type] then 
        Broadcast.sendErr(human, Lang.DRILL_CHOOSE_MY_ERR_INDEX .. " type is " .. type)
        return
    end
    local msgRet = Msg.gc.GC_ROLE_CHANGE_BASEINFO
    msgRet.ret = type
    msgRet.tip = Json.Encode(data)
    Msg.send(msgRet,human.fd)
end
-----------------------------------------------------------
function NewProto(human, type, param)
    -- print("newProto:",type,param)
    -- local msgRet = Msg.gc.GC_ROLE_CHANGE_BASEINFO
    -- msgRet.ret = type
    -- msgRet.tip = "test data"
    -- Msg.send(msgRet,human.fd)
    local f = handler[type]
    if f then 
        return f(human,param)
    end

    local msgRet = Msg.gc.GC_ROLE_CHANGE_BASEINFO

    -- 观看广告获取召唤券
    if type == AD_DRAW_REWARD_TYPE then
        human.db.adRewardCnt = human.db.adRewardCnt or 0

        if human.db.adRewardCnt > 4 then
            Broadcast.sendErr(human, Lang.AD_DRAW_REWARD_LIMIT_ERROR)
            return
        end

        --增加今日观看次数
        human.db.adRewardCnt = (human.db.adRewardCnt or 0) + 1

        Log.write(Log.LOGID_TEST, "adRewardCnt: " .. human.db.adRewardCnt)

        -- 添加高级召唤卷
        BagLogic.addItem(human, 118, 1, "draw_ad_reward")

        msgRet.ret = AD_DRAW_REWARD_TYPE
        msgRet.tip = Lang.AD_DRAW_REWARD_SUCCESS
        Msg.send(msgRet, human.fd)

        return
    end

    -- 查询加速孵化需要的钻石
    if type == QUERY_QUICK_HATCH_ZUANSHI then
        -- 初始化
        initMergeInfo(human)
        local info      = {}
        local nowTime   = os.time
        local hatchTime = human.db.mergeInfo.endTime - nowTime

        info.zuanshi    = doCalcNeedZuanshi(hatchTime)
        info.isTip      = getTodayIsTip(human)

        msgRet.ret      = QUERY_QUICK_HATCH_ZUANSHI
        msgRet.tip      = Json.Encode(info)
        Msg.send(msgRet, human.fd)
        return
    end

    -- 获取融合前的信息
    if type == QUERY_MERGE_BEFORE_INFO_TYPE then
        local tb = Util.split(param, "|")
        if tb[1] and tb[2] then
            -- 初始化
            initMergeInfo(human)

            human.db.heroBag         = human.db.heroBag or {}

            local fatherHeroBagIndex = tonumber(tb[1]) or 0
            local motherHeroBagIndex = tonumber(tb[2]) or 0

            Log.write(Log.LOGID_TEST, "查询融合前的 fatherHeroBagIndex: " .. fatherHeroBagIndex)
            Log.write(Log.LOGID_TEST, "查询融合前的 motherHeroBagIndex: " .. motherHeroBagIndex)

            local fatherHeroGrid = human.db.heroBag[fatherHeroBagIndex]
            if not fatherHeroGrid then
                Log.write(Log.LOGID_TEST, "查询融合前的 fatherHeroGrid: 不存在下标:" .. fatherHeroBagIndex)
                return
            end

            Log.write(Log.LOGID_TEST, "查询融合前的 fatherHeroGrid: " .. Json.Encode(fatherHeroGrid))

            local motherHeroGrid = human.db.heroBag[motherHeroBagIndex]
            if not motherHeroGrid then
                Log.write(Log.LOGID_TEST, "查询融合前的 motherHeroGrid: 不存在下标:" .. motherHeroBagIndex)
                return
            end

            Log.write(Log.LOGID_TEST, "查询融合前的 motherHeroGrid: " .. Json.Encode(motherHeroGrid))

            local mergeInfo  = {}
            local heroSimple = {}
            local xLv        = getxLv(fatherHeroGrid, motherHeroGrid)
            local cnt        = math.floor(xLv / 2) + 1
            local isHatch    = 2
            local mergeItem  = {}
            local itemId     = 178

            for k = 1, 1 do
                mergeItem[k] = mergeItem[k] or {}
                mergeItem[k].getway = mergeItem[k].getway or {}
                mergeItem[k].suipian = mergeItem[k].suipian or {}
                mergeItem[k].equip = mergeItem[k].equip or {}
                mergeItem[k].fuwen = mergeItem[k].fuwen or {}
                Grid.makeItem(mergeItem[k], itemId, cnt)
            end

            local sonHeroID = mergeHero(fatherHeroGrid.id, motherHeroGrid.id)
            local cf        = sonHeroID and HeroExcel.hero[sonHeroID]
            heroSimple.name = cf and cf.name or ""
            if cf.grade >= 6 then
                heroSimple.name = "?????"
            end

            mergeInfo.mergeTime        = 0
            mergeInfo.xLv              = xLv
            mergeInfo.mergeItem        = mergeItem
            mergeInfo.heroData         = heroSimple
            mergeInfo.isHatch          = isHatch
            mergeInfo.adHatchRewardCnt = getResetAdHatchCnt(human)
            mergeInfo.isTip            = getTodayIsTip(human)

            Log.write(Log.LOGID_TEST, "查询融合前的 mergeInfo: " .. Json.Encode(mergeInfo))

            msgRet.ret = QUERY_MERGE_BEFORE_INFO_TYPE
            msgRet.tip = Json.Encode(mergeInfo)
            Msg.send(msgRet, human.fd)
        end
        return
    end

    -- 开始融合
    if type == MERGE_HERO_TYPE then
        local tb = Util.split(param, "|")
        if tb[1] and tb[2] then
            -- 初始化
            initMergeInfo(human)

            human.db.heroBag = human.db.heroBag or {}

            Log.write(Log.LOGID_TEST, "融合 human.db.heroBag: " .. Json.Encode(human.db.heroBag))


            local itemId = 178 --生命雨露
            local fatherHeroBagIndex = tonumber(tb[1]) or 0
            local motherHeroBagIndex = tonumber(tb[2]) or 0

            Log.write(Log.LOGID_TEST, "融合 fatherHeroBagIndex: " .. fatherHeroBagIndex)
            Log.write(Log.LOGID_TEST, "融合  motherHeroBagIndex: " .. motherHeroBagIndex)

            local fatherHeroGrid = human.db.heroBag[fatherHeroBagIndex]
            if not fatherHeroGrid then
                return
            end

            Log.write(Log.LOGID_TEST, "融合 fatherHeroGrid: " .. Json.Encode(fatherHeroGrid))

            local motherHeroGrid = human.db.heroBag[motherHeroBagIndex]
            if not motherHeroGrid then
                return
            end

            Log.write(Log.LOGID_TEST, "融合 motherHeroGrid: " .. Json.Encode(motherHeroGrid))

            local fatherHeroAttr = ObjHuman.getHeroAttrs(human, fatherHeroBagIndex)
            local motherHeroAttr = ObjHuman.getHeroAttrs(human, motherHeroBagIndex)

            local mergeInfo = {}
            local attrs = RoleDefine.PANEL_ATTR_KEY

            if fatherHeroGrid.lv < 100 or motherHeroGrid.lv < 100 then
                Broadcast.sendErr(human, Lang.MERGE_LV_NOT_ENOUGHT_FAIL)
                return
            end

            local sonHeroID = mergeHero(fatherHeroGrid.id, motherHeroGrid.id)
            if sonHeroID <= 0 then
                return
            end

            for key, value in pairs(attrs) do
                local param1 = fatherHeroAttr[key] or 0
                local param2 = motherHeroAttr[key] or 0
                attrs[key] = math.floor(((param1 + param2) / 4))
            end

            Log.write(Log.LOGID_TEST, "融合后的属性: " .. Json.Encode(attrs))

            local xLv = getxLv(fatherHeroGrid, motherHeroGrid)
            local cnt = math.floor(xLv / 2) + 1
            local heroSimple = {}
            local isHatch = 1

            Log.write(Log.LOGID_TEST, "xLv: " .. xLv)
            Log.write(Log.LOGID_TEST, "cnt: " .. cnt)

            local bagCnt = BagLogic.getItemCnt(human, itemId, true)
            if bagCnt < cnt then
                Broadcast.sendErr(human, Lang.ITEM_USE_ERR_NO)
                return
            end

            --使用道具
            ItemLogic.use(human, itemId, cnt)

            local delHeroList = { [1] = fatherHeroBagIndex, [2] = motherHeroBagIndex }
            for key, heroIndex in pairs(delHeroList) do
                local heroID = HeroLogic.getHeroIdByIndex(human, heroIndex)
                --脱装备
                HeroEquip.putOff(human, heroID, heroIndex, ItemDefine.EQUIP_SUBTYPE_WEAPON, false, true)
                HeroEquip.putOff(human, heroID, heroIndex, ItemDefine.EQUIP_SUBTYPE_CLOTH, false, true)
                HeroEquip.putOff(human, heroID, heroIndex, ItemDefine.EQUIP_SUBTYPE_SHOES, false, true)
                HeroEquip.putOff(human, heroID, heroIndex, ItemDefine.EQUIP_SUBTYPE_SHIPIN, false, true)
                -- HeroEquip.putOff(human, heroID, heroIndex, ItemDefine.EQUIP_SUBTYPE_SHENQI, false, true)
                HeroEquip.putOff(human, heroID, heroIndex, ItemDefine.EQUIP_SUBTYPE_RING, false, true)
                HeroEquip.putOff(human, heroID, heroIndex, ItemDefine.EQUIP_SUBTYPE_AMULET, false, true)

                --脱符文
                FuwenLogic.putOff(human, heroID, heroIndex, 1, false, true)
                FuwenLogic.putOff(human, heroID, heroIndex, 2, false, true)

                HeroLogic.delHeroByIndex(human, heroIndex, "hero_merge")
            end

            -- 记录融合英雄
            human.db.mergeInfo.heroInfo.heroID             = sonHeroID
            human.db.mergeInfo.heroInfo.xLv                = xLv
            human.db.mergeInfo.heroInfo.heroAttrs          = attrs
            human.db.mergeInfo.startTime                   = os.time()
            human.db.mergeInfo.endTime                     = os.time() + getHatchTime(xLv)
            human.db.mergeInfo.heroInfo.fatherHeroBagIndex = fatherHeroBagIndex
            human.db.mergeInfo.heroInfo.motherHeroBagIndex = motherHeroBagIndex

            local cf                                       = sonHeroID and HeroExcel.hero[sonHeroID]
            heroSimple.name                                = cf and cf.name or ""
            if cf.grade >= 6 then
                heroSimple.name = "?????"
            end

            if getHatchTime(xLv) == 0 then
                isHatch = 3
            end
            mergeInfo.mergeTime        = getHatchTime(xLv)
            mergeInfo.xLv              = xLv
            mergeInfo.heroData         = heroSimple
            mergeInfo.isHatch          = isHatch
            mergeInfo.adHatchRewardCnt = getResetAdHatchCnt(human)
            mergeInfo.isTip            = getTodayIsTip(human)

            Log.write(Log.LOGID_TEST, "融合 mergeInfo: " .. Json.Encode(mergeInfo))

            Broadcast.sendErr(human, Lang.MERGE_SUCCESS)

            msgRet.ret = MERGE_HERO_TYPE
            msgRet.tip = Json.Encode(mergeInfo)
            Msg.send(msgRet, human.fd)
        end
        return
    end

    -- 获取融合中的信息
    if type == QUERY_MERGE_INFO_TYPE then
        -- 初始化
        initMergeInfo(human)

        human.db.heroBag = human.db.heroBag or {}

        local mergeInfo  = {}
        local mergeTime  = 0
        local heroSimple = {}
        local xLv        = human.db.mergeInfo.heroInfo.xLv or 0
        local sonHeroID  = human.db.mergeInfo.heroInfo.heroID or 0
        local isHatch    = 2

        if sonHeroID == 0 then
            mergeInfo.mergeTime = mergeTime
            mergeInfo.xLv       = xLv
            mergeInfo.heroData  = heroSimple
            mergeInfo.isHatch   = isHatch
            msgRet.ret          = QUERY_MERGE_INFO_TYPE
            msgRet.tip          = Json.Encode(mergeInfo)
            Msg.send(msgRet, human.fd)
            return
        end

        local mergeTime = human.db.mergeInfo.endTime - os.time()

        if mergeTime <= 0 then
            -- 孵化成功
            mergeTime = 0
            isHatch = 3
        else
            isHatch = 1
        end

        local cf        = sonHeroID and HeroExcel.hero[sonHeroID]
        heroSimple.name = cf and cf.name or ""
        if cf.grade >= 6 then
            heroSimple.name = "?????"
        end

        mergeInfo.mergeTime        = mergeTime
        mergeInfo.xLv              = xLv
        mergeInfo.heroData         = heroSimple
        mergeInfo.isHatch          = isHatch
        mergeInfo.adHatchRewardCnt = getResetAdHatchCnt(human)
        mergeInfo.isTip            = getTodayIsTip(human)

        msgRet.ret                 = QUERY_MERGE_INFO_TYPE
        msgRet.tip                 = Json.Encode(mergeInfo)
        Log.write(Log.LOGID_TEST, "融合中 msgRet: " .. Json.Encode(msgRet))
        Msg.send(msgRet, human.fd)
        return
    end

    -- 获取融合英雄
    if type == GET_MERGE_HERO_TYPE then
        local nowTime     = os.time()
        local mergeInfo   = {}
        local heroSimple  = {}
        local xLv         = human.db.mergeInfo.heroInfo.xLv or 0
        local sonHeroID   = human.db.mergeInfo.heroInfo.heroID or 0
        local hatchTime   = human.db.mergeInfo.endTime - nowTime
        local isHatch     = 2
        local heroIndex   = 0
        local msgTyep     = GET_MERGE_HERO_TYPE
        local cf          = sonHeroID and HeroExcel.hero[sonHeroID]
        local heroNiceNet = {}

        if hatchTime <= 0 then
            -- 孵化成功
            hatchTime = 0
            heroIndex = hatchHero(human)
            local heroGrid = human.db.heroBag[heroIndex]
            if not heroGrid then return end
            heroSimple.general = heroSimple.general or {}
            HeroGrid.makeHeroSimple(heroSimple, heroGrid, heroIndex, human)

            local heroID = heroGrid.id or 0
            local isNew = not HeroBook.isGet(human, cf.id, cf.star)
            makeHeroNice(heroNiceNet, heroID, nil, isNew, heroIndex)
        else
            heroSimple.name = cf and cf.name or ""
            if cf.grade >= 6 then
                heroSimple.name = "?????"
            end
            isHatch = 1
            msgTyep = QUERY_MERGE_INFO_TYPE
        end

        mergeInfo.mergeTime        = hatchTime
        mergeInfo.xLv              = xLv
        mergeInfo.heroData         = heroSimple
        mergeInfo.isHatch          = isHatch
        mergeInfo.adHatchRewardCnt = getResetAdHatchCnt(human)
        mergeInfo.isTip            = getTodayIsTip(human)
        mergeInfo.heroNiceNet      = heroNiceNet

        msgRet.ret                 = msgTyep
        msgRet.tip                 = Json.Encode(mergeInfo)
        Log.write(Log.LOGID_TEST, "获取英雄 ret: " .. Json.Encode(msgRet))
        Msg.send(msgRet, human.fd)
        return
    end

    -- 加速孵化
    if type == QUICK_HATCH_TYPE then
        local tb = Util.split(param, "|")
        local quickType = tonumber(tb[1]) or 0
        local cnt = tonumber(tb[2]) or 0
        local isHatch = 1

        if tb[1] and tb[2] then
            -- 初始化
            initMergeInfo(human)

            -- 剩余时间
            local nowTime = os.time()
            local hatchTime = human.db.mergeInfo.endTime - nowTime

            if hatchTime <= 0
            then
                Broadcast.sendErr(human, Lang.QUICK_HATCH_TIME_OUT)
                return
            end

            local itemSpeedTime = 0
            if quickType == 1 then
                local speedTime = (60 * 5 * cnt)           -- 正常数量加速券的加速时间
                local lastSpeedTime = (60 * 5 * (cnt - 1)) --少一张加速券的加速时间
                local itemCnt = 0

                if hatchTime > lastSpeedTime and hatchTime <= speedTime then
                    itemCnt = cnt
                elseif hatchTime > 0 and hatchTime <= lastSpeedTime then
                    itemCnt = cnt - 1
                elseif hatchTime >= speedTime then
                    itemCnt = cnt
                else
                    itemCnt = 0
                end

                itemSpeedTime = (60 * 5 * itemCnt)

                local bagCnt = BagLogic.getItemCnt(human, 179, true)
                if bagCnt < itemCnt then
                    Broadcast.sendErr(human, Lang.ITEM_USE_ERR_NO)
                    return
                end

                --使用道具
                ItemLogic.use(human, 179, cnt)
                human.db.mergeInfo.endTime = human.db.mergeInfo.endTime - itemSpeedTime
            elseif quickType == 2 then
                local zuanshiCnt = doCalcNeedZuanshi(hatchTime)

                -- 判断消耗
                if not ObjHuman.checkRMB(human, zuanshiCnt) then
                    return
                end

                itemSpeedTime = (30 * zuanshiCnt)

                -- 扣钻石
                ObjHuman.decZuanshi(human, -zuanshiCnt, "hero_merge")

                if tb[3] then
                    human.db.isTip = human.db.isTip or 1
                    human.db.isTip = tonumber(tb[3])
                end

                human.db.mergeInfo.endTime = human.db.mergeInfo.endTime - itemSpeedTime
            elseif quickType == 3 then
                human.db.adHatchRewardCnt = human.db.adHatchRewardCnt or 0

                if human.db.adHatchRewardCnt > 4 then
                    Broadcast.sendErr(human, Lang.AD_HATCH_REWARD_LIMIT_ERROR)
                    return
                end

                --加速30分钟
                itemSpeedTime              = 30 * 60

                --增加今日观看次数
                human.db.adHatchRewardCnt  = (human.db.adHatchRewardCnt or 0) + 1

                human.db.mergeInfo.endTime = human.db.mergeInfo.endTime - itemSpeedTime
            end

            local hatchTime = human.db.mergeInfo.endTime - nowTime

            -- 孵化成功
            if hatchTime < 0 then
                hatchTime = 0
                isHatch = 3
            end

            local mergeInfo  = {}
            local heroSimple = {}
            local sonHeroID  = human.db.mergeInfo.heroInfo.heroID or 0
            local cf         = sonHeroID and HeroExcel.hero[sonHeroID]
            heroSimple.name  = cf and cf.name or ""
            if cf.grade >= 6 then
                heroSimple.name = "?????"
            end

            mergeInfo.mergeTime        = hatchTime
            mergeInfo.heroData         = heroSimple
            mergeInfo.xLv              = human.db.mergeInfo.heroInfo.xLv
            mergeInfo.isHatch          = isHatch
            mergeInfo.adHatchRewardCnt = getResetAdHatchCnt(human)
            mergeInfo.isTip            = getTodayIsTip(human)

            msgRet.ret                 = QUICK_HATCH_TYPE
            msgRet.tip                 = Json.Encode(mergeInfo)

            Log.write(Log.LOGID_TEST, "加速孵化 ret: " .. Json.Encode(msgRet))

            Msg.send(msgRet, human.fd)
            return
        end
        return
    end
end

-- 孵化英雄
function hatchHero(human)
    Log.write(Log.LOGID_TEST, "孵化英雄id " .. human.db.mergeInfo.heroInfo.heroID)

    --添加英雄
    local heroIndex, fjlist = HeroLogic.addHero(human, human.db.mergeInfo.heroInfo.heroID, nil, 1,
        "hero_merge")

    Log.write(Log.LOGID_TEST, "孵化英雄成功 下标" .. heroIndex)

    local attrs = RoleDefine.PANEL_ATTR_KEY
    for key, value in pairs(attrs) do
        attrs[key] = 1
    end

    human.db.mergeInfo.startTime                   = 0
    human.db.mergeInfo.endTime                     = 0
    human.db.mergeInfo.heroInfo                    = {}
    human.db.mergeInfo.heroInfo.heroID             = 0
    human.db.mergeInfo.heroInfo.xLv                = 0
    human.db.mergeInfo.heroInfo.fatherHeroBagIndex = 0
    human.db.mergeInfo.heroInfo.motherHeroBagIndex = 0
    human.db.mergeInfo.heroInfo.heroAttrs          = attrs

    Log.write(Log.LOGID_TEST, "孵化重置 mergeInfo: " .. Json.Encode(human.db.mergeInfo))

    return heroIndex
end

-- 初始化融合信息
function initMergeInfo(human)
    human.db.mergeInfo                             = human.db.mergeInfo or {}
    human.db.mergeInfo.startTime                   = human.db.mergeInfo.startTime or 0 --融合时间 时间戳
    human.db.mergeInfo.endTime                     = human.db.mergeInfo.endTime or 0   --孵化时间 单位s
    human.db.mergeInfo.heroInfo                    = human.db.mergeInfo.heroInfo or {}
    human.db.mergeInfo.heroInfo.heroID             = human.db.mergeInfo.heroInfo.heroID or 0
    human.db.mergeInfo.heroInfo.xLv                = human.db.mergeInfo.heroInfo.xLv or 0
    human.db.mergeInfo.heroInfo.fatherHeroBagIndex = human.db.mergeInfo.heroInfo.fatherHeroBagIndex or 0
    human.db.mergeInfo.heroInfo.motherHeroBagIndex = human.db.mergeInfo.heroInfo.motherHeroBagIndex or 0
    human.db.mergeInfo.heroInfo.heroAttrs          = human.db.mergeInfo.heroInfo.heroAttrs or RoleDefine.PANEL_ATTR_KEY
end

-- 获取孵化时间 单位s
function getHatchTime(xLv)
    local time = (xLv * 5) + (xLv - 1) * (xLv - 1) - 5

    if time < 0 then
        return 0
    end

    return time * 60
end

-- 计算需要钻石数量
function doCalcNeedZuanshi(hatchTime)
    local cnt = 0
    if hatchTime > 0 then
        cnt = math.ceil(hatchTime / 30)
    end
    return cnt
end

-- 获取xlv
function getxLv(fatherHeroGrid, motherHeroGrid)
    local fatherHeroXLv = fatherHeroGrid.xLv or 0
    local motherHeroXLv = motherHeroGrid.xLv or 0
    local params1 = math.max(fatherHeroXLv, motherHeroXLv)
    local params2 = math.floor((fatherHeroGrid.lv + motherHeroGrid.lv) / 200) + 1
    local xLv = params1 + params2

    if xLv > 50 then
        return 50
    end

    return xLv
end

-- 融合获取英雄ID
function mergeHero(fatherHeroID, motherHeroID)
    local fatherHeroConfig = HeroExcel.hero[fatherHeroID]
    local motherHeroConfig = HeroExcel.hero[motherHeroID]

    if not fatherHeroConfig or not motherHeroConfig then
        return 0
    end

    --规则3 heroID + heroID
    for _, config in pairs(MergeRule[3].items) do
        if fatherHeroID == config[1] and motherHeroID == config[2] then
            return config[3]
        end
    end

    --规则2 种族 + heroID
    for _, config in pairs(MergeRule[2].items) do
        if fatherHeroConfig.camp == config[1] and motherHeroID == config[2] then
            return config[3]
        end
    end

    --规则1 种族 + 种族
    for _, config in pairs(MergeRule[1].items) do
        if fatherHeroConfig.camp == config[1] and motherHeroConfig.camp == config[2] then
            return config[3]
        end
    end
    return 0
end

-- 获取剩余融化孵化加速广告观看次数
function getResetAdHatchCnt(human)
    local adHatchRewardCnt = human.db.adHatchRewardCnt or 0
    return math.max(AD_HATCH_RESET_FREECNT - adHatchRewardCnt, 0)
end

-- 获取是否今日不再提示
function getTodayIsTip(human)
    local isTip = human.db.isTip or 1
    return tonumber(isTip)
end

-- 封装客户端需要的json格式
function makeHeroNice(net, id, cnt, isNew, index)
    net.heroSimple = net.heroSimple or {}
    net.itemData = net.itemData or {}
    net.heroStatic = net.heroStatic or {}
    net.attrs = net.attrs or {}
    net.attrsMax = net.attrsMax or {}

    if cnt then
        net.itemData[1] = net.itemData[1] or {}
        Grid.makeItem(net.itemData[1], id, cnt)
    end
    local heroConfig = HeroExcel.hero[id]
    local specialConfig = HeroExcel.specialHero[id]
    if heroConfig then
        net.heroSimple[1] = net.heroSimple[1] or {}
        net.heroStatic[1] = net.heroStatic[1] or {}
        makeHeroSimpleByID(net.heroSimple[1], id, index)
        makeHeroStatic(net.heroStatic[1], id)
    end

    net.body = specialConfig and (heroConfig and heroConfig.body or 0) or 0
    net.isNew = isNew and 1 or 0
    net.weightLv = heroConfig and heroConfig.grade or 0

    net.bubble = ""
    local attrsNum = 0
    local attrsMaxNum = 0
    if heroConfig then
        local bubble = PaomaExcel.bubble[heroConfig.id]
        net.bubble = bubble and bubble.drawCard or ""
        local heroGrid = HeroGrid.getCacheHeroGridTujian(id)
        for key = RoleDefine.ATK, RoleDefine.SPEED do
            local value = heroGrid.attrs[key]
            attrsNum = attrsNum + 1
            net.attrs[attrsNum] = net.attrs[attrsNum] or {}
            net.attrs[attrsNum].key = key
            net.attrs[attrsNum].value = value

            attrsMaxNum = attrsMaxNum + 1
            net.attrsMax[attrsMaxNum] = net.attrs[attrsMaxNum] or {}
            net.attrsMax[attrsMaxNum].key = key
            net.attrsMax[attrsMaxNum].value = HeroDefine.getTujianMaxValue(key)
        end
    end
end

-- 根据英雄id封装英雄信息heroSimple 额外处理
function makeHeroSimpleByID(net, id, index, others, human, tujian)
    local star = others and others.star or nil
    local grid = HeroGrid.getCacheHeroGrid(id, star, others)
    makeHeroSimple(net, grid, index, human, others, tujian)
end

-- 填充英雄详细信息：静态 额外格式
function makeHeroStatic(net, id, tuJian)
    net.skillList = net.skillList or {}
    net.beSkill = net.beSkill or {}

    local cf = id and HeroExcel.hero[id]
    if not cf then
        net.id = 0
        net.name = ""
        net.body = 0
        net.job = 0
        net.weightLv = 0
        net.normalAtkID = 0
        net.skillList[0] = 0
        net.beSkill[0] = 0
        net.skin = 0
        return
    end

    local star = cf.star
    if tuJian and tuJian == 1 then
        local tuJianConfig = HeroExcel.tujian[id]
        if tuJianConfig then
            local maxStarIndex = #tuJianConfig.star
            star = tuJianConfig.star[maxStarIndex]
        end
    end

    net.id = id
    net.name = cf.name
    net.body = cf.body
    net.job = cf.job
    net.weightLv = cf.grade

    local attrConfig = HeroDefine.getAttrConfig(id, star)
    net.normalAtkID = attrConfig.normalAtkID

    for i = 1, #attrConfig.skillList do
        net.skillList[i] = net.skillList[i] or {}
        makeSkillNet(net.skillList[i], attrConfig.skillList[i])
    end

    for i = 1, #attrConfig.beSkillList do
        net.beSkill[i] = net.beSkill[i] or {}
        makeSkillNet(net.beSkill[i], attrConfig.beSkillList[i])
    end
    net.skin = #cf.skin > 0 and 1 or 0
end

-- 封装英雄信息 额外处理
function makeHeroSimple(net, grid, index, human, others, tuJian)
    local id = grid and (grid.id or grid.heroID)
    local cf = id and HeroExcel.hero[id]
    local star = grid and grid.star or (cf and cf.star or 1)
    local upStarConfig = HeroDefine.getNextAttrConfig(id, star)
    local jobConfig = cf and cf.job and HeroExcel.job[cf.job]
    local isGongMing = XingYaoGongMing.isGongMing(human, index)

    net.id = id or 0
    net.index = index or 0
    net.uuid = grid and grid.uuid or ""
    net.gl = cf and cf.gl or 0
    net.camp = cf and cf.camp or 0
    net.job = cf and cf.job or 0
    net.star = others and others.star or star --cf and cf.star or 0 星级调整 dxzeng
    net.icon = grid and grid.head or (cf and cf.head or 0)
    net.body = grid and grid.body or (cf and cf.body or 0)
    if grid and human and index then -- todo 皮肤这个以后可能还是需要继续整理
        local skinConf = SkinLogic.getHeroSkin(human, index)
        if skinConf then
            net.icon = skinConf.head
            net.body = skinConf.body
        end
    end
    net.up = upStarConfig == nil and 0 or 1 --是否能够升星

    net.lv = others and others.lv or (grid and grid.lv or 1)
    net.xLv = others and others.xLv or (grid and grid.xLv or 0)
    net.zhandouli = grid and grid.zhandouli or 0
    net.quality = grid and grid.quality or 0
    net.isLock = (grid and grid.isLock) and 1 or 0
    net.hp = others and others.hp or 0
    net.hpMax = others and others.hpMax or 0
    net.cnt = others and others.cnt or 1
    net.isget = HeroBook.isGetHero(human, id) or 0
    net.weightLv = cf and cf.grade or 0
    net.name = cf and cf.name or ""
    net.grade = cf and cf.grade or 0
    net.jobDesc = jobConfig and jobConfig.desc or ""
    net.label = cf and cf.label or ""
    net.order = cf and cf.order or 0
    net.isGongMing = isGongMing or 0
    net.general = net.general or {}

    --是否发送图鉴信息
    if tuJian then
        local tj = HeroExcel.tujian[id]
        if tj ~= nil then
            net.general[1] = net.general[1] or {}
            net.general[1].cm = tj.cm or 0
            net.general[1].kg = tj.kg or 0
            net.general[1].age = tj.age or 0
            net.general[1].cup = tj.cup or ""
            net.general[1].character = tj.character or ""
            net.general[1].interest = tj.interest or ""
            net.general[1].desc = tj.desc or ""
        end
    end
end

-- 获取技能信息
function makeSkillNet(net, id)
    local skillConfig = SkillExcel.skill[id]
    if not skillConfig then return end
    net.id   = id
    net.icon = skillConfig.icon
    net.name = skillConfig.name
    net.type = skillConfig.type
    net.desc = skillConfig.desc
    net.need = skillConfig.need or 0
    net.lv   = skillConfig.skillLv or 0
    -- todo

    net.cd   = net.cd or {}
    net.buff = net.buff or {}

    if #skillConfig.cd ~= 0 then
        net.cd[1] = net.cd[1] or {}
        net.cd[2] = net.cd[2] or {}
        net.cd[1] = skillConfig.cd[1]
        net.cd[2] = skillConfig.cd[2]
    end

    local len = #skillConfig.buffers
    for i = 1, len do
        local buffId = skillConfig.buffers[i][1]
        local buffConfig = BufferExcel.buffer[buffId]
        net.buff[i] = net.buff[i] or {}
        net.buff[i].id = buffId
        net.buff[i].name = buffConfig.name
        net.buff[i].desc = buffConfig.desc
    end
    net.lvUpDesc = skillConfig.lvUpDesc
    -- todo
end
