local SevenDayData = class("SevenDayData", BaseData)

function SevenDayData:ctor()
    self:clear()
end

function SevenDayData:clear()
    self.data.isDirty = false
    self.collectTaskCount = 0
    self.collectStepCount = 0
    self.openTs = 0
    self.endTime = 0
    self.tasks = {}
    self.stepRewards = {}
    DataManager:unregisterCrossDayFunc("SevenDayData")
    DataManager:unregisterTryOpenFunc("SevenDayData")
end

function SevenDayData:init(data)
    data = data or GConst.EMPTY_TABLE
    self.openTs = GFunc.formatTimeStep(data.open_day_ts)
    if self.openTs and self.openTs > 0 then
        self.openTs = self.openTs - self.openTs % 86400
        self.endTime = self.openTs + self:getDurationTime()
    else
        self.openTs = 0
        self.endTime = self.openTs
    end
    self.tasks = data.tasks or {}
    self.stepRewards = data.claimed or {}

    local today = Time:getBeginningOfServerToday()
    self.actDay = (today - self.openTs) // 86400 + 1

    self:calCollectTaskCount()
    self:calCollectStepCount()
    self:initTaskListener()

    if self.openTs <= 0 then
        DataManager:registerTryOpenFunc("SevenDayData", function()
            if self.openTs <= 0 then
                if ModuleManager:getIsOpen(ModuleManager.MODULE_KEY.SEVEN_DAY, true) then
                    self.openTs = Time:getBeginningOfServerToday()
                    self.endTime = self.openTs + self:getDurationTime()
                    self.actDay = 1
                    DataManager:unregisterTryOpenFunc("SevenDayData")
                end
            end
        end)
    end

    DataManager:registerCrossDayFunc("SevenDayData", function()
        self.actDay = self.actDay + 1
        self:setDirty()
    end)
end

function SevenDayData:getIsOpen()
    if GFunc.isShenhe() then
        return false
    end
    if not ModuleManager:getIsOpen(ModuleManager.MODULE_KEY.SEVEN_DAY, true) then
        return false
    end
    local nowTime = Time:getServerTime()
    if self.endTime < nowTime or self.openTs > nowTime then
        return false
    end
    if self.collectTaskCount >= self:getSevenDayTaskMaxCount() and self.collectStepCount >= self:getSevenDayRewardMaxCount() then
        return false
    end
    return true
end

function SevenDayData:getDurationTime()
    if not self.durationTime then
        self.durationTime = GFunc.getConstIntValue("act_sevenday_time") * 86400
    end
    return self.durationTime
end

function SevenDayData:getActDay()
    return self.actDay or 1
end

function SevenDayData:getEndTime()
    return self.endTime
end

function SevenDayData:refreshTasks(data)
    if not data then
        return
    end

    for id, task in pairs(data) do
        self.tasks[id] = task
    end
    self:calCollectTaskCount()
end

function SevenDayData:refreshClaimed(data)
    if not data then
        return
    end
    for id, b in pairs(data) do
        self.stepRewards[id] = b
    end
    self:calCollectStepCount()
end

function SevenDayData:opened()
    return self.openTs > 0
end

function SevenDayData:setOpen()
    if self.openTs > 0 then
        return
    end
    self.collectTaskCount = 0
    self.collectStepCount = 0
    self.stepRewards = {}

    self.openTs = Time:getServerTime()
    self.endTime = self.openTs + self:getDurationTime()
    self.actDay = 1
end

function SevenDayData:setDirty()
    self.data.isDirty = not self.data.isDirty
end

function SevenDayData:getSevenDayTaskCfg()
    if self.sevenDayTaskCfg == nil then
        self.sevenDayTaskCfg = ConfigManager:getConfig("act_sevenday_quest")
    end
    return self.sevenDayTaskCfg
end

function SevenDayData:getSevenDayTaskMaxCount()
    if self.sevenDayTaskMaxCount == nil then
        self.sevenDayTaskMaxCount = ConfigManager:getConfigNum("act_sevenday_quest")
    end
    return self.sevenDayTaskMaxCount
end

function SevenDayData:getSevenDayRewardCfg()
    if self.sevenDayRewardCfg == nil then
        self.sevenDayRewardCfg = ConfigManager:getConfig("act_sevenday_quest_reward")
    end
    return self.sevenDayRewardCfg
end

function SevenDayData:getSevenDayRewardMaxCount()
    if self.sevenDayRewardMaxCount == nil then
        self.sevenDayRewardMaxCount = ConfigManager:getConfigNum("act_sevenday_quest_reward")
    end
    return self.sevenDayRewardMaxCount
end

function SevenDayData:calCollectTaskCount()
    self.collectTaskCount = 0
    for id, info in ipairs(self:getSevenDayTaskCfg()) do
        if self:taskCollected(id) then
            self.collectTaskCount = self.collectTaskCount + 1
        end
    end
end

function SevenDayData:calCollectStepCount()
    self.collectStepCount = 0
    for id, info in ipairs(self:getSevenDayRewardCfg()) do
        if self:getStepCollected(id) then
            self.collectStepCount = self.collectStepCount + 1
        end
    end
end

function SevenDayData:getTaskListByDay(day)
    if not self.taskList then
        self.taskList = {}
        for id, info in ipairs(self:getSevenDayTaskCfg()) do
            if not self.taskList[info.day] then
                self.taskList[info.day] = {}
            end
            table.insert(self.taskList[info.day], id)
        end
    end
    return self.taskList[day] or {}
