local ActSevenDayData = class("ActSevenDayData", BaseData)

function ActSevenDayData:ctor()
    self.taskData = {}
    self.scoreReceivedIds = {}
    self.data.isDirty = false
end

function ActSevenDayData:clear()
    self.taskData = {}
    self.scoreReceivedIds = {}
    DataManager:unregisterCrossDayFunc("ActSevenDayData")
    ModuleManager.TaskManager:unRegisterAllModuleTask("ActSevenDayData")
end

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

function ActSevenDayData:initData(data)
    data = data or GConst.EMPTY_TABLE
    if EDITOR_MODE then
		Logger.logHighlight("七天乐数据")
		Logger.printTable(data)
	end

    self.scoreReceivedIds = {} -- 已领取奖励的积分id
    if data.score_reward_ids then
        for _, id in ipairs(data.score_reward_ids) do
            self.scoreReceivedIds[id] = true
        end
    end
    self.taskData = data.tasks or {}
    self.scoreReceivedIds = data.claimed or {}
    -- local taskProgress = data.tasks or {}
    -- for id, info in pairs(self:getTaskCfg()) do
    --     local maxCount = info.number or 1
    --     local task = taskProgress[id] or {}
	-- 	local progress = task.progress or 0
    --     if task.claimed then
    --         progress = maxCount
    --     end
    --     self.taskData[id] = {progress = progress, collect = task.claimed or false}
    -- end

	DataManager:registerCrossDayFunc("ActSevenDayData", function()
		self:setDirty()
	end)
	-- 注册任务监听
	for id, info in pairs(self:getTaskCfg()) do
		ModuleManager.TaskManager:registerTask("ActSevenDayData", info.type, function(count)
			self:addTaskProgress(info.type, count)
		end)
	end
    self:setDirty()
end

function ActSevenDayData:isOpen(period)
    period = period or 1
    local moduleKey = period == 1 and ModuleManager.MODULE_KEY.ACT_SEVENDAY or ModuleManager.MODULE_KEY.ACT_SEVENDAY_2
    if not ModuleManager:getIsOpen(moduleKey, true) then
        return false
    end

    if self:getRemainTime(period) <= 0 then
        return false
    end

    return true
end

function ActSevenDayData:hasRedPoint(period)
    if not self:isOpen(period) then
        return false
    end

    return self:hasTaskRp(period) or self:hasGiftRp(period)
end

-- 获取开启天数
function ActSevenDayData:getOpenDays(period)
    if self._openDays == nil then
        self._openDays = GFunc.getConstIntValue("act_sevenday_duration")
    end
    return self._openDays
end

-- 获取活动开启时间（玩家创号那天）
function ActSevenDayData:getOpenTime(period)
    period = period or 1
    local addDay = 0
    if period == 2 then
        addDay = ModuleManager:getOpenDay(ModuleManager.MODULE_KEY.ACT_SEVENDAY_2) or 0
        if addDay > 0 then
            addDay = addDay - 1
        end
    end
    return Time:getDayBeginTimeStamp(DataManager.PlayerData:getCreateTime()) + addDay*86400
end

-- 结束时间
function ActSevenDayData:getEndTime(period)
    return self:getOpenTime(period) + (self:getOpenDays(period) * 24 * 3600)
end

-- 获取剩余时间
function ActSevenDayData:getRemainTime(period)
    return self:getEndTime(period) - Time:getServerTime()
end

-- 获取当前为活动第几天
function ActSevenDayData:getActDay(period)
    local days = (Time:getServerTime() - self:getOpenTime(period)) // 86400
    if days < 0 then
        days = -days
    end
    return math.min(days + 1, 7)
end

-- 任务及积分奖励 ----------------------------------------------------------------------------------------------------

-- 获取任务配置
function ActSevenDayData:getTaskCfg(taskId)
    taskId = tonumber(taskId)
    if taskId then
        return ConfigManager:getConfig("act_sevenday_quest")[taskId]
    else
        return ConfigManager:getConfig("act_sevenday_quest")
    end
end

-- 获取天对应的任务ids
function ActSevenDayData:getTaskIdsByDay(day, period)
    if period == 2 then
        day = day + 7
    end
    if self.taskDayMap == nil then
        self.taskDayMap = {}
        for id, info in pairs(self:getTaskCfg()) do
            if self.taskDayMap[info.day] == nil then
                self.taskDayMap[info.day] = {}
            end
            table.insert(self.taskDayMap[info.day], id)
        end
    end

    return self.taskDayMap[day] or {}
end

