%%%-------------------------------------------------------------------
%%% @doc    扭蛋逻辑模块
%%% Module  : lib_capsule_egg.erl
%%% Created : 2020-06-24
%%% @Author : tyl
%%%-------------------------------------------------------------------
-module(lib_capsule_egg).

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


%% API
-export([
	send_msg/3
	,login/1                         %% 登录

	,get_capsule_egg_info/2          %% 查询扭蛋库抽奖信息
	,draw_capsule_egg/5              %% 抽奖
	,send_score_store_goods/1        %% 查询积分商城商品列表
	,exchange_goods/2                %% 积分商城商品兑换
	,send_times_reward_info/2        %% 次数奖励信息
	,receive_times_reward/3          %% 领取次数奖励
	,weekly_refresh/0                %% 每7天刷新次数奖励
	,do_refresh_player/1

	%% 数据库操作
	,save_db_person_score/2
	,save_db_capsule_egg/6
	,update_db_capsule_egg/4
	,save_db_server_score/3
	,get_db_server_score/0
	,save_db_top_server_score/2
	,get_db_top_server_score/0
	,save_db_draw_log/5
	,get_db_draw_log/2
	,get_db_top_draw_log/2
	,get_db_player_name/1
	,tran_format/2
]).


%% 登录
login(Player) ->
	#player_status{id = RoleId} = Player,
	CapsuleEggMap =
	case get_db_capsule_egg(RoleId) of
		[_|_] = InfoList ->
			make_capsule_egg_map(InfoList, #{}, RoleId);
		_ ->
			init_capsule_egg_map(?POOL_TYPE_LIST, #{})
	end,
	Score =
	case get_db_person_score(RoleId) of
		[PersonScore] -> PersonScore;
		_ -> 0
	end,
	StatusCapsuleEgg =
	#status_capsule_egg{
		capsule_egg_map = CapsuleEggMap,
		score = Score
	},
	Player#player_status{capsule_egg = StatusCapsuleEgg}.

%% 查询扭蛋库抽奖信息
get_capsule_egg_info(Player, PoolType) ->
	#player_status{capsule_egg = StatusCapsuleEgg, sid = Sid} = Player,
	#status_capsule_egg{capsule_egg_map = CapsuleEggMap} = StatusCapsuleEgg,
	case maps:get(PoolType, CapsuleEggMap, []) of
		#capsule_egg_data{next_free_time = NextTime, draw_times = DrawTimes} ->
			NowTime = utime:unixtime(),
			FreeTimes =
			case NowTime >= NextTime of
				true -> 1;
				_ -> 0
			end,
			Msg = [PoolType, FreeTimes, NextTime, DrawTimes],
			send_msg(Sid, 17000, Msg),
			{ok, Player};
		_ ->
			Msg = [PoolType, 1, 0, 0],
			send_msg(Sid, 17000, Msg),
			{ok, Player}
	end.

%% 抽奖
draw_capsule_egg(Player, PoolType, DrawTimes, _IsFree, AddBuff) ->
	#player_status{capsule_egg = StatusCapsuleEgg, sid = Sid} = Player,
	#status_capsule_egg{capsule_egg_map = CapsuleEggMap} = StatusCapsuleEgg,
	NowTime = utime:unixtime(),
	CheckList = [{pool_type_true, PoolType}, {draw_times_true, DrawTimes},
		{check_data, CapsuleEggMap, PoolType}
		% {money_enough, Player, PoolType, DrawTimes, NowTime}% , {bag_size}
	],
	case check_list(CheckList) of
		true ->
			case do_draw_capsule_egg(Player, PoolType, DrawTimes, NowTime, AddBuff) of
				{true, Player1} ->
					{ok, Player1};
				{false, Err} ->
					send_msg(Sid, 17003, [Err, 0, 0, 0, [], 0]),
					{ok, Player}
			end;
		{false, Res} ->
			send_msg(Sid, 17003, [Res, 0, 0, 0, [], 0]),
			{ok, Player}
	end.

%% 查询积分商城商品列表
send_score_store_goods(Player) ->
	#player_status{id = RoleId, sid = Sid} = Player,
	OrderList = data_capsule_egg:get_capsule_egg_exchange_list_cfg(),
	F = fun(Order, GoodsList) ->
		case data_capsule_egg:get_capsule_egg_exchange_cfg(Order) of
			#capsule_egg_exchange_cfg{
				reward          = [{_, GoodTypeId, _Num}]
				,limit_type     = LimitType
				,exchange_times = ExchangeLim
			} ->
				ExchangeCounts = get_exchange_counts(RoleId, GoodTypeId, LimitType),
				Num = ?IF((ExchangeLim > 0 andalso ExchangeLim > ExchangeCounts), ExchangeLim - ExchangeCounts, 0),
				[{Order, GoodTypeId, LimitType, Num}|GoodsList];
			_ ->
				GoodsList
		end end,
	SendGoodsList = lists:foldl(F, [], OrderList),
	send_msg(Sid, 17005, [SendGoodsList]).

