--夺宝奇兵活动
--玩法: 从四条配置中各随机一个奖励, 然后把这4个奖励按照一定数量组成一个奖池给玩家抽奖, 奖励抽到后就减少
--注意事项：活动开启期间, 不能改4条配置中prizeData里各个奖励的顺序,因为服务器存储的是随机到的奖励的index
--db
--[=[
        human.db.absAct[id] = {
            awardData = {
                [type] = {idx = 1, cnt = 1}, --key为奖池类型，idx为配置中随机到的奖励index，cnt表示当前奖励数量
            },

            isFreeReset = nil,    --免费重置标识, 1-免费

            posData = {         --已经抽奖的位置, pos为位置
                [pos] = {poolType = poolType, idx = idx}
            },
            isStart = nil,         --是否开始游戏
            isTips = nil,          --提示, 为0时不提示，其他情况都提示
            dailyFreeState = nil,  --每日单抽免费标识，为0时不免费，其他情况免费
        }
    }
]=]--

local Msg = require("core.Msg")
local Grid = require("bag.Grid")
local Util = require("common.Util")
local BagLogic = require("bag.BagLogic")
local ItemDefine = require("bag.ItemDefine")
local AbsActLogic = require("absAct.AbsActLogic")
local Broadcast = require("broadcast.Broadcast")
local Lang = require("common.Lang")
local duobaoCfg = require("excel.absAct").DuoBaoQiBing
local YunYingLogic = require("yunying.YunYingLogic")
local AbsActExcel = require("excel.absAct")
local TriggerDefine = require("trigger.TriggerDefine")
local TriggerLogic = require("trigger.TriggerLogic")
local CycleActivityLogic = require("yunying.CycleActivity")


local LOGTYPE = "duobaoqibing"      --日志标识
local POOL1CNT = 30                 --从奖池1中抽取的奖励数量
local POOL2CNT = 12                 --从奖池2中抽取的奖励数量
local POOL3CNT = 2                  --从奖池3中抽取的奖励数量
local POOL4CNT = 1                  --从奖池4中抽取的奖励数量
local LOTTERYCOSTCNT = 400          --单抽消耗数量
local RESETCOSTCNT = 1000           --重置消耗数量
local COSTITEMID = ItemDefine.ITEM_ZUANSHI_ID  --单抽/重置消耗的道具id


local function getAwardNumByType(poolType)
    local num = 0
    if not poolType then
        return num
    end
    if poolType == 1 then
        num = POOL1CNT
    elseif poolType == 2 then
        num = POOL2CNT
    elseif poolType == 3 then
        num = POOL3CNT
    elseif poolType == 4 then
        num = POOL4CNT
    end
    return num
end



--从配置中随机一个奖励，并返回奖励的index
local function getAwardIdx(awardCfg)
    local totalWeight = 0
    for _, v in ipairs(awardCfg.prizeData) do
        totalWeight = totalWeight + v[3]
    end
    local randWeight = math.random(0, totalWeight)

    local weight, randIdx = 0, 0
    for idx, data in ipairs(awardCfg.prizeData) do
        weight = weight + data[3]
        if randWeight <= weight then
            randIdx = idx
            break
        end
    end
    return randIdx
end

--生成奖励数据
local function generateAwardData(human, id)
    human.db.absAct[id] = human.db.absAct[id] or {}
    local actData = human.db.absAct[id]
    actData.awardData = actData.awardData or {}
    local awardData = actData.awardData

    for type, cfg in ipairs(duobaoCfg) do
        local awardIdx = getAwardIdx(cfg)
        awardData[type] = {
            idx = awardIdx,
            cnt = getAwardNumByType(type),
            --type = type
        }
    end
end

--填充协议数据
local function populateMsg(actData, msgTb)
    local awardData = actData.awardData
    local posData = actData.posData

    local awardNum, len = 0, 0
    for i=1, 4 do
        awardNum = getAwardNumByType(i)
        local awardIdx = awardData[i].idx
        local awardInfo = duobaoCfg[i].prizeData[awardIdx]

        for j=1, awardNum do
            len = len + 1
            msgTb[len].isGet = 0
            msgTb[len].poolType = i
            msgTb[len].index = len
            
            Grid.makeItem(msgTb[len].item, awardInfo[1], awardInfo[2])

            if posData and posData[len] then
                msgTb[len].isGet = 1
                local poolType = posData[len].poolType

                --奖池类型不一样, 说明该位置抽到的是别的奖池的道具, 需要修改道具信息
                if poolType ~= i then
                    msgTb[len].poolType = poolType
                    awardIdx = posData[len].idx
                    local realAwardInfo = duobaoCfg[poolType].prizeData[awardIdx]
                    Grid.makeItem(msgTb[len].item, realAwardInfo[1], realAwardInfo[2])
                end
            end
        end
    end
    msgTb[0] = len
