%%%-------------------------------------------------------------------
%%% @doc     藏宝图 - 高级藏宝图
%%% Module  : lib_treasure_map_advance.erl
%%% Created : 2021-02-23
%%% @author : tyl
%%%-------------------------------------------------------------------
-module(lib_treasure_map_advance).

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


%% API
-export([
	login_init/2
	,get_advanced_map/1                 %% 获取高级藏宝图奖励信息
	,send_treasure_map_tv/1
	,receive_advanced_map_reward/1      %% 领取高级藏宝图轮盘奖励
	,receive_monthly_reward/2           %% 领取月次数奖励
	,player_clean/1                     %% 月度奖励结算，清理在线玩家进程数据

	,db_save_monthly_times/3
	,db_select_monthly_times/0
	,db_select_monthly_times_by_id/1
	,db_delete_monthly_times/0
]).

%% 月度抽奖次数存在数据库中
%% 每日抽奖次数存在计数器中
%% 登录加载月度次数

-define(ADVANCE_TREASURE_MAP_TV, advance_treasure_map_tv).

login_init(RoleId, DataMap) ->
	case lib_treasure_map_advance:db_select_monthly_times_by_id(RoleId) of
		[Times] ->
			AdvancedMap = #advanced_map{times = Times},
			maps:put(?ADVANCE_TREASURE, AdvancedMap, DataMap);
		_ ->
			DataMap
	end.

%% 使用高级宝图,获取相关奖励
get_advanced_map(Player) ->
	#player_status{role_treasure_map = RoleTreasureMap, sid = Sid, figure = Figure} = Player,
	#role_treasure_map{map = DataMap} = RoleTreasureMap,
	#figure{lv = RoleLv, vip = Vip} = Figure,
	AdvancedMap = maps:get(?ADVANCE_TREASURE, DataMap, #advanced_map{}),
	#advanced_map{times = Times, rewards = OldRewards} = AdvancedMap,
	%% 上次挖宝还未完成，禁止进行下一次
	case OldRewards =/= [] of
		true ->
			lib_server_send:send_to_sid(Sid, pt_424, 42402,
				[?ERRCODE(err424_last_not_finish), ?ADVANCE_TREASURE, 0, 0, []]
			),
			{Player, 0, []};
		_ ->
			NewTimes = Times + 1,
			AddWeight = calc_weight_add(NewTimes),
			case lib_treasure_map:calc_treasure_rewards(
				?ADVANCE_TREASURE, RoleLv, Vip, AddWeight)
			of
				{ShowRewardIds, RewardId, TvType} when RewardId > 0 ->
					GetReward = fetch_reward(RewardId),
					NewAdvancedMap = AdvancedMap#advanced_map{
						reward_id = RewardId, rewards = GetReward, tv_type = TvType
					},
					NewDataMap = maps:put(?ADVANCE_TREASURE, NewAdvancedMap, DataMap),
					NewRoleTreasureMap = RoleTreasureMap#role_treasure_map{
						type = ?ADVANCE_TREASURE,
						time = utime:unixtime(), map = NewDataMap
					},
					NewPlayer = Player#player_status{
						role_treasure_map = NewRoleTreasureMap},

					{NewPlayer, RewardId, ShowRewardIds};
				_ ->
					lib_server_send:send_to_sid(Sid, pt_424, 42402,
						[?ERRCODE(err424_reward_err), ?ADVANCE_TREASURE, 0, 0, []]
					),
					{Player, 0, []}
			end
	end.

fetch_reward(RewardId) ->
	case data_treasure_map:get_reward(RewardId) of
		#base_treasure_map_rewards{rewards = Rewards} -> ok;
		_ -> Rewards = []
	end,
	Rewards.

%% 触发领取奖励(消耗物品已经在外部接口统一处理)
receive_advanced_map_reward(Player) ->
	#player_status{role_treasure_map = RoleTreasureMap, id = RoleId} = Player,
	#role_treasure_map{type = Type, map = DataMap} = RoleTreasureMap,
	case Type of
		?ADVANCE_TREASURE ->
			AdvancedMap = maps:get(?ADVANCE_TREASURE, DataMap, #advanced_map{}),
			#advanced_map{rewards = Rewards, tv_type = TvType, times = Times} = AdvancedMap,
			Produce = #produce{type = treasure_map, reward = Rewards},
			NewTimes = Times + 1,
			NewAdvanceMap = #advanced_map{times = NewTimes},
			NewRoleTreasureMap = RoleTreasureMap#role_treasure_map{
				map = maps:put(?ADVANCE_TREASURE, NewAdvanceMap, DataMap)
			},
			%% 直接发放奖励，前端屏蔽进包动画，转盘结束后再弹传闻
			{ok, RewardPlayer} = lib_goods_api:send_reward_with_mail(
				Player#player_status{role_treasure_map = NewRoleTreasureMap},
				Produce, ?MOD_TREASURE_MAP
			),
			mod_treasure_map_advance:update_times(RoleId, NewTimes),

			%% 传闻延迟发送
			TvTuple = {TvType, Rewards},
			proc_put_tv_list(TvTuple),
			DelayTime = data_treasure_map:get_kv(advanced_map_speed),
			util:send_after([], DelayTime*1000, self(), {'mod', ?MODULE, send_treasure_map_tv, []}),

			{ok, RewardPlayer};
		_ ->
			{false, ?ERRCODE(err424_type_err)}
	end.

