%%%-------------------------------------------------------------------
%%% @doc
%%%     惊喜红包
%%% @end
%%% @author tyl
%%% Created : 2020-10-27
%%%-------------------------------------------------------------------
-module(surprise_red_packet).

-include("custom_act.hrl").
-include("common.hrl").
-include("server.hrl").
-include("figure.hrl").
-include("errcode.hrl").
-include("goods.hrl").
-include("def_goods.hrl").
-include("red_packet.hrl").
-include("def_event.hrl").
-include("rec_event.hrl").

%% API
-export([
	handle_event/2
	,send_red_packet_info/3     %% 基础信息
	,draw_red_packet/2          %% 抽取红包
	,receive_red_packet/2       %% 领取红包
	,receive_box/2              %% 领取宝箱
	,send_red_packet_log/3      %% 全服记录
]).


%% ---------------------------------------------------------------------------
%% @doc 处理充值事件 @end
%% ---------------------------------------------------------------------------
handle_event(Player, #event_callback{type_id = ?EVENT_RECHARGE}) ->
	case lib_custom_act_util:get_open_subtype_list(?CUSTOM_ACT_TYPE_SUP_RED_PACKET) of
		[] ->
			{ok, Player};
		OpenActList ->
			send_red_packet_info1(Player, OpenActList),
			{ok, Player}
	end;
handle_event(Role, _) ->
	{ok, Role}.

%% ---------------------------------------------------------------------------
%% @doc 发送惊喜红包活动信息 @end
%% ---------------------------------------------------------------------------
send_red_packet_info1(_Player, []) ->
	ok;
send_red_packet_info1(Player, [Info | T]) ->
	#act_info{key = {Type, SubType}} = Info,
	send_red_packet_info(Player, Type, SubType),
	send_red_packet_info1(Player, T).

send_red_packet_info(Player, Type, SubType) ->
	{AwardId, DrawTimes, CanReceive, GoldNum, BoxReceived} =
		case lib_custom_act_api:is_open_act(Type, SubType) of
		    true -> pack_act_info(Player, Type, SubType);
		    false -> {0, 0, 0, 0, 0}
	    end,
	lib_server_send:send_to_sid(Player#player_status.sid, pt_332, 33250,
		[SubType, AwardId, DrawTimes, CanReceive, GoldNum, BoxReceived]),
	ok.

pack_act_info(Player, Type = ?CUSTOM_ACT_TYPE_SUP_RED_PACKET, SubType) ->
	RedPacketData = red_packet_data(Type, SubType),
	case lib_custom_act_util:keyfind_act_condition(Type, SubType, draw_pool) of
		{draw_pool, PoolId} ->
			ActInfo = lib_custom_act_util:get_custom_act_open_info(Type, SubType),
			#act_info{stime = StartTime, etime = EndTime} = ActInfo,
			#player_status{id = RoleId} = Player,
			%% 活动期间的充值金额
			Recharge = lib_recharge_data:get_my_recharge_between(
				RoleId, StartTime, EndTime
			),
			AwardList = data_sup_red_packet:get_reward_list(PoolId),
			#sup_red_packet{draw_times = DrawTimes, draw_id = DrawId
				,grade = Grade, box_received = BoxReceived} = RedPacketData,
			ShowAwardId = case DrawTimes of
				              0 ->
					              case AwardList of
						              [ShowId | _] -> ShowId;
						              _ -> 0
					              end;
				              _ ->
					              MaxAwardId = case DrawId > 0 of
												   true ->
													   DrawId;
												   _ ->
													   case AwardList of
														   [ShowId | _] -> ShowId;
														   _ -> 0
													   end
					                           end,
					              CfgMaxAwardId = lists:max(AwardList),
					              case Grade > 0 of
									  true -> MaxAwardId;
									  _ -> min(MaxAwardId + 1, CfgMaxAwardId)
					              end
			              end,
			case Grade > 0 of
				true -> CanReceive = 1;
				_    -> CanReceive = 0
			end,
			{ShowAwardId, DrawTimes, CanReceive, Recharge, BoxReceived};
		_ ->
			{0, 0, 0, 0, 0}
	end;