end

--生成抽奖数据
local function generateLotteryData(actData)
    local awardVec = {}
    local len, totalWeight = 0,0
    local awardData = actData.awardData
    for type, data in ipairs(awardData) do
        if data.cnt > 0 then
            local awardInfo = duobaoCfg[type].prizeData[data.idx]
            local itemId = awardInfo[1]
            local itemNum = awardInfo[2]
            local weight = awardInfo[3]
            for i=1, data.cnt do
                len = len + 1
                totalWeight = totalWeight + weight
                awardVec[len] = {itemId, itemNum, weight, type, data.idx}
            end
        end
    end
    return awardVec, totalWeight
end

--刷天处理
function updateDaily(human, id)
    -- local state = AbsActLogic.isStarted(human, id)
    local state = CycleActivityLogic.isStarted(human, id)
    if not state then
        return
    end

    local actData = human.db.absAct[id]
    if not actData then
        return
    end
    actData.isTips = 1

    actData.dailyFreeState = 1
end


function isRed(human, YYInfo, absActConfig)
    local id = absActConfig.funcID
    -- local state = AbsActLogic.isStarted(human, id)
    local state = CycleActivityLogic.isStarted(human, id)
    if not state then
        return false
    end

    local actData = human.db.absAct[id]
    if not actData then
        return false
    end

    if actData.dailyFreeState and actData.dailyFreeState == 0 then
        return false
    end
    return true
end


--查询
function Query(human, id)
    -- local state = AbsActLogic.isStarted(human, id)
    -- print("[DuoBaoQiBing_Query ] id = "..id.." name = "..human.db.name)
    local state = CycleActivityLogic.isStarted(human, id)
    if not state then
        return Broadcast.sendErr(human, Lang.YUNYING_ERR_TIME)
    end

    local actData = human.db.absAct[id]
    if not actData then
        return Broadcast.sendErr(human, Lang.YUNYING_ERR_TIME)
    end

    local msgRet = Msg.gc.GC_DBQB_QUERY
    msgRet.isFreeReset = actData.isFreeReset or 0
    msgRet.isStart = actData.isStart or 0
    msgRet.isTips = 1
    if actData.isTips and actData.isTips == 0 then
        msgRet.isTips = 0
    end

    msgRet.isFree = 0
    if not actData.dailyFreeState or actData.dailyFreeState == 1 then
        msgRet.isFree = 1
    end

    if not actData or not actData.awardData then
        generateAwardData(human, id)
    end

    Grid.makeItem(msgRet.lotteryCost, COSTITEMID, LOTTERYCOSTCNT)
    Grid.makeItem(msgRet.resetCost, COSTITEMID, RESETCOSTCNT)
    populateMsg(actData, msgRet.awardPoolData)

    Msg.send(msgRet, human.fd)
end

--奖池重置
function ResetAwardPool(human, id, resetType)
    if not id or not resetType then
        return Broadcast.sendErr(human, Lang.COMMON_ARGUMENT_ERROR)
    end

    -- local state = AbsActLogic.isStarted(human, id)
    local state = CycleActivityLogic.isStarted(human, id)
    if not state then
        return Broadcast.sendErr(human, Lang.YUNYING_ERR_TIME)
    end

    local actData = human.db.absAct[id]
    if not actData then
        return Broadcast.sendErr(human, Lang.YUNYING_ERR_TIME)
    end

    if resetType == 1 then
        if not actData.isFreeReset or actData.isFreeReset <= 0 then
            return Broadcast.sendErr(human, Lang.YUNYING_ERR_TIME)
        end
        actData.isFreeReset = 0
    elseif resetType == 2 then
        if BagLogic.getItemCnt(human, COSTITEMID) < RESETCOSTCNT then
            return Broadcast.sendErr(human, Lang.COMMON_ITEM_NOT_ENOUGH)
        end
        BagLogic.delItem(human, COSTITEMID, RESETCOSTCNT, LOGTYPE)
    else
        return Broadcast.sendErr(human, Lang.COMMON_ARGUMENT_ERROR)
    end

    --重置数据
    generateAwardData(human, id)
    actData.posData = nil
    actData.isStart = 0

    --通知客户端
    local msgRet = Msg.gc.GC_DBQB_RESET
    msgRet.isFreeReset = actData.isFreeReset or 0
    msgRet.isStart = actData.isStart or 0

    populateMsg(actData, msgRet.awardPoolData)
    Msg.send(msgRet, human.fd)
end

