local Msg = require("core.Msg")
local Util = require("common.Util")
local ObjHuman = require("core.ObjHuman")
local Lang  = require("common.Lang")
local Broadcast = require("broadcast.Broadcast")
local Grid = require("bag.Grid")
local BagLogic = require("bag.BagLogic")
local AbsActLogic = require("absAct.AbsActLogic")
local AbsActDefine = require("absAct.AbsActDefine")
local MailManager = require("mail.MailManager")
local MailExcel = require("excel.mail")
local AbsActExcel = require("excel.absAct")
local ItemExcel = require("excel.item").item
local ItemDefine = require("bag.ItemDefine")
local YunYingLogic = require("yunying.YunYingLogic")
local PanelDefine = require("broadcast.PanelDefine")
local CycleActivityLogic = require("yunying.CycleActivity")

--[[
    absAct.xlxs-surpriseChest
    新英雄来袭-惊喜宝箱
        1.每天凌晨0点解锁一个宝箱，每个宝箱都会有单独对应的任务
        2.完成任务可以领取奖励;未完成任务,跨天后可以花元宝补领奖励
    DB:
        human.db.absAct[id] = {
            curDay = xxx,     -- 当前是哪一天
            days = {
                [day] = {
                    state = xxx,  -- 天数 = 状态(0未解锁,1已解锁(不能领),2可领,3已领取,4可补领,5已补领)
                    cnt   = xxx,
                },
                ...
            }
        }
   local:
        getActID()              -- 获取活动id
        getSChestDBAndConfig()  -- 获取DB和配置
        getInitDB()             -- 初始DB数据
        getCurSChestInfo()      -- 取当天配置信息
        updateSend()            -- 更新活动状态
        getReward()             -- 获得奖励
        everyReqTriggerTask()   -- 每次活动请求时触发任务
        wrapSurpriseChestNet()  -- 包装惊喜宝箱协议数据
    public:
        getAndSendMsg()         -- 发送活动数据
        isRed()                 -- 红点提醒
        isActive()              -- 激活状态
        isOpen()                -- 活动开启
        getLeftTime()           -- 得到活动剩余时间
        get()                   -- 领取任务完成奖励
        buGet()                 -- 领取补领奖励
        updateDaily()           -- 每日更新
        finishTaskCB()          -- 完成任务回调
--]]

STATE_0 = 0  -- 未解锁
STATE_1 = 1  -- 已解锁(不能领)
STATE_2 = 2  -- 可领
STATE_3 = 3  -- 已领取
STATE_4 = 4  -- 可补领
STATE_5 = 5  -- 已补领

TASK_1 = 1   -- 活跃度达到X点活跃值
TASK_2 = 2   -- 冠军联赛挑战X次
TASK_3 = 3   -- 在线时长达到X分钟
TASK_4 = 4   -- 接取任意悬赏任务X次
TASK_5 = 5   -- 占卜消耗X个占卜币
TASK_6 = 6   -- 挑战X次公会boss
TASK_7 = 7   -- 参与女巫森林X次

local S_CHEST_CONFIG = {}  -- actID = {sChestInfo,...}

local function getSChestDBAndConfig(human, id)
    local actDB = human.db.absAct[id]                   
    if not actDB then return end                        -- 判断活动是否存在

    local absActConfig = AbsActExcel.absActivity[id]    
    if not absActConfig then return end                 -- 判断活动配置是否存在

    local actId = absActConfig.actId                    -- 活动里面的子活动id
    if not S_CHEST_CONFIG[actId] then                   -- 未缓存配置信息
        S_CHEST_CONFIG[actId] = {}
        local len = 0
        for _,sChestInfo in pairs(AbsActExcel.surpriseChest) do
            if actId == sChestInfo.actId then
                len = len + 1
                S_CHEST_CONFIG[actId][len] = sChestInfo
            end
        end
    end

    return actDB,id,actId,S_CHEST_CONFIG[actId]         -- 活动DB,活动id,子活动id,子活动配置
end