pack_act_info(_, _Type, _SubType) ->
	{0, 0, 0, 0, 0}.

%% ---------------------------------------------------------------------------
%% @doc 抽取红包 @end
%% ---------------------------------------------------------------------------
draw_red_packet(Player, SubType) ->
	Type = ?CUSTOM_ACT_TYPE_SUP_RED_PACKET,
	IsOpen = lib_custom_act_api:is_open_act(Type, SubType),
	RedPackData = red_packet_data(Type, SubType),
	#sup_red_packet{draw_times = DrawTimes, draw_id = DrawId, grade = Grade} = RedPackData,
	PoolId = case lib_custom_act_util:keyfind_act_condition(Type, SubType, draw_pool) of
		         {draw_pool, TPoolId} -> TPoolId;
		         _ -> 0
	         end,
	CfgAwardList  = data_sup_red_packet:get_reward_list(PoolId),
	CfgMaxAwardId = lists:max(CfgAwardList),
	AwardId = get_award_id(CfgAwardList, DrawTimes, DrawId, Grade),
	AwardConfig = data_sup_red_packet:get_red_packet(AwardId),
	if
		IsOpen =:= false ->
			lib_server_send:send_to_sid(Player#player_status.sid, pt_332, 33251,
				[?ERRCODE(err331_act_closed), SubType, AwardId, 0]
			),
			{ok, Player};
		AwardId > CfgMaxAwardId ->
			lib_server_send:send_to_sid(Player#player_status.sid, pt_332, 33251,
				[?ERRCODE(err331_red_packet_all_receive), SubType, AwardId, 0]
			),
			{ok, Player};
		not is_record(AwardConfig, base_sup_red_packet) ->
			lib_server_send:send_to_sid(Player#player_status.sid, pt_332, 33251,
				[?ERRCODE(err331_red_packet_cfg_err), SubType, AwardId, 0]
			),
			{ok, Player};
		AwardConfig#base_sup_red_packet.draw_pool =/= PoolId ->
			lib_server_send:send_to_sid(Player#player_status.sid, pt_332, 33251,
				[?ERRCODE(err331_red_packet_cfg_err), SubType, AwardId, 0]
			),
			{ok, Player};
		true ->
			ActInfo = lib_custom_act_util:get_custom_act_open_info(Type, SubType),
			#act_info{stime = StartTime, etime = EndTime} = ActInfo,
			#player_status{id = RoleId} = Player,
			Recharge = lib_recharge_data:get_my_recharge_between(
				RoleId, StartTime, EndTime
			),
			RedPacketData = red_packet_data(Type, SubType),
			case do_draw_red_packet(RedPacketData, AwardId, Recharge) of
				{true, AwardType, RedPacketData1} ->
					lib_server_send:send_to_sid(Player#player_status.sid, pt_332, 33251,
						[?SUCCESS, SubType, AwardId, AwardType]
					);
				%% 这里包括第一次抽取
				{false, ErrorCode1, RedPacketData1} ->
					lib_server_send:send_to_sid(Player#player_status.sid, pt_332, 33251,
						[ErrorCode1, SubType, AwardId, 0]
					)
			end,
			ActData = #custom_act_data{
				type = Type, subtype = SubType, act_data = RedPacketData1,
				time = utime:unixtime()
			},
			lib_custom_act_data:save_custom_data(RoleId, ActData),
			{ok, Player}
	end.

%% 本次抽奖的奖励Id
get_award_id(CfgAwardList, DrawTimes, DrawId, _Grade) ->
	FirstShowId = case CfgAwardList of
		              [ShowId | _] -> ShowId;
		              _ -> 0
	              end,
	MaxAwardId = case DrawId > 0 of
		             true ->
			             DrawId;
		             _ ->
			             FirstShowId
	             end,
	AwardId = case DrawTimes =< 0 of
				  true -> MaxAwardId;
				  _ ->
					  MaxAwardId + 1
	          end,
	AwardId.

