local DailyTaskData = class("DailyTaskData", BaseData)

local TaskDailyCfg = ConfigManager:getConfig("task_daily")
local TaskDailyStageCfg = ConfigManager:getConfig("task_daily_stage")
local TaskAchievementCfg = ConfigManager:getConfig("task_achievement")

function DailyTaskData:ctor()
	self.data.isDirty = false
end

function DailyTaskData:clear()
	DataManager:unregisterCrossDayFunc("DailyTaskData")
	ModuleManager.TaskManager:unRegisterAllModuleTask("DailyTaskData")
end

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

function DailyTaskData:init(daily, achievement)
	daily = daily or {}
	achievement = achievement or {}

	self:initDaily(daily)
	self:initAchievement(achievement)

	-- 监听任务
	for id, info in pairs(TaskDailyCfg) do
		ModuleManager.TaskManager:registerTask("DailyTaskData", info.task_type, function(count)
			self.dailyRedState = nil
			self:addTaskProgress(info.task_type, count)
		end)
	end

	for id, info in pairs(TaskAchievementCfg) do
		ModuleManager.TaskManager:registerTask("DailyTaskData", info.type, function(count)
			self.achievementRedState = nil
			self:addTaskProgress(info.type, count)
		end)
	end

	-- 跨天
	DataManager:registerCrossDayFunc("DailyTaskData", function()
		-- 重置任务数据
		for id, data in pairs(self.dailyTaskData) do
			data.claimed = 0
			data.progress = 0
		end
		-- 重置进度奖励数据
		for id, claimed in pairs(self.progRewardData) do
			self.progRewardData[id] = false
		end

		self.dayPoint = 0
		self:setDirty()
	end)
	self.dailyRedState = nil
	self.achievementRedState = nil
	self:showRedPoint()
end

function DailyTaskData:initDaily(daily)
	daily = daily or {}

	--任务领取状态&进度
	self.dailyTaskData = daily.tasks or {}
	-- 活跃度
	self.dayPoint = daily.point or 0
	-- 活跃度领奖
	self.progRewardData = daily.stage_claimed or {}

	-- 任务配置
	self.dailyTaskIds = {}
	for id, info in pairs(TaskDailyCfg) do
		table.insert(self.dailyTaskIds, id)
	end
	table.sort(self.dailyTaskIds)
	-- 阶段配置
	self.dailyStageIds = {}
	for id, info in pairs(TaskDailyStageCfg) do
		table.insert(self.dailyStageIds, id)
	end
	table.sort(self.dailyStageIds)
	self.dailyRedState = nil
	self:showRedPoint()
end

function DailyTaskData:initAchievement(achievement)
	achievement = achievement or {}

	-- 成就任务
	self.achievementData = achievement.tasks or {}
	self.achievementRedState = nil
	self:showRedPoint()
end

function DailyTaskData:getIsOpen(showToast)
	if not ModuleManager:getIsOpen(ModuleManager.MODULE_KEY.TASK, not showToast) then
		return false
	end

	return true
end

function DailyTaskData:showRedPoint()
	if self.dailyRedState == nil and self.achievementRedState == nil then
		return self:showDailyRedPoint() or self:showAchievementRedPoint()
	end
	return self.dailyRedState or self.achievementRedState
end

function DailyTaskData:showDailyRedPoint()
	if not self.dailyTaskData then
		return
	end
	if self.dailyRedState ~= nil then
		return self.dailyRedState
	end
	for idx, id in pairs(self.dailyTaskIds) do
		if self:canClaimTask(id) then
			self.dailyRedState = true
			return true
		end
	end

	for idx, id in pairs(self.dailyStageIds) do
		if self:canClaimStage(id) then
			self.dailyRedState = true
			return true
		end
	end

	self.dailyRedState = false
	return false
end

function DailyTaskData:showAchievementRedPoint()
	if not self.achievementData then
		return
	end
	if self.achievementRedState ~= nil then
		return self.achievementRedState
	end
	for id, info in pairs(TaskAchievementCfg) do
		for stage = 1, self:getAchievementTotalStage(id) do
			if self:canClaimAchievement(id, stage) then
				self.achievementRedState = true
				return true
			end
		end
	end
	self.achievementRedState = false
	return false
end