local function getInitDB(human, funcID, isUpdateDaily)
    -- local state = AbsActLogic.isStarted(human, funcID)
    local state = CycleActivityLogic.isStarted(human, funcID)
    if not state then return end

    local actDB,id,actId,sChestConfig = getSChestDBAndConfig(human, funcID)
    if not actDB then return end

    -- 初始活动DB数据
    local absConfig = AbsActExcel.absActivity[funcID]
    if not actDB.curDay or isUpdateDaily then                                   -- 若没初始 或者 跨天更新
        actDB.curDay = Util.diffDay(absConfig.realStartTime) + 1                -- DB当前任务是哪一天
    end
    
    actDB.days = actDB.days or {}                                               -- DB所有天的数据
    
    -- DB初始各天数据
    for _,sChestInfo in ipairs(sChestConfig) do
        actDB.days[sChestInfo.day] = actDB.days[sChestInfo.day] or {}
        if sChestInfo.day == actDB.curDay then                                  -- 当天
            if (actDB.days[sChestInfo.day].state or 0) == STATE_0 then          -- 若为未解锁状态
                actDB.days[sChestInfo.day].state = STATE_1                      -- 改为已解锁状态
            end
        elseif sChestInfo.day < actDB.curDay then                               -- 之前的天数
            if (actDB.days[sChestInfo.day].state or 0) < STATE_3 then           -- 若小于已领取状态
                actDB.days[sChestInfo.day].state = STATE_4                      -- 改为可补领状态
            end 
        else                                                                    -- 后面天数,改为未解锁
            actDB.days[sChestInfo.day].state = STATE_0
        end
        actDB.days[sChestInfo.day].cnt = actDB.days[sChestInfo.day].cnt or 0    -- 任务完成数,默认为0
        if sChestInfo.day == actDB.curDay then                                  -- 当前天
            if actDB.days[sChestInfo.day].cnt >= sChestInfo.maxCnt then         -- 任务完成次数够
                if (actDB.days[sChestInfo.day].state or 0) ~= STATE_3 then      -- 不等于领取状态
                    actDB.days[sChestInfo.day].state = STATE_2                  -- 修改可领取状态
                end
            end
        end
    end

    return actDB,id,actId,sChestConfig
end

local function getCurSChestInfo(human, actDB, sChestConfig)
     -- 取得当天的配置信息
    local curSChestInfo
    for _,sChestInfo in ipairs(sChestConfig) do         
        if sChestInfo.day == actDB.curDay then
            curSChestInfo = sChestInfo
            break
        end
    end

    return curSChestInfo
end

local function updateSend(human, day, actDB)
    local msgRet = Msg.gc.GC_ABS_SURPRISE_CHEST_UPDATE
    msgRet.day = day
    msgRet.cnt = actDB.days[day].cnt
    msgRet.state = actDB.days[day].state
    Msg.send(msgRet, human.fd)
end

local function getReward(human, funcID, day, isBuGet)
    local actDB,id,actId,sChestConfig = getInitDB(human, funcID)
    if not actDB then return end

    local sChestInfo
    for _,tempInfo in ipairs(sChestConfig) do
        if day == tempInfo.day then
            sChestInfo = tempInfo
            break
        end
    end

    if not sChestInfo then return end

    if isBuGet then                                                                    -- 补领
        if actDB.days[day].state ~= STATE_4 then return end                            -- 不是可补领状态
        if not ObjHuman.checkRMB(human, sChestInfo.yuanbao) then                       -- 补领需判断需要的钻石是否足够
            return
        end

        actDB.days[day].state = STATE_5                                                -- 改变为已补领状态
        ObjHuman.decZuanshi(human, -sChestInfo.yuanbao, "abs_surpriseChest_buyGet")    -- 扣钻石
        BagLogic.addItemList(human, sChestInfo.items, "abs_surpriseChest_buyGet")      -- 添加补领道具
    else                                                                               -- 完成任务的领取
        if actDB.days[day].state ~= STATE_2 then return end                            -- 不是可领状态
        actDB.days[day].state = STATE_3                                                -- 改变为已领取状态
        BagLogic.addItemList(human, sChestInfo.items, "abs_surpriseChest_get")         -- 添加完成任务道具
    end

    Broadcast.sendErr(human, Lang.ABS_SURPRISE_CHEST_GET_SUCESS)
    updateSend(human, day, actDB)                                                      -- 信息改变,推道前端更新

    YunYingLogic.sendBanner(human)
    YunYingLogic.updateIcon(YYInfo[funcID], human)
    YunYingLogic.sendGroupUpdate(YYInfo[funcID], human, PanelDefine.PANEL_ID_5015)
end

local function everyReqTriggerTask(human, funcID)
    -- 在线时长达到X分钟这个任务,每次请求活动时,算一下在线时间
	local time = math.max(os.time() - human.db.lastLoginTime, 0)    
    local onlineTime = (human.db.onlineTimeDay or 0) + time
    finishTaskCB(human, funcID, TASK_3, math.floor(onlineTime / 60), true)

    if human.db.dailyTask and human.db.dailyTask.nowHuoYue then
        finishTaskCB(human, funcID, TASK_1, human.db.dailyTask.nowHuoYue, true)
    end
end

