%%-----------------------------------------------------------------------------
%% @Module  :       lib_lucky_turntable.erl
%% @Author  :       J
%% @Email   :       j-som@foxmail.com
%% @Created :       2018-03-31
%% @Description:    幸运转盘
%%-----------------------------------------------------------------------------
-module (lib_lucky_turntable).

-include("server.hrl").
-include("figure.hrl").
-include("custom_act.hrl").
-include("def_event.hrl").
-include("def_goods.hrl").
-include("def_fun.hrl").
-include("rec_event.hrl").
-include("lucky_turntable.hrl").
-include("errcode.hrl").
-include("common.hrl").
-include("def_module.hrl").

-export([
    handle_event_consume/3
    ,handle_event_recharge/3
    ,send_act_info/3
    ,turn_table/4
    ]).

-export([
    send_reward_status/2
    ]).

% -compile(export_all).

%% 消费&充值后次数的更新
handle_event_consume(Player, ActInfos, MoneyMap) ->
    #player_status{id = RoleId, figure = #figure{lv = Lv}, gold = NewGold} = Player,
    OldGold = maps:get(old_gold, MoneyMap, undefined),
    if is_integer(OldGold) andalso OldGold > NewGold -> %% 消费了
            Cost = round(OldGold - NewGold),
            update_turntable_times(consume, ActInfos, RoleId, Lv, Cost);
        true -> %% 没有消费行为
            skip
    end,
    ok.

