
% date  :   2021-7-27
% desc  :   货币祈愿协议入口
% author:   JiangXun

-module(lib_currencywish).
-include("server.hrl").
-include("currencywish.hrl").
-include("figure.hrl").
-include("errcode.hrl").
-include("def_goods.hrl").
-include("def_module.hrl").

% --------外部函数--------
-export([
        % check_wish_legal/1
        login/1,                    % 用户登录初始化
        logout/1,                   % 下线写入数据库
        check_list/1,               
        do_consumegoods_to_wish/2   % 祈愿
]).

% --------内部函数--------
-export([
        check_type/2,
        % check_enough/2,
        ascend_award_and_decend_good/4, % 每次祈愿获得奖励和消耗物品
        ascend_award_and_decend_gold/4,
        % 交易券祈愿
        do_ticket_wish/4,
        after_ticket_wish/3,
        % 豪华祈愿
        do_luxury_wish/4,
        after_luxury_wish/3,
        % 经验祈愿
        do_experience_wish/4,
        after_experience_wish/3
    ]).

% -------内部外部都使用------
-export([
        cal_costcount/3,
        cal_freecount/2,
        increment_onecount/3,
        check/1
    ]).

% --------gm使用-------------
-export([
        zero_costcount/3,
        gm_reset_wishcount/2
    ]).

%--------祈愿检查相关-------
% 所有合法的祈愿类型
get_wish_type() ->
    [?TICKET_WISH, ?LUXURY_WISH, ?EXPERIENCE_WISH].

% 有免费祈愿的祈愿类型，目前只有豪华祈愿可以免费祈愿
get_havefreecd_type() ->
    [?LUXURY_WISH].


% -------------下线和上线操作-------
login(RoleId) ->
    Sql = io_lib:format(?SQL_CURRENCYWISH_SELECT, [RoleId]),
    case db:get_row(Sql) of
        [Ticket_FreeLast, Luxury_FreeLast, Expr_FreeLast] ->
            #role_currencywish{lastfreetimemap = #{?TICKET_WISH => Ticket_FreeLast,?LUXURY_WISH => Luxury_FreeLast, ?EXPERIENCE_WISH => Expr_FreeLast}};
        _ ->
            #role_currencywish{lastfreetimemap = #{?TICKET_WISH => 0,?LUXURY_WISH => 0, ?EXPERIENCE_WISH => 0}}
    end.
 
logout(PlayerState) ->
    #player_status{id = RoleId, role_currencywish = Role_currencywish} = PlayerState,
    #role_currencywish{lastfreetimemap = Lastfreetimemap} = Role_currencywish,
    F = fun(_K, V, AccIn) ->
        AccIn ++ [V]
    end,

    DurableList = maps:fold(F, [RoleId], Lastfreetimemap),
    Sql = io_lib:format(?SQL_CURRENCYWISH_REPLACE, DurableList),
    db:execute(Sql).


% -------每日抽奖计数器---------
cal_costcount(RoleId, Module, Type) ->
    lib_daily:get_count(RoleId, Module, Type).


cal_freecount(WishType, Role_currencywish) ->
    #role_currencywish{lastfreetimemap = Lastfreetimemap} = Role_currencywish,
    {ok, Lastfreetime} = maps:find(WishType, Lastfreetimemap),
    NowTime = utime:unixtime(),
    _FreeWishCount = 
    % case is_same_day(four, Lastfreetime, NowTime) of

    case utime:is_logic_same_day(Lastfreetime, NowTime, 4) of
        true ->
            1;
        false ->
            0
    end.

increment_onecount(RoleId, Module, Type) ->
    lib_daily:increment(RoleId, Module, Type).

zero_costcount(RoleId, Module, Type) ->
    lib_daily:set_count(RoleId, Module, Type, 0).



check_type(_Value, []) -> false;
check_type(Value, [H|List]) ->
    if
        Value =:= H ->
            true;
        true ->
            check_type(Value, List)
    end.


% check_enough([], []) -> true;
% check_enough([H1|HaveGoodList], [H2|CostGoodList]) ->
%     {TypeId, HaveNum} = H1,
%     {TypeId, CostNum} = H2,
%     if
%         HaveNum < CostNum ->
%             {false, err340_no_enough_consume};   
%         true ->
%             check_enough(HaveGoodList,CostGoodList)
%     end.