-- 获取排序的id列表
function ActSevenDayData:getSortTaskIdsByDay(day, period)
	local ids = self:getTaskIdsByDay(day, period)
	local sortIds = {}

	for i, id in ipairs(ids) do
		local temp = {id = id, sort = id}
        if self:isTaskReceived(id) then
			temp.sort = temp.sort + 10000000
		end
		if self:canClaimTask(id) then
			temp.sort = temp.sort - 10000000
		end
        table.insert(sortIds, temp)
	end
	table.sort(sortIds, function(a, b)
		return a.sort < b.sort
	end)

	local result = {}
	for i, data in ipairs(sortIds) do
		table.insert(result, data.id)
	end
	return result
end


-- 获取类型对应的ids列表
function ActSevenDayData:getTaskIdsByType(taskType)
    if not self.taskTypeMap then
        self.taskTypeMap = {}
        for id, info in pairs(self:getTaskCfg()) 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 ActSevenDayData:getScoreCfg(scoreId)
    scoreId = tonumber(scoreId)
    if scoreId then
        return ConfigManager:getConfig("act_sevenday_quest_reward")[scoreId]
    else
        return ConfigManager:getConfig("act_sevenday_quest_reward")
    end
end

-- 获取任务类型
function ActSevenDayData:getTaskType(taskId)
    return self:getTaskCfg(taskId).type
end

-- 获取任务目标
function ActSevenDayData:getTaskTarget(taskId)
    return self:getTaskCfg(taskId).number
end

-- 获取任务奖励
function ActSevenDayData:getTaskReward(taskId)
    return self:getTaskCfg(taskId).reward
end

-- 获取任务数据
function ActSevenDayData:getTaskData(taskId)
    if self.taskData[taskId] == nil then
        self.taskData[taskId] = {progress = 0, claimed = 0}
    end

    self.taskData[taskId].collect = (self.taskData[taskId].claimed or 0) == 1
    return self.taskData[taskId]
end

-- 获取任务进度
function ActSevenDayData:getTaskProg(taskId)
    return self:getTaskData(taskId).progress or 0
end

-- 任务是否已领取
function ActSevenDayData:isTaskReceived(taskId)
    return self:getTaskData(taskId).claimed == 1
end

-- 任务是否可领取
function ActSevenDayData:canClaimTask(taskId)
    if self:isTaskReceived(taskId) then
        return false
    end
    if self:getTaskProg(taskId) < self:getTaskTarget(taskId) then
        return false
    end

    return true
end

-- 获取所有可领取的任务奖励
function ActSevenDayData:getAllCanClaimTaskIds(period)
    period = period or 1
    local ids = {}
    for day = 1, self:getActDay(period) do
        for i, id in ipairs(self:getTaskIdsByDay(day, period)) do
            if self:canClaimTask(id) then
                table.insert(ids, id)
            end
        end
    end
    return ids
end

function ActSevenDayData:setTaskClaimed(taskId, ids)
    if taskId then
        self:getTaskData(taskId).claimed = 1
    elseif ids then
        for i, taskId in ipairs(ids) do
            self:getTaskData(taskId).claimed = 1
        end
    end
    self:setDirty()
end

-- 获取积分奖励目标
function ActSevenDayData:getScoreTarget(scoreId)
    return self:getScoreCfg(scoreId).num
end

-- 获取总积分
function ActSevenDayData:getScoreTotal(period)
    period = period or 1
    local cfg = self:getScoreCfg()
    local maxNum = 0
    for k, v in pairs(cfg) do
        if v.period == period and maxNum < v.num then
            maxNum = v.num
        end
    end
    return maxNum
end

-- 获取积分
function ActSevenDayData:getScore(period)
    period = period or 2
    if period == 1 then
        return DataManager.BagData.ItemData:getItemNumById(GConst.ItemConst.ITEM_ID_SEVEN_DAY_SCORE)
    else
        return DataManager.BagData.ItemData:getItemNumById(GConst.ItemConst.ITEM_ID_SEVEN_DAY_SCORE_2)
    end
end

-- 积分是否已领取
function ActSevenDayData:isScoreReceived(scoreId)
    return self.scoreReceivedIds[scoreId]
end

-- 积分奖励是否可领取
function ActSevenDayData:canClaimScore(scoreId, period)
    period = period or 1
    if self:isScoreReceived(scoreId) then
        return false
    end
    if self:getScore(period) < self:getScoreTarget(scoreId) then
        return false
    end

    return true
end

-- 获取所有可领取的积分奖励
function ActSevenDayData:getAllCanClaimScoreIds(period)
    period = period or 1
    local ids = {}
    for id, info in ipairs(self:getScoreCfg()) do
        if info.period == period and self:canClaimScore(id, period) then
            table.insert(ids, id)
        end
    end
    return ids
end

function ActSevenDayData:setScoreReceived(scoreId, ids)
    if scoreId then
        self.scoreReceivedIds[scoreId] = true
    elseif ids then
        for i, scoreId in ipairs(ids) do
            self.scoreReceivedIds[scoreId] = true
        end
    end
    self:setDirty()