handle_event_recharge(Player, ActInfos, #callback_recharge_data{gold = Gold}) ->
    #player_status{id = RoleId, figure = #figure{lv = Lv}} = Player,
    update_turntable_times(recharge, ActInfos, RoleId, Lv, Gold),
    ok.

%% 查询轮盘信息
send_act_info(Player, SubType, TurnType) ->
    #player_status{id = _RoleId, sid = Sid, figure = #figure{lv = RoleLv}} = Player,
    Type = ?CUSTOM_ACT_TYPE_LUCKY_TURNTABLE,
    case lib_custom_act_api:get_open_custom_act_infos(Type) of
        StartActs = [_|_] ->
            case lists:filter(fun(#act_info{key = {_, SubTypeX}}) -> 
                if SubType == SubTypeX -> true;
                    true -> false
                end
            end, StartActs) of
                [#act_info{}|_] ->
                    #custom_act_data{act_data = ActData} = lib_custom_act_data:custom_act_data(Type, SubType),
                    case ActData of
                        #lucky_turntable_data{times = Times, recharge = Recharge, consume = Consume} ->
                            BinInfo = pack_turntable_act_info(SubType, TurnType, RoleLv, Times, Recharge, Consume),
                            lib_server_send:send_to_sid(Sid, BinInfo);
                        _ -> %?ERR("~p ~p", [SubType, ActData]),
                            BinInfo = pack_turntable_act_info(SubType, TurnType, RoleLv, [{?TABLE_1, 0, 0}, {?TABLE_2, 0, 0}], 0, 0),
                            lib_server_send:send_to_sid(Sid, BinInfo)
                    end;
                _ ->
                    BinInfo = pack_turntable_act_info(SubType, TurnType, RoleLv, [], 0, 0),
                    lib_server_send:send_to_sid(Sid, BinInfo)
            end;
        _ ->
            BinInfo = pack_turntable_act_info(SubType, TurnType, RoleLv, [], 0, 0),
            lib_server_send:send_to_sid(Sid, BinInfo)
    end.

%% 转轮盘
turn_table(PS, SubType, TurnType, Skip) ->
    #player_status{id = RoleId, sid = Sid, figure = #figure{lv = RoleLv}} = PS,
    case check_turn_table(RoleId, RoleLv, SubType, TurnType) of
        {true, CustomData, _SuitId, SuitCfg} ->
            do_turn_table(PS, SubType, TurnType, CustomData, SuitCfg, Skip);
        {false, Errcode} -> %?ERR("~p", [Errcode]),
            {ok, BinData} = pt_332:write(33203, [SubType, TurnType, Errcode, 0, []]),
            lib_server_send:send_to_sid(Sid, BinData)
    end.

-spec do_turn_table(Player, SubType, TurnType, CustomData, SuitCfg, Skip) -> term() when
    Player  :: #player_status{},
    SubType :: integer(),
    TurnType :: ?TABLE_1 | ?TABLE_2,
    CustomData :: #custom_act_data{},
    SuitCfg :: #base_lucky_turntable{},
    Skip :: 0|1.
do_turn_table(Player, SubType, TurnType, CustomData, SuitCfg, Skip) ->
    #player_status{id = RoleId, figure = #figure{name = RoleName, lv = RoleLv, vip = Vip}} = Player,
    #custom_act_data{act_data = ActData} = CustomData,
    #lucky_turntable_data{times = Times} = ActData,
    {_, UseCount, TotalCount} = lists:keyfind(TurnType, 1, Times),
    WeightList = get_weight_list_by_turn_type(TurnType, SuitCfg),
    WeightList1 = [{Weight, Element} || {Element, Weight} <- WeightList],
    TableGrade = urand:rand_with_weight(WeightList1),
    Type = ?CUSTOM_ACT_TYPE_LUCKY_TURNTABLE,
    case lib_custom_act_util:get_act_reward_cfg_info(Type, SubType, TableGrade) of
        #custom_act_reward_cfg{reward = Reward = [{_GoodsType, GoodsId, GoodsNum}|_]} ->
            %% 发奖
            NewPlayer = lib_goods_api:send_reward(Player, Reward, turntable_reward),
            %% 更新次数
            NewTimes = lists:keyreplace(TurnType, 1, Times, {TurnType, UseCount+1, TotalCount}),
            NewActData = ActData#lucky_turntable_data{times = NewTimes},
            NewCustomData = CustomData#custom_act_data{act_data = NewActData},
            lib_custom_act_data:save_custom_data(RoleId, NewCustomData),
            %% 新增转盘记录
            if Skip =/= 0 ->
                    lib_chat:send_TV({all}, ?MOD_AC_CUSTOM, 22, [RoleName, GoodsId, GoodsNum, SubType]),
                    mod_lucky_turntable:add_record(SubType, TurnType, RoleId, RoleName, GoodsId, GoodsNum);
                true ->
                    spawn(fun() ->
                        timer:sleep(3000),
                        lib_chat:send_TV({all}, ?MOD_AC_CUSTOM, 22, [RoleName, GoodsId, GoodsNum, SubType]),
                        mod_lucky_turntable:add_record(SubType, TurnType, RoleId, RoleName, GoodsId, GoodsNum)
                    end)
            end,
            {ok, BinData} = pt_332:write(33203, [SubType, TurnType, ?SUCCESS, TableGrade, Reward]),
            %% 日志
            NowTime = utime:unixtime(),
            WLv     = util:get_world_lv(),
            lib_log_api:log_custom_act_reward(RoleId, Type, SubType, TableGrade, WLv, Reward, [],
                Vip, RoleLv, Player#player_status.gold, NewPlayer#player_status.gold, Player#player_status.bgold, NewPlayer#player_status.bgold, NowTime),
            lib_server_send:send_to_uid(RoleId, BinData),
            {ok, NewPlayer};
        _  ->
            % ?ERR("turntable reward error ~p ~p", [SubType, TableGrade]),
            {ok, BinData} = pt_332:write(33203, [SubType, TurnType, ?FAIL, TableGrade, []]),
            lib_server_send:send_to_uid(RoleId, BinData),
            ok
    end.

%% 通用查询奖励状态
send_reward_status(Player, ActInfo) ->
    #act_info{key = {Type, SubType}} = ActInfo,
    GradeIds = lib_custom_act_util:get_act_reward_grade_list(Type, SubType),
    F = fun(GradeId, Acc) ->
        case lib_custom_act_util:get_act_reward_cfg_info(Type, SubType, GradeId) of
            #custom_act_reward_cfg{
                name      = Name,
                desc      = Desc,
                condition = Condition,
                format    = Format,
                reward    = Reward
            } ->
                ConditionStr = util:term_to_string(Condition),
                RewardStr = util:term_to_string(Reward),
                [{GradeId, Format, 0, 0, 0, Name, Desc, ConditionStr, RewardStr} | Acc];
            _ -> Acc
        end
    end,
    PackList = lists:foldl(F, [], GradeIds),
    {ok, BinData} = pt_331:write(33104, [Type, SubType, PackList]),
    lib_server_send:send_to_sid(Player#player_status.sid, BinData).

get_weight_list_by_turn_type(?TABLE_1, #base_lucky_turntable{weight_lucky = LuckyWeight}) ->
    LuckyWeight;
get_weight_list_by_turn_type(?TABLE_2, #base_lucky_turntable{weight_suprise = SupriseWeight}) ->
    SupriseWeight.

%% 检查转轮盘条件
check_turn_table(_RoleId, RoleLv, SubType, TurnType) ->
    Type = ?CUSTOM_ACT_TYPE_LUCKY_TURNTABLE,
    #custom_act_cfg{condition = Condition} = get_act_cfg(Type, SubType),
    case lib_custom_act_api:is_open_act(Type, SubType) of
        true ->
            case lib_custom_act_check:check_act_condtion([role_lv, suit], Condition) of
                [LvCfg, SuitId|_] when LvCfg =< RoleLv ->
                    if TurnType =/= ?TABLE_1 andalso TurnType =/= ?TABLE_2 ->
                            {false, ?FAIL};
                        true ->
                            #custom_act_data{act_data = ActData} = CustomData = lib_custom_act_data:custom_act_data(Type, SubType),
                            case ActData of
                                #lucky_turntable_data{times = Times} ->
                                    case lists:keyfind(TurnType, 1, Times) of
                                        {_, UseCount, TotalCount} when UseCount < TotalCount ->
                                            case data_lucky_turntable:get_turntable_cfg(SuitId, UseCount+1) of
                                                SuitCfg = #base_lucky_turntable{} ->
                                                    {true, CustomData, SuitId, SuitCfg};
                                                _ -> % ?ERR("~p ~p ~p", [TurnType, SuitId, UseCount+1]),
                                                    {false, ?FAIL}
                                            end;
                                        _ ->
                                            {false, ?ERRCODE(err331_turntable_times_limit)}
                                    end;
                                _ ->
                                    {false, ?ERRCODE(err331_turntable_times_limit)}
                            end
                    end;
                _ ->
                    {false, ?LEVEL_LIMIT}
            end;
        _ ->
            {false, ?ERRCODE(err331_act_closed)}
    end.

pack_turntable_act_info(SubType, TurnType, _RoleLv, [], Recharge, Consume) ->
    {ok, BinInfo} = pt_332:write(33202, [SubType, TurnType, 0, 0, 0, Recharge, 0, Consume, 0]),
    BinInfo;
pack_turntable_act_info(SubType, TurnType, RoleLv, Times, Recharge, Consume) ->
    case lists:keyfind(TurnType, 1, Times) of
        {_, UseCount, TotalCount} -> ok;
        _   -> UseCount = 0, TotalCount = 0
    end,
    #custom_act_cfg{condition = Condition} = get_act_cfg(?CUSTOM_ACT_TYPE_LUCKY_TURNTABLE, SubType),
    case lib_custom_act_check:check_act_condtion([role_lv, suit], Condition) of
        [LvCfg, SuitId|_] when RoleLv >= LvCfg ->
            case data_lucky_turntable:get_turntable_cfg(SuitId, TotalCount+1) of
                #base_lucky_turntable{type = TurnCfgs, golds = Golds} ->
                    NeedRecharge = calc_gold_need_2(recharge, TurnCfgs, Golds, TurnType, Recharge),
                    NeedConsume  = calc_gold_need_2(consume, TurnCfgs, Golds, TurnType, Consume);
                _ ->
                    NeedRecharge = 0, NeedConsume = 0
            end,
            case data_lucky_turntable:get_suit_times(SuitId) of
                TimesCfg = [_|_] ->
                    MaxTimes = lists:max(TimesCfg);
                _ ->
                    MaxTimes = 0
            end;
        _ ->
            MaxTimes = 0, NeedRecharge = 0, NeedConsume = 0
    end,
    {ok, BinInfo} = pt_332:write(33202, [SubType, TurnType, MaxTimes, TotalCount, UseCount, Recharge, NeedRecharge, Consume, NeedConsume]),
    BinInfo.

%%
-spec update_turntable_times(MoneyType, ActInfos, RoleId, RoleLv, Gold) -> term() when
    MoneyType :: recharge | consume,
    ActInfos  :: [#act_info{}, ...],
    RoleId    :: integer(),
    RoleLv    :: integer(),
    Gold      :: integer(). 
update_turntable_times(MoneyType, ActInfos, RoleId, RoleLv, Gold) ->
    Type = ?CUSTOM_ACT_TYPE_LUCKY_TURNTABLE,
    lists:map(fun(#act_info{key = {_, SubType}}) ->
        #custom_act_cfg{condition = Condition} = get_act_cfg(Type, SubType),
        case lib_custom_act_check:check_act_condtion([role_lv, suit], Condition) of
            [LvCfg, SuitId|_] when RoleLv >= LvCfg ->
                update_turntable_times_do(Type, SubType, SuitId, RoleId, MoneyType, Gold);
            _ -> % ?ERR("lv limit ~p", [RoleLv]),
                skip
        end
    end, ActInfos).

update_turntable_times_do(Type, SubType, SuitId, RoleId, MoneyType, Gold) ->
    #custom_act_data{act_data = ActData} = CustomData = lib_custom_act_data:custom_act_data(Type, SubType),
    case ActData of
        #lucky_turntable_data{} -> ActData1 = ActData;
        _  -> ActData1 = #lucky_turntable_data{times = [{?TABLE_1, 0, 0}, {?TABLE_2, 0, 0}]}
    end,
    #lucky_turntable_data{recharge = Recharge, consume = Consume} = ActData1,
    if MoneyType == recharge ->
            ActData2 = ActData1#lucky_turntable_data{recharge = round(Recharge + Gold)};
        true -> %% consume
            ActData2 = ActData1#lucky_turntable_data{consume = round(Consume + Gold)}
    end,    
    MoneyNeed = calc_gold_need_1(SuitId, ActData1),
    NewActData = lists:foldl(fun({TableType, NeedGoldList}, TempActData) ->
        % {Count, IncreType, MoneyNeedNum}
        SortNeedGoldList = lists:keysort(1, NeedGoldList),
        update_lucky_turntable_money_data(Recharge, Consume, TempActData, TableType, SortNeedGoldList, MoneyType)
    end, ActData2, MoneyNeed),
    % ?ERR("~p ~p ~p", [SubType, NewActData, ActData1]),
    ?IF(NewActData =/= ActData1, lib_custom_act_data:save_custom_data(RoleId, CustomData#custom_act_data{act_data = NewActData}), ok),
    ok.

-spec update_lucky_turntable_money_data(OldRecharge, OldConsume, ActData, TableType, NeedGoldList, MoneyType) -> NewActData when
    OldRecharge :: integer(),               %% 旧充值累计
    OldConsume :: integer(),                %% 旧彩钻消费累计
    ActData :: #lucky_turntable_data{},     %% 转盘数据
    TableType :: ?TABLE_1 | ?TABLE_2,       %% 转盘档次类型
    NeedGoldList :: [{Count, IncreType, MoneyNeed}] | list(),   %% 潜在可新增的次数及其条件
    Count     :: integer(),                 %% 潜在可新增次数
    IncreType :: recharge | consume,        %% 触发次数增加类型
    MoneyNeed :: integer(),                 %% 触发次数所需彩钻数
    MoneyType :: recharge | consume,        %% 事件触发类型
    NewActData :: #lucky_turntable_data{}.
update_lucky_turntable_money_data(OldRecharge, OldConsume, ActData, TableType, NeedGoldList, MoneyType) ->
    #lucky_turntable_data{recharge = NewRecharge, consume = NewConsume} = ActData,
    NewActData = lists:foldl(fun({Count, IncreType, MoneyNeed}, TempActData) ->
        #lucky_turntable_data{times = TempTimes} = TempActData,
        if  
            MoneyType == IncreType ->
                if MoneyType == recharge ->
                        if OldRecharge < MoneyNeed andalso NewRecharge >= MoneyNeed ->
                                NewTempTimes =
                                case lists:keyfind(TableType, 1, TempTimes) of
                                    {_, UseCount, TotalCount} ->
                                        NewTotalCount = max(TotalCount, Count),
                                        lists:keyreplace(TableType, 1, TempTimes, {TableType, UseCount, NewTotalCount});
                                    _ ->
                                        lists:keystore(TableType, 1, TempTimes, {TableType, 0, Count})
                                end;
                            true ->
                                NewTempTimes = TempTimes
                        end,
                        TempActData#lucky_turntable_data{times = NewTempTimes};
                    true -> %% consume
                        if OldConsume < MoneyNeed andalso NewConsume >= MoneyNeed ->
                                NewTempTimes =
                                case lists:keyfind(TableType, 1, TempTimes) of
                                    {_, UseCount, TotalCount} ->
                                        NewTotalCount = max(TotalCount, Count),
                                        lists:keyreplace(TableType, 1, TempTimes, {TableType, UseCount, NewTotalCount});
                                    _ ->
                                        lists:keystore(TableType, 1, TempTimes, {TableType, 0, Count})
                                end;
                            true ->
                                NewTempTimes = TempTimes
                        end,
                        TempActData#lucky_turntable_data{times = NewTempTimes}
                end;
            true ->
                TempActData
        end
    end, ActData, NeedGoldList),
    NewActData.


%% 计算新增次数所需的总彩钻数
-spec calc_gold_need_1(SuitId, ActData) -> MoneyNeed when
    SuitId  :: integer(),               %% 套件id,活动条件配置获取
    ActData :: #lucky_turntable_data{},
    MoneyNeed :: [{TableType, [{Count, IncreType, MoneyNeedCfg}, ...]}, ...] | list(),
    TableType :: ?TABLE_1 | ?TABLE_2,   %% 转盘档次类型
    Count :: integer(),                 %% 新增的次数
    IncreType :: recharge | consume,    %% 触发次数增加类型
    MoneyNeedCfg :: integer().          %% 所需彩钻数
calc_gold_need_1(SuitId, #lucky_turntable_data{times = Times}) ->
    case Times of
        [_|_] -> Times1 = Times;
        _     -> Times1 = [{?TABLE_1, 0, 0}, {?TABLE_2, 0, 0}]
    end,
    SuitTimesCfg = data_lucky_turntable:get_suit_times(SuitId),
    AccessTimes = lists:foldl(fun({TableType, _UseCount, Count}, Acc) -> 
        FilterSuitTimes = lists:filter(fun(SuitTime) -> SuitTime > Count end, SuitTimesCfg),
        [{TableType, FilterSuitTimes}|Acc]        
    end, [], Times1),
    MoneyNeed = lists:foldl(fun({TableTypeX, CountL}, Acc) ->
        lists:foldl(fun(CountX, TempAcc) -> 
            case data_lucky_turntable:get_turntable_cfg(SuitId, CountX) of
                #base_lucky_turntable{type = IncreTypeCfg, golds = Golds} ->
                    case lists:keyfind(TableTypeX, 1, IncreTypeCfg) of
                        {_, IncreType} ->
                            case lists:keyfind(TableTypeX, 1, Golds) of
                                {_, MoneyNeedCfg} -> 
                                    case lists:keyfind(TableTypeX, 1, TempAcc) of
                                        {_, TableTypeAcc} ->
                                            NewTableTypeAcc = [{CountX, IncreType, MoneyNeedCfg}|TableTypeAcc];
                                        _ ->
                                            NewTableTypeAcc = [{CountX, IncreType, MoneyNeedCfg}]
                                    end,
                                    lists:keystore(TableTypeX, 1, TempAcc, {TableTypeX, NewTableTypeAcc});
                                _   -> TempAcc
                            end;
                        _ -> TempAcc
                    end;
                _ -> TempAcc
            end
        end, Acc, CountL)
    end, [], AccessTimes),
    MoneyNeed.

%% 计算新增次数还需要多少彩钻数
-spec calc_gold_need_2(RechargeType, TurnCfgs, Golds, TurnType, Gold) -> integer() when
    RechargeType :: recharge | consume,
    TurnCfgs :: list(),                 %% 两档转盘的类型
    Golds :: list(),                    %% 两档转盘需要的彩钻数
    TurnType :: ?TABLE_1 | ?TABLE_2,    %% 转盘档次类型
    Gold :: integer().                  %% 当前充值|消费总彩钻数
calc_gold_need_2(RechargeType, TurnCfgs, Golds, TurnType, Gold) ->
    case lists:keyfind(RechargeType, 2, TurnCfgs) of
        {TurnTypeCfg, _} ->
            if TurnTypeCfg == TurnType ->
                    case lists:keyfind(TurnType, 1, Golds) of
                        {_, TotalNeedGold} -> max(0, round(TotalNeedGold - Gold));
                        _   -> 0
                    end;
                true -> 
                    0
            end;
        _ -> 
            0
    end.    

get_act_cfg(ActType, SubType) ->
    case lib_custom_act_util:get_act_cfg_info(ActType, SubType) of
        Cfg = #custom_act_cfg{} -> Cfg;
        _   -> #custom_act_cfg{}
    end.