-- 是否完成全部每日任务
function DailyTaskData:isAllDailyTaskFinished()
	for idx, id in pairs(self.dailyTaskIds) do
		if not self:isTaskReceived(id) then
			return false
		end
	end

	for idx, id in pairs(self.dailyStageIds) do
		if not self:isStageReceived(id) then
			return false
		end
	end

	return true
end

-- 任务 -----------------------------------------------------------------------------------------------------------------------------------------

-- 任务是否开启
function DailyTaskData:isTaskOpen(taskId)
	if TaskDailyCfg[taskId].func_open == nil then
		return true
	end

	return ModuleManager:getIsOpen(TaskDailyCfg[taskId].func_open, true)
end

-- 获取任务类型
function DailyTaskData:getTaskType(taskId)
	return TaskDailyCfg[taskId].task_type
end

-- 获取任务循环类型
function DailyTaskData:getTaskRoutineType(taskId)
	return TaskDailyCfg[taskId].routine_type
end

-- 获取任务目标
function DailyTaskData:getTaskTarget(taskId)
	return TaskDailyCfg[taskId].number
end

-- 获取任务奖励点数
function DailyTaskData:getTaskPoint(taskId)
	return TaskDailyCfg[taskId].value
end

-- 获取任务当前进度
function DailyTaskData:getTaskProg(taskId)
	taskId = tonumber(taskId)
	return self.dailyTaskData[taskId] and self.dailyTaskData[taskId].progress or 0
end

-- 任务是否已领取
function DailyTaskData:isTaskReceived(taskId)
	taskId = tonumber(taskId)
	return self.dailyTaskData[taskId] and self.dailyTaskData[taskId].claimed and self.dailyTaskData[taskId].claimed > 0
end

-- 任务是否已完成
function DailyTaskData:isTaskFinished(taskId)
	return self:getTaskProg(taskId) >= self:getTaskTarget(taskId)
end

-- 任务是否可领取
function DailyTaskData:canClaimTask(taskId)
	return self:isTaskFinished(taskId) and not self:isTaskReceived(taskId)
end

-- 获取可领奖的所有任务id
function DailyTaskData:getCanClaimTaskIds()
	local ids = {}
	for idx, taskId in pairs(self.dailyTaskIds) do
		if self:canClaimTask(taskId) then
			table.insert(ids, taskId)
		end
	end
	return ids
end

-- 获取可展示的每日任务id列表
function DailyTaskData:getTaskIdsSort()
	local taskids = self.dailyTaskIds or {}

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

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

-- 任务进度变化
function DailyTaskData:addTaskProgress(taskType, count)
	for taskId, info in pairs(TaskDailyCfg) do
		if self:getTaskType(taskId) == taskType then
			self.dailyTaskData[taskId] = self.dailyTaskData[taskId] or {}
			if not self:isTaskFinished(taskId) then
				self.dailyTaskData[taskId].progress = (self.dailyTaskData[taskId].progress or 0) + count
			end
		end
	end
	for achievementId, info in pairs(TaskAchievementCfg) do
		if self:getTaskTypeByAchievementId(achievementId) == taskType then
			self.achievementData[achievementId] = self.achievementData[achievementId] or {}
			if not self:isAchievementFinished(achievementId, self:getAchievementTotalStage(achievementId)) then
				self.achievementData[achievementId].progress = (self.achievementData[achievementId].progress or 0) + count
			end
		end
	end

	self.dailyRedState = nil
	self.achievementRedState = nil
	self:setDirty()
end

-- 领奖成功
function DailyTaskData:onTaskClaimed(dayPoint)
	self.dayPoint = dayPoint or self.dayPoint

	for idx, taskId in pairs(self:getCanClaimTaskIds()) do
		self.dailyTaskData[taskId].claimed = 1
	end

	self.dailyRedState = nil
	self:setDirty()
end

-- 阶段 -----------------------------------------------------------------------------------------------------------------------------------------

-- 领取条件
function DailyTaskData:getStageCondition(stageId)
	return TaskDailyStageCfg[stageId].point
end

-- 获取奖励
function DailyTaskData:getStageReward(stageId)
	return TaskDailyStageCfg[stageId].reward
end

-- 获取循环类型
function DailyTaskData:getStageRoutineType(stageId)
	return TaskDailyStageCfg[stageId].routine_type
end

-- 获取阶段id列表
function DailyTaskData:getStageIds()
	return self.dailyStageIds
end

