%% ---------------------------
%% desc	 :快速挂机(经验仙盏)
%% module:fast_exp_drop.erl
%% author:hh
%% time	 :20/02/12
%% ---------------------------

-module(fast_exp_drop).

-include("exp_dun_drop.hrl").
-include("server.hrl").
-include("common.hrl").
-include("dungeon.hrl").
-include("def_event.hrl").
-include("def_module.hrl").
-include("def_goods.hrl").
-include("rec_event.hrl").
-include("errcode.hrl").
-include("figure.hrl").
-include("custom_act.hrl").
-include("common.hrl").
-include("vip.hrl").
-export([
	handle_event/2,

	get_fast_drop_reward/2,
	get_fast_drop_time/1,
	get_exp_dun_max_wave/1,
	get_fast_drop_max_count/1
	]).

handle_event(Player = #player_status{id = RoleId, figure = #figure{lv = RoleLv}}, #event_callback{type_id = ?EVENT_LV_UP}) ->
	OpenLv = data_module:get_module_open_lv(?MOD_DUNGEON, ?EXP_DROP_2),
	if RoleLv == OpenLv ->
            #player_status{exp_dun_drop = #role_exp_dun_drop{fast_drop_time = Time}} = Player,
            if Time == 0 ->
                    Now = utime:unixtime(),
                    db_update_fast_reward_time(RoleId, Now),
                    {ok, Player#player_status{exp_dun_drop = #role_exp_dun_drop{fast_drop_time = Now}}};
                true ->
                    {ok, Player}
            end;
		true ->
			{ok, Player}
	end;
handle_event(Player = #player_status{id = RoleId, sid = Sid}, #event_callback{type_id = ?EVENT_SUP_VIP_CHANGE}) ->
    MaxCount = get_fast_drop_max_count(Player),
    DropedCount = lib_daily:get_count(RoleId, ?MOD_DUNGEON, ?MOD_EXP_DUN_FAST_DROP),
    {ok, BinData} = pt_610:write(61051, [MaxCount, DropedCount, utime:unixtime()]),
    lib_server_send:send_to_sid(Sid, BinData),
    {ok, Player};
handle_event(Player = #player_status{id = RoleId, figure = #figure{lv = RoleLv}}, #event_callback{type_id = ?EVENT_LOGIN_CAST}) ->
    OpenLv = data_module:get_module_open_lv(?MOD_DUNGEON, ?EXP_DROP_2),
    case db:get_row(?SELECT_ROLE_FAST_EXP, [RoleId]) of
        [FastDropTime|_] -> ok;
        _ ->
        	if RoleLv >= OpenLv ->
        			Now =  utime:unixtime(),
            		FastDropTime = Now,
            		db_update_fast_reward_time(RoleId, Now);
            	true ->
            		FastDropTime = 0
            end
    end,
    {ok, Player#player_status{exp_dun_drop = #role_exp_dun_drop{fast_drop_time = FastDropTime}}};
handle_event(_Player, _) ->
	{ok, _Player}.

get_fast_drop_reward(Player, RewardTimes) ->
 	#player_status{id = RoleId, sid = Sid, exp_dun_drop = ExpDunDrop, gold = PreGold, figure=#figure{lv=Lv, vip = VipLv}} = Player,
 	case exp_dun_drop_check:fast_drop_reward_check(Player, RewardTimes) of
 		{true, NewPlayer, BaseExp, RealRewardTimes, DropedCount, RestCount, Cost} ->
 			%% 快速挂机基础奖励
            FastDropBaseRewards = [{?TYPE_EXP, 0, round(BaseExp*RealRewardTimes)}],
            %% 额外的放置经验挂机收益
			{RandGoods, DailyGoods} = get_extra_rand_drop(Player, [], RealRewardTimes),
			%% 限时掉落获得
			LimitGoods = calc_act_limit_drop_goods(Lv),
            %% 总收益 = 快速挂机基础奖励+额外放置经验挂机收益
			Rewards0   = lists:append(FastDropBaseRewards, RandGoods),
			Rewards    = lists:append(Rewards0,LimitGoods),

		    NullCellNum = lib_goods_api:get_cell_num(RoleId),
		    {MailGoods, CellGoods, _} = lib_exp_dun_drop:calc_avalible_loc_goods(Rewards, NullCellNum),
		    NewPlayer1 = lib_goods_api:send_reward(NewPlayer, CellGoods, fast_exp_dun_drop_reward),
            DailyGoods =/= [] andalso lib_daily:set_count(RoleId, DailyGoods),
		    MailGoods =/= [] andalso
		     begin
		        Title = utext:get(6100012),
		        Content = utext:get(6100013),
		        lib_mail_api:send_sys_mail([RoleId], ?MOD_DUNGEON, Title, Content, MailGoods)
		     end,

		    Now = utime:unixtime(),
            if RestCount > 0 -> NewDropedCount = DropedCount;
                true -> 
                    NewDropedCount = DropedCount+1,
                    lib_daily:set_count_offline(RoleId, ?MOD_DUNGEON, ?MOD_EXP_DUN_FAST_DROP, NewDropedCount)
            end,
		    db_update_fast_reward_time(RoleId, Now),
		    FastDropMax = get_fast_drop_max_count(NewPlayer1),
            RewardsShow = lib_exp_dun_drop:tran_rewards_show(_CalcType = fast_exp_drop, FastDropBaseRewards, RandGoods++LimitGoods),
		    {ok, Bin} = pt_610:write(61050, [?SUCCESS, 2, RewardTimes, RewardsShow]),
		    {ok, Bin1} = pt_610:write(61051, [FastDropMax, NewDropedCount, Now]),
		    lib_server_send:send_to_sid(Sid, <<Bin/binary, Bin1/binary>>),
		    #player_status{gold = AfterGold} = NewPlayer2 = NewPlayer1#player_status{exp_dun_drop = ExpDunDrop#role_exp_dun_drop{fast_drop_time = Now}},
            %% 日志
            MaxCount = fast_exp_drop:get_fast_drop_max_count(NewPlayer2),
            case lists:keyfind(?TYPE_EXP, 1, Rewards) of
                {_, _, ExpAdd} -> ok;
                {_, ExpAdd}    -> ok;
                _   -> ExpAdd = 0
            end,
            RewardsBin = util:term_to_bitstring(Rewards),
            % CostBin    = util:term_to_bitstring(Cost),
            case Cost of
                [{_, _, CostGold}|_] -> ok;
                _ -> CostGold = 0
            end,
            lib_log_api:log_onhook_fast(
                [RoleId, VipLv, RewardTimes, NewDropedCount, max(0, MaxCount - NewDropedCount), PreGold, AfterGold, CostGold, ExpAdd, RewardsBin, Now]
            ),
			% 触发七日目标任务
			{ok, NewPlayer3} = lib_seven_days_goal:do_finish_task(NewPlayer2, ?MOD_DUNGEON, 15),
		    lib_achievement_api:dun_exp_quick_event(NewPlayer3, 1),
		    lib_activitycalen_api:role_success_end_activity(RoleId, ?MOD_DUNGEON, 15),
		    custom_act_mobilize:update_mobilize_task(NewPlayer3, fast_onhook, 1),
            SupVipTpye = lib_sup_vip:sup_vip_type(NewPlayer3),
            UpLv = NewPlayer3#player_status.figure#figure.lv - Lv,
            ta_agent_fire:ta_fast_exp_drop(NewPlayer3, [RewardTimes, SupVipTpye, UpLv, CostGold]),
		    {ok, NewPlayer3};
 		{false, ErrCode} ->
 			lib_server_send:send_to_sid(Sid, pt_610, 61050, [ErrCode, 2, RewardTimes, []]),
 			{ok, Player}
 	end.

 db_update_fast_reward_time(RoleId, Time) ->
 	db:execute(?REPLACE_DROP_INFO_FAST_DROP_TIME, [RoleId, Time]),
 	ok.

get_fast_drop_max_count(Player) when is_record(Player, player_status)->
	get_fast_drop_max_count(Player#player_status.vip_status#vip_status.sup_vip);
get_fast_drop_max_count(SupVip) when is_record(SupVip, role_sup_vip)->
	BaseCount = data_exp_dun_drop:get_kv(1),
	case lib_sup_vip:is_sup_vip(SupVip) of
		true ->
			SubVipCount = data_exp_dun_drop:get_kv(2),
			BaseCount + SubVipCount;
		_ ->
			BaseCount
	end.
get_extra_rand_drop(Player, GoodsLimit, Times) ->
    #player_status{dungeon_record = Record, figure = #figure{lv = Lv}} = Player,
	MaxWave = get_exp_dun_max_wave(Record),
	DropCount = calc_fast_drop_count(Times),
    OpenDay = util:get_open_day(),
	{_NewGoodsLimit, RewardsGoods} = lib_exp_dun_drop:do_calc_interval_goods(DropCount, MaxWave, GoodsLimit, Lv, OpenDay, []),
	ExpRewards = calc_extra_exp(Times, MaxWave),
	% update_goods_limit(RoleId, GoodsLimit, NewGoodsLimit),
	RewardsGoods0 = merge_unique_goods(ExpRewards ++ RewardsGoods),
	RewardsGoods1 = [{GoodsType, GoodsId, Num} || {{GoodsType, GoodsId}, Num} <- RewardsGoods0],
	lib_exp_dun_drop:calc_exp_drop_add_ratio_rewards(Player, RewardsGoods1).

calc_extra_exp(Times, Wave) ->
    IntervalExp = data_exp_dun_drop:get_exp_effiency(Wave),
    Interval    = data_exp_dun_drop:get_kv(3),
    ExpDropCounts  = umath:floor(Times*3600/Interval),
    TotalExp    = umath:floor(ExpDropCounts*umath:floor(IntervalExp/12)),
    if TotalExp =/= 0 ->
            % ?ERR("~p", [TotalExp]),
            [{{?TYPE_EXP, 0}, TotalExp}];
        true ->
            []
    end.

merge_unique_goods(RewardsGoods) ->
	lists:foldl(fun({{GoodsType, GoodsId}, Num}, Acc) ->
		case lists:keyfind({GoodsType, GoodsId}, 1, Acc) of
			{_, OldNum} ->
				lists:keystore({GoodsType, GoodsId}, 1, Acc, {{GoodsType, GoodsId}, round(OldNum + Num)});
			_ ->
				lists:keystore({GoodsType, GoodsId}, 1, Acc, {{GoodsType, GoodsId}, Num})
		end
	 end, [], RewardsGoods).

get_exp_dun_max_wave(Record) ->
	[DunId|_] = data_dungeon:get_ids_by_type(?DUNGEON_TYPE_EXP),
	DunRec = maps:get(DunId, Record, []),
	case lists:keyfind(?DUNGEON_REC_MAX_SCORE, 1, DunRec) of
		{_, MaxWave} -> ok;
		_ 			 -> MaxWave = 0
	end,
	MaxWave.

% update_goods_limit(RoleId, GoodsLimit, NewGoodsLimit) ->
% 	GoodsLimit1    = lists:keysort(1, GoodsLimit),
% 	NewGoodsLimit1 = lists:keysort(1, NewGoodsLimit),
% 	if GoodsLimit1 == NewGoodsLimit1 ->
% 			skip;
% 		true ->
% 			exp_dun_drop_mgr:update_goods_limit(RoleId, NewGoodsLimit1)
% 	end.

%% 计算附加的时间内的物品掉落产出次数
calc_fast_drop_count(Times) ->
	DropInterVal = data_exp_dun_drop:get_kv(4),
	TotalSec = round(Times*3600),
	round(TotalSec/DropInterVal).

get_fast_drop_time(Player) ->
	#player_status{exp_dun_drop = ExpDunDrop} = Player,
	case ExpDunDrop of
		#role_exp_dun_drop{fast_drop_time = Time} ->
			Time;
		_ ->
			0
	end.

%%计算限时掉落
calc_act_limit_drop_goods(Lv)->
     Opens = lib_custom_act_util:get_open_subtype_list(?CUSTOM_ACT_THEME_LIMIT_DROP),
	drop_logic:calc_all_limit_drop(Opens,0,Lv,[]).