do_draw_red_packet(RedPacketData, AwardId, Recharge) ->
	#sup_red_packet{draw_times = DrawTimes, grade = Grade
	} = RedPacketData,
	case DrawTimes of
		% 未抽取过,第一次抽取
		0 ->
			case Grade > 0 of
				true -> %% 理论上这种情况不会发生
					{false, ?ERRCODE(err331_red_packet_err), RedPacketData};
				_ ->
					RewardList = get_reward_money(AwardId),
					{Type, _RewardGold} = urand:rand_with_weight(RewardList),
					NewRedPacketData = RedPacketData#sup_red_packet{
						draw_times = 1, grade = Type, draw_id = AwardId},
					{true, Type, NewRedPacketData}
			end;
		_ ->
			% 未领奖
			case Grade > 0 of
				true ->
					{false, ?ERRCODE(err331_last_reward), RedPacketData};
				_ ->
					do_draw_core(RedPacketData, AwardId, Recharge)
			end
	end.

do_draw_core(RedPacketData, AwardId, Recharge) ->
	#sup_red_packet{draw_times = DrawTimes} = RedPacketData,
	case check_draw(AwardId, Recharge, RedPacketData) of
		{false, ErrorCode} ->
			NewRedPacketData = RedPacketData,
			{false, ErrorCode, NewRedPacketData};
		_ ->
			RewardList = get_reward_money(AwardId),
			{Type, _RewardGold} = urand:rand_with_weight(RewardList),
			NewRedPacketData = RedPacketData#sup_red_packet{
				draw_times = DrawTimes + 1, grade = Type, draw_id = AwardId
			},
			{true, Type, NewRedPacketData}
	end.

%% ---------------------------------------------------------------------------
%% @doc 领取红包 @end
%% ---------------------------------------------------------------------------
receive_red_packet(Player, SubType) ->
	Type = ?CUSTOM_ACT_TYPE_SUP_RED_PACKET,
	IsOpen = lib_custom_act_api:is_open_act(Type, SubType),
	RedPackData = red_packet_data(Type, SubType),
	#sup_red_packet{grade = Grade, draw_id = DrawId} = RedPackData,
	PoolId = case lib_custom_act_util:keyfind_act_condition(Type, SubType, draw_pool) of
		         {draw_pool, TPoolId} -> TPoolId;
		         _ -> 0
	         end,
	AwardList = data_sup_red_packet:get_reward_list(PoolId),
	case DrawId > 0 of
		true -> AwardId = DrawId;
		_ ->
			case AwardList of
				[AwardId|_] -> ok;
				_ -> AwardId = 0
			end
	end,
	AwardConfig = data_sup_red_packet:get_red_packet(AwardId),
	if
		IsOpen =:= false ->
			lib_server_send:send_to_sid(Player#player_status.sid, pt_332, 33252,
				[?ERRCODE(err331_act_closed), SubType, AwardId, 0]
			),
			{ok, Player};
		not is_record(AwardConfig, base_sup_red_packet) ->
			lib_server_send:send_to_sid(Player#player_status.sid, pt_332, 33252,
				[?ERRCODE(err331_red_packet_cfg_err), SubType, AwardId, 0]
			),
			{ok, Player};
		true ->
			case Grade > 0 of
				true ->
					%% 检查充值是否满足
					ActInfo = lib_custom_act_util:get_custom_act_open_info(Type, SubType),
					#act_info{stime = StartTime, etime = EndTime} = ActInfo,
					#player_status{id = RoleId} = Player,
					Recharge = lib_recharge_data:get_my_recharge_between(
						RoleId, StartTime, EndTime
					),
					case check_draw(AwardId, Recharge, RedPackData) of
						{false, ErrorCode} ->
							lib_server_send:send_to_sid(Player#player_status.sid, pt_332, 33252,
								[ErrorCode, SubType, AwardId, 0]
							),
							{ok, Player};
						_ ->
							GetMoney = get_grade_money(Grade, AwardConfig),
							MoneyList = [{?TYPE_GOLD, 0, GetMoney}],
							About = io_lib:format("~w,~w,~w", [SubType, AwardId, Grade]),
							Produce = #produce{
								type = red_packet, subtype = Type, reward = MoneyList
								,remark = About
							},
							Player1 = lib_goods_api:send_reward(Player, Produce),
							NewRedPackData = RedPackData#sup_red_packet{grade = 0, draw_id = AwardId},
							Now = utime:unixtime(),
							ActData = #custom_act_data{
								type = Type, subtype = SubType, act_data = NewRedPackData,
								time = Now
							},
							lib_custom_act_data:save_custom_data(RoleId, ActData),
							%% 全服记录
							#player_status{id = RoleId, figure = #figure{name = RoleName}} = Player1,
							Log = [{RoleId, RoleName, AwardId, Grade, GetMoney, Now}],
							Grade >= 2 andalso mod_custom_act_log:cast({red_packet_log, Type, SubType, Log}),
							lib_server_send:send_to_sid(Player#player_status.sid, pt_332, 33252,
								[?SUCCESS, SubType, AwardId, Grade]
							),
							%% 求到上档以上发传闻
							send_tv(Grade, MoneyList, RoleId, RoleName),
							log_send_goods(Player1, Player, Type, SubType, "receive_red_packet", MoneyList),
							{ok, Player1}
					end;
				_ ->
					lib_server_send:send_to_sid(Player#player_status.sid, pt_332, 33252,
						[?ERRCODE(err331_red_packet_not_receive), SubType, AwardId, 0]
					),
					{ok, Player}
			end
	end.

