%%%-------------------------------------------------------------------
%%% @doc    孩子-任务逻辑
%%% Module  : lib_child_task.erl
%%% Created : 2020-02-17
%%% @Author : tyl
%%%-------------------------------------------------------------------
-module(lib_child_task).

-include("common.hrl").
-include("server.hrl").
-include("child.hrl").
-include("figure.hrl").
-include("def_goods.hrl").
-include("def_fun.hrl").
-include("predefine.hrl").
-include("def_module.hrl").
-include("goods.hrl").
-include("errcode.hrl").

-export([
	finish_add_liveness/2           %% 达成xx活跃度
	,finish_kill_deserted_boss/1    %% 达成击杀xx只废都boss
	,finish_kill_reward_boss/1      %% 达成击杀xx只赏金boss
	,finish_guild_collect/1         %% 达成完成xx次公会采集
	,finish_multi_dun/4             %% 达成完成xx次多人副本
	,finish_dungeon/4               %% 参与经验副本xx次
	,finish_charm_beach/1           %% 完成温泉xx次
	,finish_husong/1                %% 完成护送xx次
	,finish_guild_noon_boss/1       %% 完成xx次公会午间boss
	,finish_guild_night_boss/1      %% 完成xx次公会晚间boss
	,finish_grow_up_child/1         %% 完成孩子培养xx次
	,finish_vote_for_child/1        %% 完成孩子点赞xx次

	,get_child_daily_task_info/1    %% 获取每日任务信息
	,receive_daily_task_exp/2       %% 领取日常任务经验
	,receive_daily_task_reward/2    %% 领取经验阶段奖励
	,quick_receive_task_reward/1    %% 一键领取阶段奖励

	,async_event/4                  %% 异步玩家进程
	,daily_clear/1                  %% 清理日常任务数据
	,do_refresh_child_task/1
]).

%% -------------------------------------- API --------------------------------------
%% 达成xx活跃度
finish_add_liveness(Player, Num) ->
	{ok, NewPlayer} = trigger_task(Player, ?TASK_TYPE_ADD_LIVENESS, 0, Num),
	NewPlayer.

%% 达成击杀xx只废都boss(废弃)
finish_kill_deserted_boss(Player) ->
	{ok, NewPlayer} = trigger_task(Player, ?TASK_TYPE_KILL_DESERTED_BOSS, 0, 1),
	NewPlayer.

%% 达成击杀xx只赏金boss
finish_kill_reward_boss(Player) ->
	{ok, NewPlayer} = trigger_task(Player, ?TASK_TYPE_KILL_REWARD_BOSS, 0, 1),
	NewPlayer.

%% 达成完成xx次公会采集(废弃)
finish_guild_collect(Player) ->
	{ok, NewPlayer} = trigger_task(Player, ?TASK_TYPE_GUILD_COLLECT, 0, 1),
	NewPlayer.

%% 达成完成xx次多人副本
finish_multi_dun(Player, DunType, _DunId, Num) ->
	case DunType of
		?CHILD_TASK_MULTI_DUNGEON ->
			{ok, NewPlayer} = trigger_task(Player, ?TASK_TYPE_FINISH_MULTI_DUN, 0, Num),
			NewPlayer;
		_ ->
			Player
	end.

%% 完成经验副本xx次
finish_dungeon(Player, DunType, DunId, Num) ->
	DunKey = case  lists:member(DunType, ?CHILD_TASK_All_DUNGEON_TYPE) of
		         true -> DunType;
		         _   -> DunId
	         end,
	Sequence = case get_sequence(dun_exp, DunKey) of  %% 需要判断副本Id
		           Seq when Seq > 0 -> Seq;
		           _                -> 0
	           end,
	case Sequence > 0 of
		true ->
			{ok, NewPlayer} = trigger_task(Player, ?TASK_TYPE_FINISH_EXP_DUN, DunKey, Num),
			NewPlayer;
		_ ->
			Player
	end.

%% 完成温泉xx次
finish_charm_beach(Player) ->
	{ok, NewPlayer} = trigger_task(Player, ?TASK_TYPE_CHARM_BEACH, 0, 1),
	NewPlayer.