%检查祈愿类型是否合法
check({type_legal, WishType}) ->
    WishTypeList = get_wish_type(),
    check_type(WishType, WishTypeList);
    
%检查是否超过当日最大祈愿次数，这里要注意有可能会有免费祈愿哦~
check({upper_limit, WishType, PlayerState}) ->
    if
        WishType =:= ?TICKET_WISH -> %交易券祈愿没有每日上限
            true;
        true ->
            #player_status{id = RoleId} = PlayerState,
            KeyConvert = list_to_atom(lists:concat([?EXCHANGE_TIMES, WishType])),
            [MaxCostCount] = data_currencywish:get_currencywish_kv(KeyConvert),  %每日付费兑换最大次数
            NowCostCount = cal_costcount(RoleId, ?MOD_CURRENCYWISH, WishType),
            if
                NowCostCount >= MaxCostCount ->
                    % 检查是否有免费次数
                    case lists:member(WishType, get_havefreecd_type()) of
                        true ->
                            case check({cdlimit, WishType, PlayerState}) of
                                {true, _} ->
                                    true;
                                {false, _} ->
                                    false
                            end;
                        false ->
                            false
                    end;
                true ->
                    true
            end
    end;


%cd是否已经冷却结束
check({cdlimit, WishType, PlayerState}) ->
    #player_status{role_currencywish = Role_currencywish} = PlayerState,
    #role_currencywish{lastfreetimemap = LastFreeTimeMap} = Role_currencywish,
    {ok, LastFreeTime} = maps:find(WishType, LastFreeTimeMap), %最后一次使用免费次数的时间
    ConsultKey = list_to_atom(lists:concat([?FREECD, WishType])),
    [CDLimit] = data_currencywish:get_currencywish_kv(ConsultKey),
    NowTime = utime:unixtime(),
    CD = NowTime - LastFreeTime,
    if
        CD < CDLimit  ->
            RestCD = CDLimit - CD,
            {false, RestCD};    % 未冷却结束，返回剩余冷却时间
        true ->
            {true, 0}           % 冷却结束，默认返回0
    end;


% % 消耗物品为普通物品,目前交易券祈愿会用到
% check({enough_consume, [], _PlayerState}) -> true;
% check({enough_consume, CostGoodList, PlayerState}) ->
%     GoodTypeIdList = [GoodTypeId||{_, GoodTypeId, _} <- CostGoodList],
%     HaveGoodList = lib_goods_api:get_goods_num(PlayerState, GoodTypeIdList),%[{GoodTypeId, Num}...]
%     NCostGoodList = [{GoodTypeId, GoodNum}||{_, GoodTypeId, GoodNum} <- CostGoodList],
%     check_enough(HaveGoodList, NCostGoodList);


% 消耗物品为彩钻
check({enough_gold, [], _PlayerState}) -> true;
check({enough_gold, CostGood, PlayerState}) ->
    [{_, _, CostNum}] = CostGood,
    #player_status{gold = HaveGoldNum} = PlayerState,
    if
        HaveGoldNum < CostNum ->
            {false, err340_no_enough_consume};
        true ->
            true
    end.

check_list([]) -> true;
check_list([H|CKList]) ->
    case check(H) of
        true ->
            check_list(CKList);
        {true, _} ->
            check_list(CKList);
        false ->
            false;
        {false, _} ->
            false
    end.


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


% 消耗一般物品的祈愿使用此api
ascend_award_and_decend_good(_WishType, CostGoodList, AwardGoodList, PlayerState) ->
    case lib_goods_api:cost_object_list_with_check(PlayerState, CostGoodList, do_currency_wish_cost, "") of   %先消耗
        {false, Err1, _} ->
            {false, Err1};
        {true, PlayerState1, _} -> 
            PlayerState2 = lib_goods_api:send_reward(PlayerState1, AwardGoodList, do_currency_wish_awards), %后增加
            {ok, PlayerState2}
    end.      