%% ---------------------------------------------------------------------------
%% @doc 全服记录 @end
%% ---------------------------------------------------------------------------
send_red_packet_log(SubType, LogList, Sid) ->
	F = fun(LogInfo, AccL) ->
		case LogInfo of
			[{_RoleId, _RoleName, _AwardId, _Grade, _GetMoney, _Time} = Info] ->
				[Info|AccL];
			_ ->
				AccL
		end end,
	PackList = lists:foldl(F, [], LogList),
	lib_server_send:send_to_sid(Sid, pt_332, 33253,
		[SubType, PackList]
	),
	ok.

%% ---------------------------------------------------------------------------
%% @doc 宝箱领取 @end
%% ---------------------------------------------------------------------------
receive_box(Player, SubType) ->
	Type = ?CUSTOM_ACT_TYPE_SUP_RED_PACKET,
	IsOpen = lib_custom_act_api:is_open_act(Type, SubType),
	RedPackData = red_packet_data(Type, SubType),
	#sup_red_packet{box_received = BoxReceived
		,draw_times = DrawTimes} = RedPackData,
	BoxReward = case lib_custom_act_util:keyfind_act_condition(Type, SubType, extra_reward) of
		            {extra_reward, TBoxReward} -> TBoxReward;
		            _ -> []
	            end,
	if
		IsOpen =:= false ->
			lib_server_send:send_to_sid(Player#player_status.sid, pt_332, 33254,
				[?ERRCODE(err331_act_closed), SubType]
			),
			{ok, Player};
		DrawTimes =< 0 ->
			lib_server_send:send_to_sid(Player#player_status.sid, pt_332, 33254,
				[?ERRCODE(err331_box_need_draw_first), SubType]
			),
			{ok, Player};
		BoxReceived >= 1 ->
			lib_server_send:send_to_sid(Player#player_status.sid, pt_332, 33254,
				[?ERRCODE(err331_box_has_received), SubType]
			),
			{ok, Player};
		BoxReward == [] ->
			lib_server_send:send_to_sid(Player#player_status.sid, pt_332, 33254,
				[?ERRCODE(err331_box_cfg_err), SubType]
			),
			{ok, Player};
		true ->
			case BoxReward of
				{_, _, _} -> BoxReward1 = [BoxReward];
				[_|_] -> BoxReward1 = BoxReward;
				_ -> BoxReward1 = []
			end,
			NewRedPackData = RedPackData#sup_red_packet{box_received = 1},
			ActData = #custom_act_data{
				type = Type, subtype = SubType, act_data = NewRedPackData,
				time = utime:unixtime()
			},
			Produce = #produce{
				type = red_packet, subtype = Type, reward = BoxReward1
			},
			lib_custom_act_data:save_custom_data(Player#player_status.id, ActData),
			Player1 = lib_goods_api:send_reward(Player, Produce),
			lib_server_send:send_to_sid(Player#player_status.sid, pt_332, 33254,
				[?SUCCESS, SubType]  %% 配置错误
			),
			log_send_goods(Player1, Player, Type, SubType, "receive_box", BoxReward1),
			{ok, Player1}
	end.


%% ------------------------ builtin_function -----------------------------------
red_packet_data(Type, SubType) ->
	#custom_act_data{
		act_data = ActData
	} = lib_custom_act_data:custom_act_data(Type, SubType),
	case ActData of
		#sup_red_packet{} -> ActData;
		_ -> #sup_red_packet{}
	end.