%% 完成护送xx次
finish_husong(Player) ->
	{ok, NewPlayer} = trigger_task(Player, ?TASK_TYPE_HUSONG, 0, 1),
	NewPlayer.

%% 完成xx次公会午间boss(废弃)
finish_guild_noon_boss(Player) ->
	{ok, NewPlayer} = trigger_task(Player, ?TASK_TYPE_GUILD_NOON_BOSS, 0, 1),
	NewPlayer.

%% 完成xx次公会晚间boss(废弃)
finish_guild_night_boss(Player) ->
	{ok, NewPlayer} = trigger_task(Player, ?TASK_TYPE_GUILD_NIGHT_BOSS, 0, 1),
	NewPlayer.

%% 完成孩子培养xx次
finish_grow_up_child(Player) ->
	{ok, NewPlayer} = trigger_task(Player, ?TASK_TYPE_GROW_UP_CHILD, 0, 1),
	NewPlayer.

%% 完成孩子点赞xx次
finish_vote_for_child(Player) ->
	{ok, NewPlayer} = trigger_task(Player, ?TASK_TYPE_VOTE_FOR_CHILD, 0, 1),
	NewPlayer.

%% 异步玩家进程触发
async_event(RoleId, Mod, Fun, Args) when is_integer(RoleId) ->
	lib_player:apply_cast(RoleId, ?APPLY_CAST_SAVE, Mod, Fun, Args);
async_event(_PlayerId, _M, _F, _A) -> skip.

%% 清理日常任务
daily_clear(_Delay) ->
	spawn(fun() ->
		RandTime = urand:rand(1, 1000),
		timer:sleep(RandTime),
		Sql = io_lib:format(?SQL_DELETE_CHILD_DAILY_TASK, []),
		db:execute(Sql),
		refresh_child_daily_task()
	end).

refresh_child_daily_task() ->
	Pids = lib_player:get_online_pids(),
	[refresh_child_daily_task(Pid) || Pid <- Pids].

refresh_child_daily_task(Pid) ->
	lib_player:apply_cast(Pid, ?APPLY_CAST_SAVE, ?MODULE, do_refresh_child_task, []).