% 消耗彩钻的祈愿使用此api
ascend_award_and_decend_gold(_WishType, CostGood, AwardGoodList, PlayerState) ->
    case check({enough_gold, CostGood, PlayerState}) of      %祈愿前还需要检查消耗彩钻是否足够
        true ->
            case CostGood of
                [] ->
                    PlayerState1 = lib_goods_api:send_reward(PlayerState, AwardGoodList, do_currency_wish_awards), %增加
                    {ok, PlayerState1};
                [{TYPE_GOLD, _GoodTypeId, CostNum}]  ->   
                    {Res, PlayerState1} = lib_goods_api:cost_money(PlayerState, TYPE_GOLD, CostNum, do_currency_wish_cost, ""), %先扣除
                    PlayerState2 = 
                    case Res of
                        1 ->
                            lib_goods_api:send_reward(PlayerState1, AwardGoodList, do_currency_wish_awards); %后增加
                        0 ->
                            PlayerState1
                    end,
                    {ok, PlayerState2}
            end;
        {false, Err2} ->
            {false, Err2}
    end.

% 什么都不做，因为暂时没需求
after_ticket_wish(_CostGoodList, _WishType, PlayerState) ->
    {ok, PlayerState}.


% 交易券祈愿, WishType祈愿类型, Level用户等级, WishCount表示当日已经祈愿的次数
do_ticket_wish(WishType, PlayerState, Level, WishCount) ->

    % 10交易券卡{0, 101014,1}
    [_, Consume, Produce, _, _] = data_currencywish:get_wish_config(WishType, Level, WishCount),
    [{CTYPE_GOOD, CGoodTypeId, _}] = Consume,
    [{CGoodTypeId, CGoodNum}] = lib_goods_api:get_goods_num(PlayerState, [CGoodTypeId]),
    [{PTYPE_GOOD, PGoodTypeId, PBaseNum}] = Produce,

    CostGoodList = [{CTYPE_GOOD, CGoodTypeId, CGoodNum}],
    AwardGoodList = [{PTYPE_GOOD, PGoodTypeId, PBaseNum * CGoodNum}],
    {Flag, NPlayerState} =
    if
        CGoodNum == 0 -> %没有交易券跳过
            {ok, PlayerState};
        true ->
            ascend_award_and_decend_good(WishType, CostGoodList, AwardGoodList, PlayerState)
    end, 

    case Flag of
        ok ->
            {Flag1, NPlayerState1} = after_ticket_wish(CostGoodList, WishType, NPlayerState),
            % 以下参数分别表示：标识位true/false  用户状态PlayerState  暴击倍率  获得的物品
            {Flag1, NPlayerState1, 1, PBaseNum * CGoodNum};
        false ->
            {Flag, NPlayerState}
    end.
   
    
    

    
after_luxury_wish([], WishType, PlayerState) -> % 免费祈愿
    NowTime = utime:unixtime(),
    Role_currencywish = PlayerState#player_status.role_currencywish,
    Lastfreetimemap = Role_currencywish#role_currencywish.lastfreetimemap,
    NPlayerState = PlayerState#player_status{role_currencywish = #role_currencywish{lastfreetimemap = Lastfreetimemap#{WishType := NowTime}}},
    {ok, NPlayerState};