%% 延迟推送大奖传闻
send_treasure_map_tv(Player) ->
	#player_status{figure = Figure, server_num = ServerNum} = Player,
	TvShowTuple = proc_get_tv_list(),
	case TvShowTuple of
		{TvType, Rewards} ->
			notice_tv(Figure, ServerNum, TvType, Rewards),
			proc_put_tv_list({});
		_ ->
			ignore
	end,
	{ok, Player}.

notice_tv(Figure, ServerNum, TvType, Rewards) ->
	%% 传闻
	case Rewards of
		[{_, RewardId, Num}|_] -> ok;
		_ -> RewardId = 0, Num = 0
	end,
	[Id, BroRang, Msg] = case TvType of
		                     1 -> [2, {all}, [Figure#figure.name, RewardId, Num]];
		                     2 -> [3, {cluster}, [ServerNum, Figure#figure.name, RewardId, Num]];
		                     _ -> [0, none, []]
	                     end,
	BroRang =/= none andalso lib_chat:send_TV(BroRang, 424, Id, Msg).

%% 领取月度次数奖励
receive_monthly_reward(Player, ReceiveTimes) ->
	#player_status{role_treasure_map = RoleTreasureMap, id = RoleId, sid = Sid} = Player,
	#role_treasure_map{map = DataMap} = RoleTreasureMap,
	AdvancedMap = maps:get(?ADVANCE_TREASURE, DataMap, #advanced_map{}),
	#advanced_map{times = MyTimes} = AdvancedMap,
	TimeRewards = data_treasure_map:get_kv(advanced_map_times_reward),
	case TimeRewards of
		[{_, _, _}|_] ->
			TimesList = [Times||{Times, _, _}<-TimeRewards],
			MinTimes  = lists:min(TimesList),
			case lists:member(ReceiveTimes, TimesList) of
				true when MyTimes >= MinTimes ->
					case MyTimes >= ReceiveTimes of
						true ->
							mod_treasure_map_advance:receive_monthly_reward(
								RoleId, ReceiveTimes),
							ok;
						_ ->
							lib_server_send:send_to_sid(Sid, pt_424, 42406,
								[?ERRCODE(err424_cannot_receive), []]
							),
							ok
					end;
				_ ->
					lib_server_send:send_to_sid(Sid, pt_424, 42406,
						[?ERRCODE(err424_not_reward_can_receive), []]
					),
					ok
			end;
		_ ->
			lib_server_send:send_to_sid(Sid, pt_424, 42406,
				[?ERRCODE(err424_times_reward_err), []]
			),
			ok
	end.

%% 月度奖励结算，清理在线玩家进程数据
player_clean(Player) ->
	#player_status{role_treasure_map = RoleTreasureMap, sid = Sid} = Player,
	#role_treasure_map{map = DataMap} = RoleTreasureMap,
	NewDataMap = maps:put(?ADVANCE_TREASURE, #advanced_map{}, DataMap),
	NewRoleTreasureMap = RoleTreasureMap#role_treasure_map{map = NewDataMap},
	lib_server_send:send_to_sid(Sid, pt_424, 42405, [0, []]),
	Player#player_status{role_treasure_map = NewRoleTreasureMap}.

%% --------------------------- builtin func --------------------------------
calc_weight_add(NewTimes) ->
	ConfigTimesList = data_treasure_map:get_kv(advanced_map_times),
	case proplists:get_value(NewTimes, ConfigTimesList, 0) of
		AddWeight when is_integer(AddWeight) -> AddWeight;
		_ -> 0
	end.

%% -------------------------------------------------------------------
%% 玩家进程 大奖奖励传闻
proc_get_tv_list() ->
	TvKey = ?ADVANCE_TREASURE_MAP_TV,
	case get(TvKey) of
		TvTuple when is_tuple(TvTuple) -> ok;
		_ -> TvTuple = {}
	end,
	TvTuple.

proc_put_tv_list(TvTuple) when is_tuple(TvTuple) ->
	TvKey = ?ADVANCE_TREASURE_MAP_TV,
	put(TvKey, TvTuple);
proc_put_tv_list(_List) ->
	error.

%% -------------------------------------------------------------------

db_save_monthly_times(RoleId, Times, ReceiveList) ->
	db:execute(
		io_lib:format(<<"replace into treasure_map_montly_times (`role_id`, `times`, `receive_list`) values (~p,~p,'~ts')">>,
			[RoleId, Times, util:term_to_string(ReceiveList)])
	),
	ok.

db_select_monthly_times() ->
	db:get_all(io_lib:format(<<"select `role_id`, `times`, `receive_list` from treasure_map_montly_times">>, [])).

db_select_monthly_times_by_id(RoleId) ->
	db:get_row(io_lib:format(<<"select `times` from treasure_map_montly_times where `role_id`=~p">>, [RoleId])).

db_delete_monthly_times() ->
	db:execute(io_lib:format(<<"truncate table treasure_map_montly_times">>, [])),
	ok.