do_refresh_child_task(Player) ->
	#player_status{status_child = StatusChild} = Player,
	%% 如果已经领养孩子,不需要更新每日任务
	case StatusChild#status_child.child_sex > 0 of
		true -> {ok,Player};
		_ ->
			NewStatusChild = StatusChild#status_child{daily_task = []},
			Player1 = lib_child_util:save_dict_status_child(NewStatusChild, Player),
			AllTask = data_child:get_all_child_daily_task_cfg(),
			F = fun(TaskSeq, TPackList) ->
				[{TaskSeq, 0, 0}|TPackList]
			    end,
			PackList = lists:foldl(F, [], AllTask),
			lib_child:send_msg(Player#player_status.sid, 16505, [PackList]),
			%% 检测开服天数开放玩具位条件
			% {ok, NewPlayer} = lib_child_items:check_if_active_toy_slot(Player1, ?SLOT_OPEN_TYPE_OPEN_DAY),
			{ok, Player1}
	end.

%% -------------------------------------------------------------------------------
%% 获取每日任务信息
get_child_daily_task_info(Player) ->
	#player_status{status_child = StatusChild} = Player,
	#status_child{daily_task = DailyTaskList}  = StatusChild,
	F = fun(DailyTask, TPackList) ->
		#child_daily_task{
			sequence   = Sequence,
			progress   = Progress,
			task_state = TaskState
		} = DailyTask,
		[{Sequence, Progress, TaskState}|TPackList]
	end,
	PackList = lists:foldl(F, [], DailyTaskList),
	lib_child:send_msg(Player#player_status.sid, 16505, [PackList]).

%% 领取任务经验
receive_daily_task_exp(Player, Sequence) ->
	#player_status{id = RoleId, sid = Sid, status_child = StatusChild} = Player,
	#status_child{daily_task = DailyTaskList, heart_reward = HeartReward, vote_times = VoteTimes} = StatusChild,
	case lists:keyfind(Sequence, #child_daily_task.sequence, DailyTaskList) of
		#child_daily_task{sequence = Sequence, task_state = TaskState} = DailyTask ->
			if
				TaskState == ?TASK_STATE_UNFINISH ->
					lib_child:send_error(Sid, ?ERRCODE(err165_child_task_unfinish)),
					{ok, Player};
				TaskState == ?TASK_STATE_FINISH ->
					AddExp = case data_child:get_child_daily_task_cfg(Sequence) of
						         #child_daily_task_cfg{reward_exp = TAddExp} -> TAddExp;
						         _ -> 0
					         end,
					NewStatusChild   = lib_child:do_upgrade_link_heart(StatusChild, AddExp),
					NewDailyTask     = DailyTask#child_daily_task{task_state = ?TASK_STATE_RECEIVE},
					NewDailyTaskList = lists:keystore(Sequence, #child_daily_task.sequence, DailyTaskList, NewDailyTask),
					F = fun() ->
						lib_child_util:save_db_child(RoleId, "", 0, 0, 0, 0,
							NewStatusChild#status_child.heart_link_exp, HeartReward, VoteTimes, 0, 0, 0, 0, 0, 0),
						lib_child_util:update_db_child_daily_task(RoleId, NewDailyTask),
						ok end,
					case catch db:transaction(F) of
						ok ->
							NewPlayer = lib_child_util:update_dict_child_daily_tasks(
								NewDailyTaskList, Player#player_status{status_child = NewStatusChild}
							),
							%% 日志
							lib_log_api:log_child_link_heart(RoleId, 1, Sequence, [], AddExp,
								StatusChild#status_child.heart_link_exp, NewStatusChild#status_child.heart_link_exp),
							lib_child:send_msg(Sid, 16506, [NewStatusChild#status_child.heart_link_exp]),
							lib_task_api:child_heart(NewPlayer,NewStatusChild#status_child.heart_link_exp),
							ta_agent_fire:child_heart(NewPlayer,
								["完成任务", Sequence, 0, AddExp, NewStatusChild#status_child.heart_link_exp]
							),
							{ok, NewPlayer};
						_Err -> lib_child:send_error(Sid, ?FAIL), {ok, Player}
					end;
				true ->
					lib_child:send_error(Sid, ?ERRCODE(err165_child_task_reward_has_received)),
					{ok, Player}
			end;
		_ ->
			lib_child:send_error(Sid, ?ERRCODE(err165_child_has_not_trigger_task)),
			{ok, Player}
	end.

%% 领取经验阶段奖励
receive_daily_task_reward(Player, RewardId) ->
	#player_status{id = RoleId, sid = Sid, status_child = StatusChild} = Player,
	#status_child{heart_link_exp = HeartLinkExp, heart_reward = HeartLinkReward} = StatusChild,
	CheckList = [{has_receive_reward, RewardId, HeartLinkReward}, {has_receive_pre, RewardId, HeartLinkReward}],
	case lib_child_util:check_task_reward(CheckList, Player) of
		{true, _Player1} ->
			case data_child:get_child_link_heart_cfg(RewardId) of
				#child_link_heart_cfg{need_exp = NeedExp, reward = Reward} ->
					case HeartLinkExp >= NeedExp of
						true ->
							%% 最后一个奖励配置为空(领养宝宝)
							MaxRewardId = data_child:get_max_reward(),
							case RewardId == MaxRewardId of
								true -> Player1 = Player;
								_ ->
									Product = #produce{reward = Reward, type = child_heart_link_reweard, remark = "child heart link reward"},
									{ok, Player1} = lib_goods_api:send_reward_with_mail(Player, Product, ?MOD_CHILD)
							end,
							NewHeartLinkReward = [{RewardId, 1}|HeartLinkReward],
							lib_child_util:update_db_child_link_heart_reward(RoleId, NewHeartLinkReward),
							NewStatusChild = StatusChild#status_child{heart_reward = NewHeartLinkReward},
							NewPlayer = Player1#player_status{status_child = NewStatusChild},
							lib_child:send_msg(Sid, 16539, [NewHeartLinkReward]),
							{ok, NewPlayer};
						_ ->
							lib_child:send_error(Sid, ?ERRCODE(err165_child_heart_link_exp_not_enough)),
							{ok, Player}
					end;
				_ ->
					% ?INFO_TTY("reward err------"),
					{ok, Player}
			end;
		{false, Err} ->
			lib_child:send_error(Sid, Err),
			{ok, Player}
	end.

quick_receive_task_reward(Player) ->
	#player_status{id = RoleId, sid = Sid, status_child = StatusChild} = Player,
	#status_child{heart_link_exp = HeartLinkExp, heart_reward = HeartLinkReward
		,child_sex = ChildSex
	} = StatusChild,
	AllReward =
	case HeartLinkReward of
		[{_, _}|_] -> [RRewardId||{RRewardId, _}<-HeartLinkReward];
		_ -> []
	end,
	CfgAllReward = data_child:get_all_reward(),
	NotReceiveReward = CfgAllReward -- AllReward,
	case NotReceiveReward of
		[_|_] ->
			%% 是否都满足领取条件
			CheckF = fun(RewardId, {Res, TRewardList}) ->
				case data_child:get_child_link_heart_cfg(RewardId) of
					#child_link_heart_cfg{need_exp = NeedExp, reward = Reward} ->
						case HeartLinkExp >= NeedExp of
							true -> {Res, TRewardList++Reward};
							_ -> {false, TRewardList}
						end;
					_ ->
						{false, TRewardList}
				end end,
			{
				CheckRes, RewardList
			} = lists:foldl(CheckF, {true, []}, NotReceiveReward),
			OpenDay = util:get_open_day(),
			CfgDay = case data_child:get_child_kv_cfg(receive_open) of
				         #child_constant_cfg{constant = TCfgDay} -> TCfgDay;
				         _ -> ?QUICK_RECEIVE_DEFAULT_DAY
			         end,
			CheckOpenDay = OpenDay >= CfgDay,
			CheckSex = ChildSex > 0,
			if
				not CheckRes ->
					lib_child:send_error(Sid, ?ERRCODE(err165_child_heart_link_exp_not_enough)),
					{ok, Player};
				not CheckOpenDay ->
					lib_child:send_error(Sid, ?ERRCODE(err165_not_receive_open_day)),
					{ok, Player};
				CheckSex ->
					lib_child:send_error(Sid, ?ERRCODE(err165_child_has_adopt)),
					{ok, Player};
				true ->
					%% 最后一个奖励可能为空
					case RewardList of
						[] -> Player1 = Player;
						_ ->
							Product = #produce{reward = RewardList, type = child_heart_link_reweard, remark = "child heart link reward"},
							{ok, Player1} = lib_goods_api:send_reward_with_mail(Player, Product, ?MOD_CHILD)
					end,
					F = fun(TRewardId, TList) ->
						[{TRewardId, 1} | TList]
						end,
					AddRewardStatus = lists:foldl(F, [], NotReceiveReward),
					NewHeartLinkReward = AddRewardStatus ++ HeartLinkReward,
					lib_child_util:update_db_child_link_heart_reward(RoleId, NewHeartLinkReward),
					NewStatusChild = StatusChild#status_child{heart_reward = NewHeartLinkReward},
					NewPlayer = Player1#player_status{status_child = NewStatusChild},
					lib_child:send_msg(Sid, 16539, [NewHeartLinkReward]),
					{ok, NewPlayer}
			end;
		_ ->
			lib_child:send_error(Sid, ?ERRCODE(err165_has_receive_all_reward)),
			{ok, Player}
	end.

%% ---------------------------- builtin_function ---------------------------------
trigger_task(Player, TaskType, DetailId, Num) ->
	%% 加人物角色等级判断
	case is_role_lv_enough(Player, TaskType) of
		true ->
			%% 如果已经领养孩子,不再触发任务
			case is_adopt_child(Player) of
				true -> {ok, Player};
				_ ->
					case has_finish(Player, TaskType, DetailId, Num) of
						true -> {ok, Player};
						_ ->
							event(Player, TaskType, DetailId, Num)
					end
			end;
		_ ->
			{ok, Player}
	end.

%% 事件处理
event(Player, TaskType, _DetailId, _Num)   %% 触发型任务
	when TaskType == ?TASK_TYPE_GROW_UP_CHILD orelse TaskType == ?TASK_TYPE_HUSONG orelse
	TaskType == ?TASK_TYPE_GUILD_NOON_BOSS orelse TaskType == ?TASK_TYPE_GUILD_NIGHT_BOSS
	orelse TaskType == ?TASK_TYPE_CHARM_BEACH ->
	#player_status{sid = Sid, status_child = #status_child{daily_task = DailyTaskList} = _StatusChild} = Player,
	case lists:keyfind(TaskType, #child_daily_task.sequence, DailyTaskList) of
		#child_daily_task{} = _DailyTask ->
			{ok, Player};
		_ ->
			Sequence = TaskType,
			DailyTask = #child_daily_task{
				sequence   = Sequence,
				progress   = 1,
				task_state = ?TASK_STATE_FINISH},
			NewDailyTaskList = lists:keystore(
				Sequence, #child_daily_task.sequence, DailyTaskList, DailyTask
			),
			NewPlayer = lib_child_util:update_dict_child_daily_tasks(NewDailyTaskList, Player),
			%% 写库
			lib_child_util:save_db_child_daily_task(Player#player_status.id, DailyTask),
			lib_child:send_msg(Sid, 16538, [Sequence, 1, ?TASK_STATE_FINISH]),
			{ok, NewPlayer}
	end;
event(Player, TaskType, _DetailId, Num)   %% 替换型任务
	when TaskType == ?TASK_TYPE_ADD_LIVENESS ->
	#player_status{sid = Sid, status_child = #status_child{daily_task = DailyTaskList} = _StatusChild} = Player,
	Sequence = TaskType,
	DailyTask =
	case lists:keyfind(TaskType, #child_daily_task.sequence, DailyTaskList) of
		#child_daily_task{} = TDailyTask ->
			TDailyTask;
		_ ->
			#child_daily_task{
				sequence   = TaskType
			}
	end,
	#child_daily_task_cfg{task_content = TaskContent} = data_child:get_child_daily_task_cfg(Sequence),
	case TaskContent of
		[_Content, _|_] ->  %% 特殊配置模式(预留接口)
			NewPlayer = Player;
		[{_, _DetailId, NeedNum}]  ->
			case Num >= NeedNum of
				true ->
					NewDailyTask = DailyTask#child_daily_task{
						progress   = min(Num, NeedNum),
						task_state = ?TASK_STATE_FINISH
					};
				_ ->
					NewDailyTask = DailyTask#child_daily_task{
						progress   = Num
					}
			end,
			NewDailyTaskList = lists:keystore(
				Sequence, #child_daily_task.sequence, DailyTaskList, NewDailyTask
			),
			NewPlayer = lib_child_util:update_dict_child_daily_tasks(NewDailyTaskList, Player),
			%% 写库
			lib_child_util:save_db_child_daily_task(Player#player_status.id, NewDailyTask),
			lib_child:send_msg(Sid, 16538, [Sequence, NewDailyTask#child_daily_task.progress, NewDailyTask#child_daily_task.task_state]);
		_ ->
			NewPlayer = Player
	end,
	{ok, NewPlayer};
event(Player, TaskType, DunId, Num) ->   %% 累加型任务
	#player_status{sid = Sid, status_child = #status_child{daily_task = DailyTaskList} = _StatusChild} = Player,
	case lists:keyfind(TaskType, #child_daily_task.sequence, DailyTaskList) of
		#child_daily_task{sequence = Sequence, progress = Progress} = DailyTask ->
			#child_daily_task_cfg{task_content = TaskContent} = data_child:get_child_daily_task_cfg(Sequence),
			case TaskContent of
				[_Content, _|_] ->  %% 特殊配置模式(预留接口)
					NewPlayer = Player;
				[{_, DetailId, NeedNum}]  ->
					case DetailId == DunId of
						true when Progress < NeedNum ->
							NewProgress = Progress + Num,
							case NewProgress >= NeedNum of
								true ->
									NewDailyTask = DailyTask#child_daily_task{
										progress   = min(NewProgress, NeedNum),
										task_state = ?TASK_STATE_FINISH
									};
								_ ->
									NewDailyTask = DailyTask#child_daily_task{
										progress   = NewProgress
									}
							end,
							%% 写库
							lib_child_util:update_db_child_daily_task(Player#player_status.id, NewDailyTask);
						true -> % 任务已经完成
							NewDailyTask = DailyTask;
						_ ->
							NewDailyTask = DailyTask
					end,
					NewDailyTaskList = lists:keystore(Sequence, #child_daily_task.sequence, DailyTaskList, NewDailyTask),
					NewPlayer = lib_child_util:update_dict_child_daily_tasks(NewDailyTaskList, Player),
					lib_child:send_msg(Sid, 16538, [Sequence, NewDailyTask#child_daily_task.progress, NewDailyTask#child_daily_task.task_state]);
				_ ->
					NewPlayer = Player
			end,
			{ok, NewPlayer};
		_ ->
			#child_daily_task_cfg{task_content = TaskContent} = data_child:get_child_daily_task_cfg(TaskType),
			case TaskContent of
				[_Content, _|_] ->  %% 特殊配置模式(预留接口)
					NewPlayer = Player;
				[{_, _DetailId, NeedNum}] ->
					DailyTask = #child_daily_task{
						sequence   = TaskType,
						detail_id  = [DunId],
						progress   = min(Num, NeedNum),
						task_state = ?IF(Num >= NeedNum, ?TASK_STATE_FINISH, ?TASK_STATE_UNFINISH)
					},
					NewDailyTaskList = lists:keystore(TaskType, #child_daily_task.sequence, DailyTaskList, DailyTask),
					NewPlayer = lib_child_util:update_dict_child_daily_tasks(NewDailyTaskList, Player),
					%% 写库
					lib_child_util:save_db_child_daily_task(Player#player_status.id, DailyTask),
					lib_child:send_msg(Sid, 16538, [TaskType, DailyTask#child_daily_task.progress, DailyTask#child_daily_task.task_state]);
				_ ->
					NewPlayer = Player
			end,
			{ok, NewPlayer}
	end.

%% 判断人物角色等级是否满足配置
is_role_lv_enough(Player, TaskType) ->
	#player_status{figure = Figure} = Player,
	#figure{lv = Lv} = Figure,
	case data_child:get_child_daily_task_cfg(TaskType) of
		#child_daily_task_cfg{open_level = OpenLv} ->
			case Lv >= OpenLv of
				true -> true;
				_    -> false
			end;
		_ ->
			false
	end.

%% 判断是否已经领养孩子
is_adopt_child(Player) ->
	#player_status{status_child = StatusChild} = Player,
	#status_child{child_sex = ChildSex}  = StatusChild,
	case ChildSex > 0 of
		true -> true;
		_ -> false
	end.

%% 判断任务是否已经完成
has_finish(Player, TaskType, _DetailId, _Num) ->
	#player_status{status_child = StatusChild} = Player,
	#status_child{daily_task = DailyTaskList}  = StatusChild,
	case lists:keyfind(TaskType, #child_daily_task.sequence, DailyTaskList) of
		#child_daily_task{task_state = TaskState} ->
			case TaskState >= ?TASK_STATE_FINISH of
				true -> true;
				_    -> false
			end;
		_ ->
			false
	end.

%% 获取任务序列号
get_sequence(TriggerType, DetailId) ->
	SeqIds = data_child:get_all_child_daily_task_cfg(),
	F = fun(SeqId, TSeqList) ->
		case data_child:get_child_daily_task_cfg(SeqId) of
			#child_daily_task_cfg{
				task_id      = SeqId,
				task_content = Content
			} ->
				case lists:keyfind(TriggerType, 1, Content) of
					{TriggerType, DetailId, _} ->
						case Content of
							[_, _|_] ->  %% 特殊定制[{finish_dun, 1001, 1}, {finish_dun, 1002, 1}..]格式
								case lists:keyfind(DetailId, 2, Content) of
									{TriggerType, DetailId, _} ->
										[SeqId|TSeqList];
									_ -> TSeqList
								end;
							_ ->
								[SeqId|TSeqList]
						end;
					_  -> TSeqList
				end;
			_ ->
				TSeqList
		end
	end,
	case lists:foldl(F, [], SeqIds) of
		[Sequence|_] ->  Sequence;
		_ -> 0
	end.