-- 获取阶段奖励目标list
function DailyTaskData:getStageTargetList()
	local targetList = {}
	for i, id in ipairs(self.dailyStageIds) do
		table.insert(targetList, self:getStageCondition(id))
	end

	table.sort(targetList, function(a, b)
		return a < b
	end)

	return targetList
end

-- 获取当前活跃积分
function DailyTaskData:getCurStageScore()
	return self.dayPoint
end

-- 是否已领奖
function DailyTaskData:isStageReceived(stageId)
	stageId = tonumber(stageId)
	return self.progRewardData[stageId] or false
end

-- 是否可领奖
function DailyTaskData:canClaimStage(stageId)
	return self:getCurStageScore() >= self:getStageCondition(stageId) and not self:isStageReceived(stageId)
end

-- 领奖成功
function DailyTaskData:onStageClaimed(type, stageId)
	if type and stageId == 0 then
		for k, id in pairs(self:getStageIdsByType(type)) do
			if self:canClaimStage(id) then
				self.progRewardData[id] = true
			end
		end
	else
		self.progRewardData[stageId] = true
	end
	self.dailyRedState = nil
	self:setDirty()
end

-- 成就 ---------------------------------------------------------------------------------------------------------------------------------------

-- 获取领奖条件
function DailyTaskData:getAchievementCondition(achievementId, stage)
	return TaskAchievementCfg[achievementId].number[stage]
end

-- 获取奖励
function DailyTaskData:getAchievementReward(achievementId, stage)
	return TaskAchievementCfg[achievementId].reward[stage]
end

function DailyTaskData:getTaskTypeByAchievementId(achievementId)
	return TaskAchievementCfg[achievementId].type
end

-- 获取当前进度
function DailyTaskData:getAchievementProg(achievementId)
	return self.achievementData[achievementId] and self.achievementData[achievementId].progress or 0
end

-- 获取任务总共阶段
function DailyTaskData:getAchievementTotalStage(achievementId)
	return #TaskAchievementCfg[achievementId].number
end

-- 当前所处阶段
function DailyTaskData:getAchievementStage(achievementId)
	local cfg = TaskAchievementCfg[achievementId]
	local stageNum = #cfg.number
	for stage = 1, stageNum do
		if self:canClaimAchievement(achievementId, stage) then
			return stage
		end
		if not self:isAchievementFinished(achievementId, stage) then
			return stage
		end
	end
	return stageNum
end

-- 是否已完成
function DailyTaskData:isAchievementFinished(achievementId, stage)
	return self:getAchievementProg(achievementId) >= self:getAchievementCondition(achievementId, stage)
end

-- 是否已领奖
function DailyTaskData:isAchievementReceived(achievementId, stage)
	achievementId = tonumber(achievementId)
	self.achievementData[achievementId] = self.achievementData[achievementId] or {}
	return self.achievementData[achievementId].claimed and self.achievementData[achievementId].claimed >= stage or false
end

-- 是否可领奖
function DailyTaskData:canClaimAchievement(achievementId, stage)
	if self:isAchievementReceived(achievementId, stage) then
		return false
	end
	if not self:isAchievementFinished(achievementId, stage) then
		return false
	end

	return true
end

function DailyTaskData:getAchievementIdsSort()
	local temp = {}
	for id, info in ipairs(TaskAchievementCfg) do
		local info = {id = id, sort = id}
		local stage = self:getAchievementStage(id)
		if self:canClaimAchievement(id, stage) then
			info.sort = info.sort - 10000
		end
		if self:isAchievementReceived(id, stage) then
			info.sort = info.sort + 10000
		end
		table.insert(temp, info)
	end
	table.sort(temp, function(a, b)
		return a.sort < b.sort
	end)

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

-- 领奖成功
function DailyTaskData:onAchievementClaimed(achievementId, stage)
	if achievementId == nil or stage == nil then
		-- 一键领取
		for achievementId, info in ipairs(TaskAchievementCfg) do
			for stage = self:getAchievementStage(achievementId), self:getAchievementTotalStage(achievementId) do
				if self:canClaimAchievement(achievementId, stage) then
					self.achievementData[achievementId] = self.achievementData[achievementId] or {}
					self.achievementData[achievementId].claimed = stage
				end
			end
		end
	else
		self.achievementData[achievementId] = self.achievementData[achievementId] or {}
		self.achievementData[achievementId].claimed = stage
	end
	self.achievementRedState = nil
	self:setDirty()
end

return DailyTaskData