%% 是否达到抽取奖励条件
check_draw(AwardId, Recharge, _RedPacketData) ->
	case data_sup_red_packet:get_red_packet(AwardId) of
		#base_sup_red_packet{
			recharge_gold = NeedGold
		} ->
			case Recharge >= NeedGold of
				true -> true;
				_    -> {false, ?ERRCODE(err331_recharge_not_enough)}
			end;
		_ ->
			{false, ?ERRCODE(err331_red_packet_cfg_err)}
	end.

send_tv(AwardType, AwardList, RoleId, RoleName) ->
	case AwardType >= 2 of
		true ->
			AwardNum = case AwardList of
				           [{_AwardType, _GId, GNum} | _] -> GNum;
				           _ -> 0
			           end,
			TvData = [RoleName, RoleId, AwardNum],
			SubTvType = 29 + max(0, AwardType-2),
			lib_chat:send_TV(all, 331, SubTvType, TvData);
		_ ->
			ok
	end.

get_reward_money(AwardId) ->
	case data_sup_red_packet:get_red_packet(AwardId) of
		#base_sup_red_packet{
			mid_draw = MidDraw, up_draw = UpDraw
			,dream_draw = DreamDraw
		} when is_tuple(MidDraw), is_tuple(UpDraw), is_tuple(DreamDraw) ->
			[{Weight, {Type, Money}}||{Type, Money, Weight}<-[MidDraw, UpDraw, DreamDraw]];
		_ ->
			[]
	end.

get_grade_money(GradeId, AwardCfg) ->
	#base_sup_red_packet{
		mid_draw = MidDraw, up_draw = UpDraw
		,dream_draw = DreamDraw
	} =AwardCfg,
	case GradeId of
		1 -> {_, Money, _} = MidDraw;
		2 -> {_, Money, _} = UpDraw;
		3 -> {_, Money, _} = DreamDraw;
		_ -> Money = 0
	end,
	Money.

%% 记录日志
log_send_goods(NewPlayer, Player, Type, SubType, RewardType, Reward) ->
	#player_status{id = RoleId, figure = Figure, gold = Gold, bgold = BGold} = Player,
	#player_status{gold = NewGold, bgold = NewBGold} = NewPlayer,
	#figure{vip = Vip, lv = Lv} = Figure,
	WorldLv = util:get_world_lv(),
	lib_log_api:log_custom_act_reward(RoleId, Type, SubType, 0, WorldLv,
		Reward, RewardType, Vip, Lv, Gold, NewGold, BGold, NewBGold, utime:unixtime()
	),
	ok.