%% 积分商城商品兑换
exchange_goods(Player, Pos) ->
	#player_status{id = RoleId, sid = Sid, capsule_egg = StatusCapsuleEgg} = Player,
	case data_capsule_egg:get_capsule_egg_exchange_cfg(Pos) of
		#capsule_egg_exchange_cfg{
			cost_score = CostScore
			,reward = GiveGoods = [{_, GoodTypeId, _GNum}]
			,limit_type = LimType
			,exchange_times = ExchangeLim
		} = _GoodConfig ->
			ExchangeCounts = get_exchange_counts(RoleId, GoodTypeId, LimType),
			CheckList =
			[
				{exchange_counts, ExchangeLim, GoodTypeId, LimType},
				{bag_size, GiveGoods},{cost, CostScore, StatusCapsuleEgg#status_capsule_egg.score}
			],
			case check_can_exchange(CheckList, Player) of
				true ->
					%% 扣除 和 发放奖励
					NewStatusCapsuleEgg = cost_score(RoleId, StatusCapsuleEgg, CostScore),
					save_db_person_score(RoleId, StatusCapsuleEgg#status_capsule_egg.score - CostScore),   %% 积分
					%% 日志

					%% 增加次数
					add_exchange_counts(RoleId, GoodTypeId, LimType, 1),
					Produce = #produce{reward = GiveGoods, type = capsule_egg_exchange, show_tips = 1},
					{ok, NewPlayer} = lib_goods_api:send_reward_with_mail(Player#player_status{capsule_egg = NewStatusCapsuleEgg}, Produce, ?MOD_CAPSULE_EGG),

					send_msg(Sid, 17006, [?SUCCESS, Pos, GoodTypeId, ExchangeLim - ExchangeCounts - 1, NewStatusCapsuleEgg#status_capsule_egg.score]),
					{ok, NewPlayer};
				Res ->  %% 条件不满足
					send_msg(Sid, 17006, [Res, Pos, GoodTypeId, ExchangeLim - ExchangeCounts, StatusCapsuleEgg#status_capsule_egg.score]),
					{ok, Player}
			end;
		_ ->
			send_msg(Sid, 17006, [?ERRCODE(err170_exchange_pos_err), Pos, 0, 0, 0]),
			{ok, Player}
	end.

%% 次数奖励信息
send_times_reward_info(Player, PoolType) ->
	#player_status{sid = Sid, capsule_egg = StatusCapsuleEgg} = Player,
	#status_capsule_egg{capsule_egg_map = CapsuleEggMap} = StatusCapsuleEgg,
	case maps:get(PoolType, CapsuleEggMap, []) of
		#capsule_egg_data{times_reward = TimesReward} ->
			send_msg(Sid, 17011, [1, 1, PoolType, TimesReward]);
		_ ->
			send_msg(Sid, 17011, [1, 1, PoolType, []])
	end,
	ok.

%% 领取次数奖励
receive_times_reward(Player, PoolType, Times) ->
	#player_status{id = RoleId, sid = Sid, capsule_egg = StatusCapsuleEgg, figure = Figure} = Player,
	#status_capsule_egg{capsule_egg_map = CapsuleEggMap} = StatusCapsuleEgg,
	case maps:get(PoolType, CapsuleEggMap, []) of
		#capsule_egg_data{times_reward = TimesReward, draw_times = DrawTimes} = CapsuleEggData ->
			AllTimes = data_capsule_egg:get_all_times(PoolType),
			CheckCfgTrue = lists:member(Times, AllTimes),
			CheckHasRecv = case lists:keyfind(Times, 1, TimesReward) of
				               {_, _} -> false;
							   _ -> true
			               end,
			CheckCanRecv = case DrawTimes >= Times of
							   true -> true;
							   _ -> false
			               end,
			if
				CheckCfgTrue == false ->
					send_msg(Sid, 17011, [2, ?ERRCODE(err170_times_err), PoolType, TimesReward]),
					ok;
				CheckHasRecv == false ->
					send_msg(Sid, 17011, [2, ?ERRCODE(err170_times_has_received), PoolType, TimesReward]),
					ok;
				CheckCanRecv == false ->
					send_msg(Sid, 17011, [2, ?ERRCODE(err170_times_cannot_receive), PoolType, TimesReward]),
					ok;
				true ->
					case data_capsule_egg:get_times_reward(PoolType, Times) of
						[_|_] = Reward ->
							NewTimesReward = [{Times, 1}|TimesReward],
							NewCapsuleEggData = CapsuleEggData#capsule_egg_data{times_reward = NewTimesReward},
							NewCapsuleEggMap  = maps:put(PoolType, NewCapsuleEggData, CapsuleEggMap),
							NewStatusCapsuleEgg = StatusCapsuleEgg#status_capsule_egg{capsule_egg_map = NewCapsuleEggMap},
							Produce = #produce{type = capsule_egg_times_reward, reward = Reward},
							{ok, Player1} = lib_goods_api:send_reward_with_mail(Player, Produce),
							save_db_times_reward(RoleId, PoolType, Times, 1),
							NewPlayer = Player1#player_status{capsule_egg = NewStatusCapsuleEgg},
							lib_log_api:log_capsule_egg_award_times(RoleId, Figure#figure.name, PoolType, DrawTimes, Times, Reward),
							send_msg(Sid, 17011, [2, ?SUCCESS, PoolType, NewTimesReward]),
							{ok, NewPlayer};
						_ ->
							send_msg(Sid, 17011, [2, ?ERRCODE(err170_times_cannot_receive), PoolType, TimesReward]),
							ok
					end
			end;
		_ ->
			send_msg(Sid, 17011, [2, ?ERRCODE(err170_times_cannot_receive), PoolType, []]),
			ok
	end.

%% 每周一更新次数奖励领取状态
weekly_refresh() ->
	spawn(fun() ->
		timer:sleep(1000),
		%% 清理内存数据
		refresh_player(),
		%% 清理数据库数据
		Sql = io_lib:format(?SQL_DELETE_CAPSULE_EGG_TIMES_REWARD, []),
		db:execute(Sql),
		%% 清理抽奖次数
		Sql1 = io_lib:format(?SQL_UPDATE_DRAW_TIMES, []),
		db:execute(Sql1)
	end).

refresh_player() ->
	Pids = lib_player:get_online_pids(),
	[lib_player:apply_cast(Pid, ?APPLY_CAST_SAVE, ?MODULE, do_refresh_player, []) || Pid <- Pids].

do_refresh_player(Player) ->
	#player_status{sid = Sid, capsule_egg = StatusCapsuleEgg} = Player,
	#status_capsule_egg{capsule_egg_map = CapsuleEggMap} = StatusCapsuleEgg,
	F = fun(PoolType, CapsuleEggData, TMap) ->
		CapsuleEggData1 = CapsuleEggData#capsule_egg_data{draw_times = 0, times_reward = []},
		maps:put(PoolType, CapsuleEggData1, TMap)
	end,
	CapsuleEggMap1 = maps:fold(F, CapsuleEggMap, CapsuleEggMap),
	StatusCapsuleEgg1 = StatusCapsuleEgg#status_capsule_egg{capsule_egg_map = CapsuleEggMap1},
	NewPlayer = Player#player_status{capsule_egg = StatusCapsuleEgg1},
	PoolTypeL = lists:usort(maps:keys(CapsuleEggMap)),
	%% 推送最新领取状态
	F1 = fun(TPoolType) ->
		#capsule_egg_data{next_free_time = NextFreeTime} = maps:get(TPoolType, CapsuleEggMap1, #capsule_egg_data{}),
		NowTime = utime:unixtime(),
		FreeTimes = case NowTime >= NextFreeTime of
			            true -> 1;
			            _ -> 0
		            end,
		send_msg(Sid, 17000, [TPoolType, FreeTimes, NextFreeTime, 0]),
		send_msg(Sid, 17011, [1, 1, TPoolType, []])
	end,
	lists:map(F1, PoolTypeL),
	{ok, NewPlayer}.

%% 发送消息
send_msg(Sid, Cmd, Msg) ->
	{ok, Bin} = pt_170:write(Cmd, Msg),
	lib_server_send:send_to_sid(Sid, Bin).

%% ---------------------- builtin function ---------------------------------
make_capsule_egg_map([], Map, _RoleId) ->
	%% 初始化补全
	F = fun(PoolType, TMap) ->
		case maps:get(PoolType, Map, []) of
			#capsule_egg_data{} -> TMap;
			_ -> maps:put(PoolType, #capsule_egg_data{pool_type = PoolType}, TMap)
		end end,
	lists:foldl(F, Map, ?POOL_TYPE_LIST);
make_capsule_egg_map([CapsuleEggInfo|L], TMap, RoleId) ->
	[PoolType, NextFreeTime, DrawTimes, LuckyScore, TopLuckyScore] = CapsuleEggInfo,
	TimesReward =
	case get_db_times_reward(RoleId, PoolType) of
		[_|_] = TimesInfo ->
			F = fun([Times, Status], TList) ->
				[{Times, Status}|TList]
				end,
			lists:foldl(F, [], TimesInfo);
		_ ->
			[]
	end,
	CapsuleEggData = #capsule_egg_data{
		pool_type = PoolType
		,next_free_time = NextFreeTime
		,draw_times = DrawTimes
		,lucky_score = LuckyScore
		,top_lucky_score = TopLuckyScore
		,times_reward = TimesReward
	},
	NewCapsuleEggMap = maps:put(PoolType, CapsuleEggData, TMap),
	make_capsule_egg_map(L, NewCapsuleEggMap, RoleId).

init_capsule_egg_map([], Map) -> Map;
init_capsule_egg_map([PoolType|L], TMap) ->
	CapsuleEggData = #capsule_egg_data{pool_type = PoolType},
	NewCapsuleEggMap = maps:put(PoolType, CapsuleEggData, TMap),
	init_capsule_egg_map(L, NewCapsuleEggMap).

%% 抽奖具体逻辑
do_draw_capsule_egg(#player_status{capsule_egg = StatusCapsuleEgg, gold = Gold,
	id = RoleId} = Player, PoolType, DrawTimes, NowTime, AddBuff) ->
	#status_capsule_egg{capsule_egg_map = CapsuleEggMap} = StatusCapsuleEgg,
	CapsuleEggData = maps:get(PoolType, CapsuleEggMap, []),
	#capsule_egg_data{draw_times = HasDrawTimes, next_free_time = NextFreeTime,
		lucky_score = PerLuckyScore, top_lucky_score = TopPerLuckyScore
	} = CapsuleEggData,
	FreeTimes = get_free_times(NowTime, NextFreeTime),
	CostCouponNum = calc_cost_num(PoolType, DrawTimes, FreeTimes),  %% 连抽券不足时消耗的单抽券
	%% buff加成折扣
	IsDisCount = custom_unite_buff:get_capsule_disc(Player, DrawTimes),
	CheckCostDis = check_cost_discount(Player, PoolType, DrawTimes),
	case calc_true_cost_money(Player, PoolType, DrawTimes, CostCouponNum, Gold, IsDisCount) of
		[] ->
			%% 免费抽奖一次
			NewNextFreeTime = calc_next_free_time(Player, NowTime),
			%% 更新免费时间
			save_db_capsule_egg(RoleId, PoolType, NewNextFreeTime, HasDrawTimes, PerLuckyScore, TopPerLuckyScore),
			NewCapsuleEggData = CapsuleEggData#capsule_egg_data{next_free_time = NewNextFreeTime},
			NewCapsuleEggMap = maps:put(PoolType, NewCapsuleEggData, CapsuleEggMap),
			mod_capsule_egg:draw_capsule_egg(RoleId, PoolType, DrawTimes, HasDrawTimes, PerLuckyScore, TopPerLuckyScore, 1, [], AddBuff),
			mod_hi_point:success_end(RoleId, ?MOD_CAPSULE_EGG, 1),
			custom_act_adventure:do_trigger_adventure_task(RoleId, ?MOD_CAPSULE_EGG, 1),
			custom_act_days_plan:update_days_plan_task(RoleId,2,1),
			lib_task_api:capsule_egg(Player,1),
			contract_task_api:capsule_egg_trigger(RoleId, DrawTimes),
			lib_seven_days_goal:finish_task(RoleId, ?MOD_CAPSULE_EGG, 1, DrawTimes),
			{true, Player#player_status{capsule_egg = StatusCapsuleEgg#status_capsule_egg{capsule_egg_map = NewCapsuleEggMap}}};
		[_|_] = CostList ->
			%% 扣除抽奖券/货币
			case lib_goods_api:cost_object_list_with_check(Player, CostList, draw_capsule_egg, "") of
				{true, Player1, _} ->
					mod_capsule_egg:draw_capsule_egg(RoleId, PoolType, DrawTimes, HasDrawTimes, PerLuckyScore, TopPerLuckyScore, 0, CostList, AddBuff),
					mod_hi_point:success_end(RoleId, ?MOD_CAPSULE_EGG, 1, DrawTimes),
					custom_act_adventure:do_trigger_adventure_task(RoleId, ?MOD_CAPSULE_EGG, 1, DrawTimes),
					custom_act_days_plan:update_days_plan_task(RoleId,2,DrawTimes),
					lib_task_api:capsule_egg(Player1,DrawTimes),
					contract_task_api:capsule_egg_trigger(RoleId, DrawTimes),
					lib_seven_days_goal:finish_task(RoleId, ?MOD_CAPSULE_EGG, 1, DrawTimes),
					IsDisCount > 0 andalso CheckCostDis == true andalso custom_unite_buff:cost_times(Player,capsule_egg_discount,DrawTimes),
					{true, Player1};
				{false, ErrCode, _Player1} ->
					{false, ErrCode}
			end;
		{false, Err} ->
			{false, Err}
	end.

check_cost_discount(Player, PoolType, DrawTimes) ->
	[{_, GoodsTypeId, _}] = data_capsule_egg:get_capsule_egg_kv_cfg(format_draw_cost(PoolType, DrawTimes)),
	[{_, OwnNum}] = lib_goods_api:get_goods_num(Player, [GoodsTypeId]),
	case DrawTimes == 10 orelse DrawTimes == 50 of
		true when OwnNum >= 1 ->
			false;
		_ ->
			true
	end.

format_draw_times(PoolType, DrawTimes) ->
	case {PoolType, DrawTimes} of
		{1, 1}  -> long_one_cost;
		{1, 10} -> long_ten_cost;
		{1, 50} -> long_fifty_cost;
		{2, 1}  -> xuan_one_cost;
		{2, 10} -> xuan_ten_cost;
		{2, 50} -> xuan_fifty_cost;
		{3, 1}  -> hua_one_cost;
		{3, 10} -> hua_ten_cost;
		{3, 50} -> hua_fifty_cost;
		_ -> skip
	end.

format_draw_cost(PoolType, DrawTimes) ->
	case {PoolType, DrawTimes} of
		{1, 1}  -> long_one_cost_ticket;
		{1, 10} -> long_ten_cost_ticket;
		{1, 50} -> long_fifty_cost_ticket;
		{2, 1}  -> xuan_one_cost_ticket;
		{2, 10} -> xuan_ten_cost_ticket;
		{2, 50} -> xuan_fifty_cost_ticket;
		{3, 1}  -> hua_one_cost_ticket;
		{3, 10} -> hua_ten_cost_ticket;
		{3, 50} -> hua_fifty_cost_ticket;
		_ -> skip
	end.

%% 计算免费次数
get_free_times(NowTime, NextFreeTime) ->
	case NowTime >= NextFreeTime of
		true -> 1;
		_ -> 0
	end.

%% 计算连抽扣取的单抽券数量
calc_cost_num(PoolType, DrawTimes, FreeTimes) ->
	[{_, _, NeedNum}] = data_capsule_egg:get_capsule_egg_kv_cfg(format_draw_times(PoolType, DrawTimes)),
	case DrawTimes == 1 andalso FreeTimes > 0 of
		true -> 0;
		_ -> NeedNum
	end.

%% 计算扣费
%% @param: CostCouponNum 没有连抽券,需要消耗的单抽券,用于计算金额
calc_cost_money(Player, PoolType, DrawTimes, CostCouponNum) ->
	case data_capsule_egg:get_capsule_egg_kv_cfg(format_draw_cost(PoolType, DrawTimes)) of
		[{_, GoodsTypeId, _}] ->
			[{_, OwnNum}] = lib_goods_api:get_goods_num(Player, [GoodsTypeId]),
			case DrawTimes == 1 andalso CostCouponNum == 0 of
				%% 单抽并且有免费次数
				true ->
					0;
				_ ->
					case OwnNum > 0 of
						%% 有券
						true ->
							0;
						%% 没有券
						_ ->
							[{_, GoodsTypeId1, _}] = data_capsule_egg:get_capsule_egg_kv_cfg(format_draw_times(PoolType, DrawTimes)),
							[{_, OwnNum1}] = lib_goods_api:get_goods_num(Player, [GoodsTypeId1]),
							case OwnNum1 >= CostCouponNum of
								true -> 0;
								_ ->
									{_PriceType, Price} = data_goods:get_goods_buy_price(GoodsTypeId1),
									case Price =< 0 of
										true -> {false, ?ERRCODE(err150_price_err)};
										_ ->
											NotEnoughNum = max(CostCouponNum - OwnNum1, 0),
											CostMoney = NotEnoughNum*Price,
											CostMoney
									end
							end
					end
			end;
		_ ->
			{false, ?ERRCODE(err170_config_err)}
	end.

%% 计算真实扣费
calc_true_cost_money(Player, PoolType, DrawTimes, CostCouponNum, HasGold, IsDisCount) ->
	%% 检查是否有连抽券
	[{_, GoodsTypeId, _}] = CostTicket = data_capsule_egg:get_capsule_egg_kv_cfg(format_draw_cost(PoolType, DrawTimes)),
	[{_, OwnNum}] = lib_goods_api:get_goods_num(Player, [GoodsTypeId]),
	BuffRatio = custom_unite_buff:check_discount(Player, capsule_egg_discount),
	case DrawTimes > 1 andalso OwnNum > 0 of
		true -> CostTicket;
		_ ->
			[{_, GoodsTypeId1, _}] = data_capsule_egg:get_capsule_egg_kv_cfg(format_draw_times(PoolType, DrawTimes)),
			[{_, OwnNum1}] = lib_goods_api:get_goods_num(Player, [GoodsTypeId1]),
			%% 打折前判断
			case OwnNum1 >= CostCouponNum of
				true when CostCouponNum == 0 ->
					[];
				true ->
					case IsDisCount > 0 of
						true ->
							%% 如果是单抽不打折
							case DrawTimes == 1 of
								true ->
									[{?TYPE_GOODS, GoodsTypeId1, CostCouponNum}];
								_ ->
									[{?TYPE_GOODS, GoodsTypeId1, max(1, round(CostCouponNum*BuffRatio))}]
							end;
						_ ->
							[{?TYPE_GOODS, GoodsTypeId1, CostCouponNum}]
					end;
				_ ->
					{_PriceType, Price} = data_goods:get_goods_buy_price(GoodsTypeId1),
					case IsDisCount > 0 of
						true ->
							%% 如果是单抽不打折
							case DrawTimes == 1 of
								true ->
									CostMoney = Price * CostCouponNum,
									CostNum = 0;
								_ ->
									CostMoney = Price * max(0, (round(CostCouponNum * BuffRatio) - OwnNum1)),
									CostNum   = min(OwnNum1, round(CostCouponNum * BuffRatio))
							end;
						_ ->
							CostNum = OwnNum1,
							CostMoney = Price * max(0, (CostCouponNum - OwnNum1))
					end,
					case Price =< 0 of
						true -> {false, ?ERRCODE(err150_price_err)};
						_ ->
							%% 彩钻补足
							case HasGold >= CostMoney of
								true ->
									CostList = [{?TYPE_GOODS, GoodsTypeId1, CostNum}, {?TYPE_GOLD, ?GOODS_ID_GOLD, CostMoney}],
									[{Type, TGoodTypeId, Num}||{Type, TGoodTypeId, Num}<-CostList, Num > 0];
								_ ->
									{false, ?ERRCODE(money_not_enough)}
							end
					end
			end
	end.

%% 计算下一次免费时间
calc_next_free_time(Player, NowTime) ->
	%% 宠物生活技能，缩减下次免费时间
	CutTime = lib_pet_api:pet_life_skill_about_capsule_egg_free_time(Player),
	case data_capsule_egg:get_capsule_egg_kv_cfg(free_interval) of
		Interval when is_integer(Interval) -> skip;
		_ -> Interval = ?FREE_DRAW_INTERVAL
	end,
	case CutTime of
		true -> Interval1 = round(Interval/2);
		_ -> Interval1 = Interval
	end,
	NextFreeTime = NowTime + Interval1,
	NextFreeTime.

%% 构造sql语句
tran_format([], SoFar) -> SoFar;
tran_format([[]], SoFar) -> SoFar;
tran_format([Data = [_PoolType, _RoleId, _RewardCfgId, _Time]|Rest], SoFar) ->
	Value = io_lib:format(?SQL_BATCH_INSERT_CAPSULE_EGG_DRAW_LOG_VALUE, Data),
	tran_format(Rest, [Value|SoFar]).

%% ---------------------------------------------------------------------
%% 积分商城相关
%% 获取已经兑换的次数
get_exchange_counts(RoleId, KeyId, LimitType) ->
	if
		LimitType == ?SCORE_STORE_LIMIT_DAILY ->
			lib_daily:get_count(RoleId, ?MOD_CAPSULE_EGG, 1, KeyId);
		LimitType == ?SCORE_STORE_LIMIT_WEEK ->
			lib_week:get_count(RoleId, ?MOD_CAPSULE_EGG, 1, KeyId);
		true ->
			lib_counter:get_count(RoleId, ?MOD_CAPSULE_EGG, 1, KeyId)
	end.

%% 增加兑换的次数
add_exchange_counts(RoleId, KeyId, LimitType, ExchangeTimes) ->
	if
		LimitType == ?SCORE_STORE_LIMIT_DAILY ->
			lib_daily:plus_count(RoleId, ?MOD_CAPSULE_EGG, 1, KeyId, ExchangeTimes);
		LimitType == ?SCORE_STORE_LIMIT_WEEK ->
			lib_week:plus_count(RoleId, ?MOD_CAPSULE_EGG, 1, KeyId, ExchangeTimes);
		true ->
			lib_counter:plus_count(RoleId, ?MOD_CAPSULE_EGG, 1, KeyId, ExchangeTimes)
	end.

cost_score(_RoleId, StatusCapsuleEgg, CostScore) ->
	#status_capsule_egg{score = Score} = StatusCapsuleEgg,
	NewScore = Score - CostScore,
	NewStatusCapsuleEgg = StatusCapsuleEgg#status_capsule_egg{score = NewScore},
	NewStatusCapsuleEgg.

%% ---------------------- 判断逻辑 ---------------------------------
check_list([]) -> true;
check_list([Check|L]) ->
	case do_check(Check) of
		true-> check_list(L);
		{false, Res} -> {false, Res}
	end.

%% 抽奖相关判断
do_check({pool_type_true, PoolType}) ->
	case lists:member(PoolType, ?POOL_TYPE_LIST) of
		true -> true;
		_ -> {false, ?ERRCODE(err170_pool_type_err)}
	end;
do_check({draw_times_true, DrawTimes}) ->
	case lists:member(DrawTimes, ?DRAW_TIMES_LIST) of
		true -> true;
		_ -> {false, ?ERRCODE(err170_draw_times_cfg_err)}
	end;
do_check({check_data, CapsuleEggMap, PoolType}) ->
	CapsuleEggData = maps:get(PoolType, CapsuleEggMap, []),
	case CapsuleEggData of
		#capsule_egg_data{} -> true;
		_ -> {false, ?ERRCODE(err170_not_capsule_egg_data)}
	end;
do_check({money_enough, Player, PoolType, DrawTimes, NowTime}) ->
	#player_status{capsule_egg = StatusCapsuleEgg, gold = Gold} = Player,
	#status_capsule_egg{capsule_egg_map = CapsuleEggMap} = StatusCapsuleEgg,
	CapsuleEggData = maps:get(PoolType, CapsuleEggMap, []),
	case data_capsule_egg:get_capsule_egg_kv_cfg(format_draw_times(PoolType, DrawTimes)) of
		[{_, _, _NeedCouponNum}] ->
			case CapsuleEggData of
				#capsule_egg_data{next_free_time = NextFreeTime} ->
					FreeTimes = get_free_times(NowTime, NextFreeTime),
					CostCouponNum = calc_cost_num(PoolType, DrawTimes, FreeTimes),  %% 连抽券不足时消耗的单抽券
					case calc_cost_money(Player, PoolType, DrawTimes, CostCouponNum) of
						CostMoney when is_integer(CostMoney) ->
							case Gold >= CostMoney of
								true -> true;
								_ ->
									{false, ?ERRCODE(money_not_enough)}
							end;
						{false, Err} -> {false, Err}
					end;
				_ ->
					{false, ?ERRCODE(err170_not_capsule_egg_data)}
			end;
		_ ->
			{false, ?ERRCODE(err170_config_err)}
	end;
do_check({bag_size}) ->
	GoodsStatus = lib_goods_do:get_goods_status(),
	NullCell = lib_goods_util:get_null_cell_num(GoodsStatus, ?GOODS_LOC_CAPSULE_EGG_BAG),
	case NullCell > ?CAPSULE_EGG_NULL_CELL of
		true -> true;
		_ -> {false,  ?ERRCODE(err170_warehose_not_enough)}
	end;
do_check(_Check) ->
	?ERR("<<Error check_capsule_egg>>"),
	true.

check_can_exchange([], _Player) -> true;
check_can_exchange([Check|T], Player) ->
	case do_check(Check, Player) of
		true ->
			check_can_exchange(T, Player);
		{false, Err} -> Err
	end.
%% 背包大小是否满足
do_check({bag_size, GiveGoods}, Player) ->
	case lib_goods_api:can_give_goods(Player, GiveGoods) of
		true ->
			true;
		_ ->
			{false, ?ERRCODE(err150_no_cell)}
	end;
%% 兑换的次数是否足够
do_check({exchange_counts, ExchangeLim, KeyId, LimitType}, Player) ->
	#player_status{id = RoleId} = Player,
	ExchangeCounts = get_exchange_counts(RoleId, KeyId, LimitType),
	case ExchangeLim > ExchangeCounts of
		true -> true;
		false -> {false, ?ERRCODE(err170_exchange_count_not_enough)}
	end;
%% 消耗的积分是否足够
do_check({cost, Cost, Score}, _Player) ->
	case Score >= Cost of
		true ->
			true;
		_ ->
			{false, ?ERRCODE(err170_score_not_enough)}
	end;
do_check(_Check, _Player) ->
	?ERR("capsule_egg check err, Check is ~p~n",[_Check]),
	true.


%% ----------------- 数据库操作 -------------------------------
%% 个人数据
save_db_capsule_egg(RoleId, PoolType, NextFreeTime, DrawTimes, PerLuckyScore, TopLuckyScore) ->
	Sql = io_lib:format(?SQL_INSERT_CAPSULE_EGG, [RoleId, PoolType, NextFreeTime, DrawTimes, PerLuckyScore, TopLuckyScore]),
	db:execute(Sql).

get_db_capsule_egg(RoleId) ->
	Sql = io_lib:format(?SQL_SELECT_CAPSULE_EGG, [RoleId]),
	db:get_all(Sql).

update_db_capsule_egg(RoleId, PoolType, NextFreeTime, DrawTimes) ->
	Sql = io_lib:format(?SQL_UPDATE_CAPSULE_EGG, [NextFreeTime, DrawTimes, RoleId, PoolType]),
	db:execute(Sql).

%%update_db_free_time(RoleId, PoolType, NextFreeTime) ->
%%	Sql = io_lib:format(?SQL_UPDATE_FREE_TIME, [NextFreeTime, RoleId, PoolType]),
%%	db:execute(Sql).

save_db_person_score(RoleId, Score) ->
	Sql = io_lib:format(?SQL_INSERT_CAPSULE_EGG_PERSON_SCORE, [RoleId, Score]),
	db:execute(Sql).

get_db_person_score(RoleId) ->
	Sql = io_lib:format(?SQL_SELECT_CAPSULE_EGG_PERSON_SCORE, [RoleId]),
	db:get_row(Sql).

%% 全服数据
save_db_server_score(PoolType, Score, ShowScore) ->
	Sql = io_lib:format(?SQL_INSERT_CAPSULE_EGG_SERVER_LUCKY, [PoolType, Score, ShowScore]),
	db:execute(Sql).

get_db_server_score() ->
	Sql = io_lib:format(?SQL_SELECT_CAPSULE_EGG_SERVER_LUCKY, []),
	db:get_all(Sql).

%% (暂时没用到)
save_db_top_server_score(PoolType, Score) ->
	Sql = io_lib:format(?SQL_INSERT_CAPSULE_EGG_TOP_SERVER_LUCKY, [PoolType, Score]),
	db:execute(Sql).

%% (暂时没用到)
get_db_top_server_score() ->
	Sql = io_lib:format(?SQL_SELECT_CAPSULE_EGG_TOP_SERVER_LUCKY, []),
	db:get_all(Sql).

save_db_draw_log(PoolType, RoleId, RewardCfgId, Color, Time) ->
	Sql = io_lib:format(?SQL_INSERT_CAPSULE_EGG_DRAW_LOG, [PoolType, RoleId, RewardCfgId, Color, Time]),
	db:execute(Sql).

get_db_draw_log(TimeStamp, Limit) ->
	Sql = io_lib:format(?SQL_SELECT_CAPSULE_EGG_DRAW_LOG, [TimeStamp, Limit]),
	db:get_all(Sql).

get_db_top_draw_log(TimeStamp, Limit) ->
	Sql = io_lib:format(?SQL_SELECT_TOP_CAPSULE_EGG_DRAW_LOG, [TimeStamp, Limit]),
	db:get_all(Sql).

%% 次数奖励
get_db_times_reward(RoleId, PoolType) ->
	Sql = io_lib:format(?SQL_SELECT_CAPSULE_EGG_TIMES_REWARD, [RoleId, PoolType]),
	db:get_all(Sql).

save_db_times_reward(RoleId, PoolType, Times, Status) ->
	Sql = io_lib:format(?SQL_INSERT_CAPSULE_EGG_TIMES_REWARD, [RoleId, PoolType, Times, Status]),
	db:execute(Sql).

%% 查询玩家名称
get_db_player_name(RoleId) ->
	Sql = io_lib:format(?SQL_SELECT_PLAYER_NAME, [RoleId]),
	db:get_row(Sql).