after_luxury_wish(_CostGoodList, WishType, PlayerState) ->  % 付费祈愿
    increment_onecount(PlayerState#player_status.id, ?MOD_CURRENCYWISH, WishType),
    {ok, PlayerState}.

% 豪华祈愿
do_luxury_wish(WishType, PlayerState, Level, WishCount) ->

    [_, Consume, Produce, CritProbability, CritRange] = data_currencywish:get_wish_config(WishType, Level, WishCount),
    [RangeMin, RangeMax] = CritRange,
    RandNumber = urand:rand(1,100),
    CritRate =
    if
        RandNumber =< CritProbability -> %暴击
            urand:rand(RangeMin, RangeMax); %暴击倍率
        true ->
            1    %默认无暴击倍率是1
    end,
    [{CTYPE_GOOD, CGoodTypeId, CGoodNum}] = Consume,
    [{PTYPE_GOOD, PGoodTypeId, PBaseNum}] = Produce,

    AwardGoodList = [{PTYPE_GOOD, PGoodTypeId, PBaseNum * CritRate}],
    
    {Flag, NPlayerState} = 
    case check({cdlimit, WishType, PlayerState}) of
        {true, 0} -> % 免费祈愿
            CostGoodList = [],
            ascend_award_and_decend_gold(WishType, CostGoodList, AwardGoodList, PlayerState);
        _ ->    %扣费祈愿
            CostGoodList = [{CTYPE_GOOD, CGoodTypeId, CGoodNum}],
            ascend_award_and_decend_gold(WishType, CostGoodList, AwardGoodList, PlayerState)
            
    end,
    case Flag of 
        ok ->
            {Flag1, NPlayerState1} = after_luxury_wish(CostGoodList, WishType, NPlayerState),
            {Flag1, NPlayerState1, CritRate, PBaseNum * CritRate};
        false ->
            {Flag, NPlayerState}
    end.



after_experience_wish(_CostGoodList, WishType, PlayerState) ->
    increment_onecount(PlayerState#player_status.id, ?MOD_CURRENCYWISH, WishType),
    {ok, PlayerState}.
% 经验祈愿
do_experience_wish(WishType, PlayerState, Level, WishCount) ->
    [_, Consume, Produce, CritProbability, CritRange] = data_currencywish:get_wish_config(WishType, Level, WishCount),
    [RangeMin, RangeMax] = CritRange,
    RandNumber = urand:rand(1,100),
    CritRate =
    if
        RandNumber =< CritProbability -> %暴击
            urand:rand(RangeMin, RangeMax); %暴击倍率
        true ->
            1    %默认无暴击
    end,
    [{CTYPE_GOOD, CGoodTypeId, CGoodNum}] = Consume,
    [{PTYPE_GOOD, PGoodTypeId, PBaseNum}] = Produce,

    AwardGoodList = [{PTYPE_GOOD, PGoodTypeId, PBaseNum * CritRate}],
    CostGoodList = [{CTYPE_GOOD, CGoodTypeId, CGoodNum}],

    % {Flag, NPlayerState} 
    % case check({cdlimit, WishType, PlayerState}) of
    %     {true, 0} -> % 免费祈愿
    %         ascend_award_and_decend_good(WishType, [], AwardGoodList, PlayerState);
    %     _ ->
    %         ascend_award_and_decend_good(WishType, CostGoodList, AwardGoodList, PlayerState)
    % end,
    % 策划改需求，经验祈愿无免费祈愿
    {Flag, NPlayerState} = ascend_award_and_decend_gold(WishType, CostGoodList, AwardGoodList, PlayerState),
    case Flag of
        ok ->
            {Flag1, NPlayerState1} = after_experience_wish(CostGoodList, WishType, NPlayerState),
            {Flag1, NPlayerState1, CritRate, PBaseNum * CritRate};
        false ->
            {Flag, NPlayerState}
    end.
    


%常规检查已经合法,可以祈愿
do_consumegoods_to_wish(WishType, PlayerState) ->
    #player_status{id = RoleId, figure = Figure, role_currencywish = Role_currencywish} = PlayerState,
    #figure{lv = Level} = Figure,
    CostWishCount = 
    case WishType of
        ?TICKET_WISH ->
            0;
        _ -> % ?LUXURY_WISH or ?EXPERIENCE_WISH 
            cal_costcount(RoleId, ?MOD_CURRENCYWISH, WishType)
    end,

    if
        WishType =:= ?TICKET_WISH ->
            do_ticket_wish(?TICKET_WISH, PlayerState, Level, CostWishCount + 1);  
        WishType =:= ?LUXURY_WISH ->
            FreeWishCount = cal_freecount(WishType, Role_currencywish),
            do_luxury_wish(?LUXURY_WISH, PlayerState, Level, CostWishCount + FreeWishCount + 1);%暂定加1，也就是第十次祈愿用的祈愿十次后的数据
        WishType =:= ?EXPERIENCE_WISH ->
            do_experience_wish(?EXPERIENCE_WISH, PlayerState, Level, CostWishCount + 1);
        true ->
            {false, err340_undefined_currencywish_type}    %非法祈愿类型，
    end.

% gm指定某个祈愿类型当日祈愿次数清零
gm_reset_wishcount(PlayerState, WishType) ->    % 请确保WishType有实际意义否则会崩溃
    #player_status{id = RoleId, role_currencywish = Role_currencywish} = PlayerState,
    #role_currencywish{lastfreetimemap = Lastfreetimemap} = Role_currencywish,

    NLastfreetimemap = Lastfreetimemap#{WishType := 0},  %免费祈愿清零
    NPlayerState = PlayerState#player_status{role_currencywish = Role_currencywish#role_currencywish{lastfreetimemap = NLastfreetimemap}},
    zero_costcount(RoleId, ?MOD_CURRENCYWISH, WishType),    %付费祈愿清零
    pp_currencywish:handle(34001, NPlayerState, []),
    NPlayerState.