end

-- 是否有任务红点
function ActSevenDayData:hasTaskRp(period)
    period = period or 1
    -- 任务奖励
    for i = 1, self:getActDay(period) do
        if self:hasTaskDayRp(i, period) then
            return true
        end
    end
    -- 积分奖励
    for scoreId, info in ipairs(self:getScoreCfg()) do
        if period == info.period and self:canClaimScore(scoreId, period) then
            return true
        end
    end

    return false
end

function ActSevenDayData:hasTaskDayRp(day, period)
    local ids = self:getTaskIdsByDay(day, period)
    for i, taskId in ipairs(ids) do
        if self:canClaimTask(taskId) then
            return true
        end
    end

    return false
end

-- 添加任务进度
function ActSevenDayData:addTaskProgress(taskType, count)
    local ids = self:getTaskIdsByType(taskType)
    for i, id in ipairs(ids) do
        local serverData = self:getTaskData(id)
        local config = self:getTaskCfg(id)
        local addCount = count
        -- if table.containValue(GConst.TaskConst.TASK_CONDITION_EQUAL, taskType) then
        --     if config.condition == addCount then -- 有参数的任务类型处理一下
        --         addCount = 1
        --     else
        --         addCount = 0
        --     end
        -- end
        if table.containValue(GConst.TaskConst.RELPACE_TASK_TYPE, taskType) then
            serverData.progress = math.max(serverData.progress, addCount)
        else
            if serverData.progress <= math.maxinteger - addCount then -- 检查一下是否相加会溢出
                serverData.progress = serverData.progress + addCount
            end
        end
    end
end

-- 任务奖励领取成功
function ActSevenDayData:onGetRewardTask()
    self:setDirty()
end

function ActSevenDayData:getGiftList(day, period)
    if self._giftList == nil then
        self._giftList = {}
        local cfg = ConfigManager:getConfig("act_gift")
        for k, v in pairs(cfg) do
            if v.type == PayManager.PURCHARSE_ACT_TYPE.ACT_SEVEN_DAY then
                if self._giftList[v.parameter] == nil then
                    self._giftList[v.parameter] = {}
                end
                local obj = {
                    id = k,
                    cfg = v,
                }
                if v.parameter_pro and v.parameter_pro[1] == 1 then -- 免费
                    obj.isFree = true
                elseif v.item_cost then -- 道具购买
                    obj.isItemCost = true
                elseif v.recharge_id == nil then -- 广告
                    obj.isAd = true
                end
                table.insert(self._giftList[v.parameter], obj)
            end
        end
    end
    day = day or 1
    if period == 2 then -- 第二期
        day = day + 7
    end
    return self._giftList[day]
end

function ActSevenDayData:getGiftRemainNum(giftId, period)
    period = period or 1
    for i = 1, 7 do
        local list = self:getGiftList(i, period)
        for k, v in ipairs(list) do
            if v.id == giftId then
                local limit = v.cfg.limit or 0
                local boughtNum = DataManager.PaymentData:getGiftBoughtNum(PayManager.PURCHARSE_TYPE.ACT_GIFT, giftId)
                return limit - boughtNum
            end
        end
    end
    return 0
end

function ActSevenDayData:getIsGiftAllOverDay(day, period)
    period = period or 1
    local list = self:getGiftList(day, period)
    for k, v in ipairs(list) do
        local limit = v.cfg.limit or 0
        local boughtNum = DataManager.PaymentData:getGiftBoughtNum(PayManager.PURCHARSE_TYPE.ACT_GIFT, v.id)
        if limit > boughtNum then
            return false
        end
    end
    return true
end

function ActSevenDayData:hasGiftRp(period)
    local day = self:getActDay(period)
    if day <= 0 or day >= 7 then
        day = 7
    end
    for i = 1, day do
        local list = self:getGiftList(i, period)
        for k, v in ipairs(list) do
            if v.isFree or v.isAd then
                local limit = v.cfg.limit or 0
                local boughtNum = DataManager.PaymentData:getGiftBoughtNum(PayManager.PURCHARSE_TYPE.ACT_GIFT, v.id)
                if limit > boughtNum then
                    return true
                end
            end
        end
    end
    return false
end

function ActSevenDayData:hasGiftDayRp(day, period)
    local list = self:getGiftList(day, period)
    for k, v in ipairs(list) do
        if v.isFree or v.isAd then
            local limit = v.cfg.limit or 0
            local boughtNum = DataManager.PaymentData:getGiftBoughtNum(PayManager.PURCHARSE_TYPE.ACT_GIFT, v.id)
            if limit > boughtNum then
                return true
            end
        end
    end
    return false
end

return ActSevenDayData