--抽奖
function Lottery(human, id, pos)
    if not id or not pos then
        return Broadcast.sendErr(human, Lang.COMMON_ARGUMENT_ERROR)
    end

    if 1 > pos or pos > (POOL1CNT + POOL2CNT + POOL3CNT + POOL4CNT) then
        return Broadcast.sendErr(human, Lang.COMMON_ARGUMENT_ERROR)
    end

    -- local state = AbsActLogic.isStarted(human, id)
    local state = CycleActivityLogic.isStarted(human, id)
    if not state then
        return Broadcast.sendErr(human, Lang.YUNYING_ERR_TIME)
    end

    local actData = human.db.absAct[id]
    if not actData then
        return Broadcast.sendErr(human, Lang.YUNYING_ERR_TIME)
    end

    local posData = actData.posData
    if posData and posData[pos] then
        return Broadcast.sendErr(human, Lang.COMMON_ARGUMENT_ERROR)
    end

    local itemCnt = LOTTERYCOSTCNT
    if not actData.dailyFreeState or actData.dailyFreeState == 1 then
        itemCnt = 0
        actData.dailyFreeState = 0
    end

    --扣消耗
    if itemCnt > 0 then
        if BagLogic.getItemCnt(human, COSTITEMID) < itemCnt then
            return Broadcast.sendErr(human, Lang.COMMON_ITEM_NOT_ENOUGH)
        end
        BagLogic.delItem(human, COSTITEMID, itemCnt, LOGTYPE)
    end

    --抽奖
    local awardVec, totalWeight = generateLotteryData(actData)
    if #awardVec <= 0 then
        return Broadcast.sendErr(human, Lang.COMMON_ARGUMENT_ERROR)
    end

    local itemId, itemCnt, weight, poolType, awardIdx = 0,0,0,0,0
    local randWeight = math.random(0, totalWeight)
    for _,v in ipairs(awardVec) do
        weight = weight + v[3]
        if randWeight <= weight then
            itemId = v[1]
            itemCnt = v[2]
            poolType = v[4]
            awardIdx = v[5]
            break
        end
    end
    --BagLogic.addItem(human, itemId, itemCnt, LOGTYPE)
    BagLogic.addItemList(human, { {itemId, itemCnt}}, LOGTYPE)

    --更新db
    actData.posData = actData.posData or {}
    actData.posData[pos] = { poolType = poolType, idx = awardIdx }
    actData.awardData[poolType].cnt = actData.awardData[poolType].cnt - 1
    if poolType == 4 then   --抽到特殊奖励, 获得免费刷新奖池一次
        actData.isFreeReset = 1
        TriggerLogic.PublishEvent(TriggerDefine.DRAGON_PEARL, human.db._id, 1)
    end

    --通知客户端
    local msgRet = Msg.gc.GC_DBQB_LOTTERY
    msgRet.isFreeReset = actData.isFreeReset or 0
    msgRet.isFree = 0 --有免费次数会优先使用免费次数, 所以抽奖后，免费次数就没有了

    --populateMsg(actData, msgRet.awardPoolData)
    local posInfo = msgRet.posInfo
    posInfo.isGet = 1
    posInfo.poolType = poolType
    posInfo.index = pos
    Grid.makeItem(posInfo.item, itemId, itemCnt)
    Msg.send(msgRet, human.fd)

    --红点刷新
    if itemCnt == 0 then
        local config = AbsActExcel.absActivity[id]
        YunYingLogic.sendGroupUpdate(YYInfo[id], human, config.panelID)
    end
end

--点击开始游戏
function StartGame(human, id)
    if not id then
        return Broadcast.sendErr(human, Lang.COMMON_ARGUMENT_ERROR)
    end

    -- local state = AbsActLogic.isStarted(human, id)
    local state = CycleActivityLogic.isStarted(human, id)
    if not state then
        return Broadcast.sendErr(human, Lang.YUNYING_ERR_TIME)
    end

    local actData = human.db.absAct[id]
    if not actData then
        return Broadcast.sendErr(human, Lang.YUNYING_ERR_TIME)
    end

    --修改状态
    actData.isStart = 1

    --通知客户端
    local msgRet = Msg.gc.GC_DBQB_START_GAME
    msgRet.isStart = actData.isStart or 0
    Msg.send(msgRet, human.fd)
end

--关闭提示
function CloseTips(human, id)
    if not id then
        return Broadcast.sendErr(human, Lang.COMMON_ARGUMENT_ERROR)
    end

    -- local state = AbsActLogic.isStarted(human, id)
    local state = CycleActivityLogic.isStarted(human, id)
    if not state then
        return Broadcast.sendErr(human, Lang.YUNYING_ERR_TIME)
    end

    local actData = human.db.absAct[id]
    if not actData then
        return Broadcast.sendErr(human, Lang.YUNYING_ERR_TIME)
    end

    --修改状态
    actData.isTips = 0

    --通知客户端
    local msgRet = Msg.gc.GC_DBQB_TIPS
    msgRet.isTips = actData.isTips or 0
    Msg.send(msgRet, human.fd)
end