end

function SevenDayData:getStepRewardList()
    if not self.stepRewardList then
        self.stepRewardList = {}
        for id, info in ipairs(self:getSevenDayRewardCfg()) do
            table.insert(self.stepRewardList, id)
        end
    end

    return self.stepRewardList
end

function SevenDayData:getCollectedCount()
    return self.collectTaskCount
end

function SevenDayData:getTotalCount()
    return ConfigManager:getConfigNum("act_sevenday_quest")
end

function SevenDayData:getTaskInfo(id)
    if not self.tasks[id] then
        self.tasks[id] = {
            id = id,
            progress = 0,
            claimed = false
        }
    end

    return self.tasks[id]
end

function SevenDayData:taskCollected(id)
    return self:getTaskInfo(id).claimed
end

function SevenDayData:taskCount(id)
    return self:getTaskInfo(id).progress
end

function SevenDayData:taskTotalCount(id)
    local cfg = self:getSevenDayTaskCfg()[id]
    if not cfg then
        return 1 -- 防止除法报错
    end
    return cfg.number or 1
end

function SevenDayData:getTaskReward(id)
    local cfg = self:getSevenDayTaskCfg()[id]
    if not cfg then
        return
    end
    return cfg.reward
end

function SevenDayData:getTaskDay(id)
    local cfg = self:getSevenDayTaskCfg()[id]
    if not cfg then
        return 1
    end
    return cfg.day
end

function SevenDayData:getTaskType(id)
    local cfg = self:getSevenDayTaskCfg()[id]
    if not cfg then
        return
    end
    return cfg.type
end

function SevenDayData:getTaskDayLimit(id)
    local cfg = self:getSevenDayTaskCfg()[id]
    if not cfg or not cfg.count_type then
        return
    end
    return cfg.day
end

function SevenDayData:getTaskListByType(taskType)
    if not self.taskTypeMap then
        self.taskTypeMap = {}
        for id, info in ipairs(self:getSevenDayTaskCfg()) do
            if not self.taskTypeMap[info.type] then
                self.taskTypeMap[info.type] = {}
            end
            table.insert(self.taskTypeMap[info.type], id)
        end
    end

    return self.taskTypeMap[taskType] or {}
end

function SevenDayData:addTaskProgress(id, count)
    local dayLimit = self:getTaskDayLimit(id)
    if dayLimit and dayLimit > self:getActDay() then
        return
    end
    self:getTaskInfo(id).progress = self:getTaskInfo(id).progress + count
    self:setDirty()
end

function SevenDayData:canClaimTask(id)
    if self:taskCollected(id) then
        return false
    end

    return self:taskTotalCount(id) <= self:taskCount(id)
end

function SevenDayData:getStepNum(id)
    local cfg = self:getSevenDayRewardCfg()[id]
    if not cfg then
        return 1 -- 防止除法为0
    end
    return cfg.num
end

function SevenDayData:getStepCollected(id)
    return self.stepRewards[id] == true
end

function SevenDayData:getStepReward(id)
    local cfg = self:getSevenDayRewardCfg()[id]
    if not cfg then
        return
    end
    return cfg.reward
end

function SevenDayData:canClaimStepTask(id)
    if self:getStepCollected(id) then
        return false
    end

    return self:stepOver(id)
end

function SevenDayData:stepOver(id)
    return self.collectTaskCount >= self:getStepNum(id)
end

function SevenDayData:showRedPoint(day)
    if day then
        local list = self:getTaskListByDay(day)
        for _, id in ipairs(list) do
            if self:canClaimTask(id) then
                return true
            end
        end
    else
        local day = self:getActDay()
        for id, info in pairs(self.tasks) do
            local cfg = self:getSevenDayTaskCfg()[id]
            if cfg and cfg.day <= day then
                if self:canClaimTask(id) then
                    return true
                end
            end
        end

        local list = self:getStepRewardList()
        for _, id in ipairs(list) do
            if self:canClaimStepTask(id) then
                return true
            end
        end
    end

    return false
end

function SevenDayData:getSevenDayTaskI18NCfg()
    return I18N:getConfig("act_sevenday_quest")
end

function SevenDayData:getSevenDayTaskDesc(id)
	local cfg = self:getSevenDayTaskI18NCfg()
    if cfg == nil then
        return GConst.EMPTY_STRING
    end
	return cfg[id].desc
end

function SevenDayData:initTaskListener()
    local nowTime = Time:getServerTime()
    -- 活动结束就不用监听了
    if self.endTime > 0 and self.endTime < nowTime then
        ModuleManager.TaskManager:unRegisterAllModuleTask("SevenDayData")
        return false
    end
    -- 完成了就不用监听了
    if self.collectTaskCount >= self:getSevenDayTaskMaxCount() and self.collectStepCount >= self:getSevenDayRewardMaxCount() then
        ModuleManager.TaskManager:unRegisterAllModuleTask("SevenDayData")
        return false
    end

    local cfg = self:getSevenDayTaskCfg()
    for _, v in ipairs(cfg) do
        local taskType = v.type
        ModuleManager.TaskManager:registerTask("SevenDayData", taskType, function(count)
            local list = self:getTaskListByType(taskType)
            if #list > 0 then
                for _, id in ipairs(list) do
                    self:addTaskProgress(id, count)
                end
            end
        end)
    end
end

return SevenDayData