local function wrapSurpriseChestNet(net, sChestInfo, actDB)
    net.day = sChestInfo.day
    net.cnt = actDB.days[sChestInfo.day].cnt
    net.state = actDB.days[sChestInfo.day].state
    net.maxCnt = sChestInfo.maxCnt
    net.panelID = sChestInfo.panelID
    net.yuanbao = sChestInfo.yuanbao
    net.desc = sChestInfo.desc

    local len = 0
    for _, itemCf in ipairs(sChestInfo.items) do
        len = len + 1
        Grid.makeItem(net.items[len], itemCf[1], itemCf[2])
    end
    net.items[0] = len
end

function getAndSendMsg(human, funcID)
    local actDB,id,actId,sChestConfig = getInitDB(human, funcID)
    if not actDB then return end

    everyReqTriggerTask(human, funcID)

    local msgRet = Msg.gc.GC_ABS_SURPRISE_CHEST_QUERY
    msgRet.actId = funcID
    msgRet.day = actDB.curDay
    local len = 0
    for _,sChestInfo in ipairs(sChestConfig) do
        len = len + 1
        wrapSurpriseChestNet(msgRet.dayChests[len], sChestInfo, actDB)
    end
    msgRet.dayChests[0] = len
    Msg.send(msgRet, human.fd)
end

function isRed(human, YYInfo, absActConfig)
    local actDB = getInitDB(human, absActConfig.funcID)
    if not actDB then return end

    for _,sChestDayDB in ipairs(actDB.days) do
        if sChestDayDB.state == STATE_2 then return true end     -- 只要有一个可领状态则有红点
    end
end

function isActive(human, YYInfo, funcConfig)
    return not isOpen(human, YYInfo, funcConfig)
end

function isOpen(human, YYInfo, funcConfig)
    -- return AbsActLogic.isStarted(human, funcConfig.funcID)
    return CycleActivityLogic.isStarted(human, funcConfig.funcID)
end

function getLeftTime(human, YInfo, funcConfig)
    -- local ret, endTime, startTime = AbsActLogic.isStarted(human, funcConfig.funcID)
    local ret, endTime, startTime = CycleActivityLogic.isStarted(human, funcConfig.funcID)
    if ret == true then
        return endTime - os.time()
    else
        return 0
    end
end

function get(human, actId, day)
    getReward(human, actId, day)
end

function buGet(human, actId, day)
    getReward(human, actId, day, true)
end

function updateDaily(human, funcID)
    getInitDB(human, funcID, true)
end

-- 登出
function onLogout(human, funcID, parameter)
   finishTaskCB(human, funcID, TASK_3, math.floor(human.db.onlineTimeDay / 60), true)
end

-- 悬赏任务
function onBarTaskgetDo(human, funcID, parameter)
   finishTaskCB(human, funcID, TASK_4, 1)
end

-- 副本
function onCopyFight(human, funcID, parameter)
   finishTaskCB(human, funcID, TASK_7, parameter)
end

-- 每日任务
function onDailyTask(human, funcID, parameter)
   finishTaskCB(human, funcID, TASK_1, human.db.dailyTask.nowHuoYue, true)
end

-- 竞技场
function onJjcFight(human, funcID, parameter)
   finishTaskCB(human, funcID, TASK_2, 1)
end

-- 公会副本
function onUnionEctypeFight(human, funcID, parameter)
  finishTaskCB(human, funcID, TASK_6, parameter)
end  

-- 占卜
function onZhanBuBuyCard(human, funcID, parameter)
   finishTaskCB(human, funcID, TASK_5, parameter)
end

-- 任务完成
function finishTaskCB(human, funcID, type, cnt, isRelpace)
    local actDB,id,actId,sChestConfig = getInitDB(human, funcID)
    if not actDB then return end

    local curSChestDayDB = actDB.days[actDB.curDay]
    if not curSChestDayDB then return end                       -- 没有当前天数DB数据(没有当前天数的任务)

    if curSChestDayDB.state ~= STATE_1 then return end          -- 不是解锁状态,不能完成任务

    local curSChestInfo = getCurSChestInfo(human, actDB, sChestConfig)
    if not curSChestInfo then return end                        -- 没有当天配置信息
    if curSChestInfo.type ~= type then return end               -- 当天的任务类型不一致

    if isRelpace then                                           -- 若是直接替换值
        curSChestDayDB.cnt = cnt                                -- 设置任务完成次数
    else
        curSChestDayDB.cnt = curSChestDayDB.cnt + cnt           -- 设置任务完成次数
    end

    if curSChestDayDB.cnt < 0 then
        curSChestDayDB.cnt = 0
    end
    
    if curSChestDayDB.cnt >= curSChestInfo.maxCnt then          -- 任务完成次数够
        curSChestDayDB.state = STATE_2                          -- 修改可领取状态
        curSChestDayDB.cnt = curSChestInfo.maxCnt               -- 修改为最大完成次数
        YunYingLogic.sendBanner(human)
    end

    --updateSend(human, actDB.curDay, actDB)                      -- 更新推送当天DB数据
end