%%% -------------------------------------------------------
%%% @author huangyongxing@yeah.net
%%% @doc
%%% 明日之礼 -> 恭贺礼包 -> 臻享礼包
%%% @end
%%% -------------------------------------------------------
-module(custom_act_hope_gift).
-export([
        receive_reward/4
        ,receive_status/2
        ,get_round_data/2
        ,get_hope_gift_return/2     % 领取返还
        ,hope_gift_draw/3           % 抽奖
        ,handle_event/2
    ]).
-export([
        gm_get_act_data/3           % 打印活动数据 #custom_act_data{}
        ,gm_get_receive_status/3    % 打印个人明日之礼活动领取状态数据
    ]).

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

-ifdef(DEV_SERVER).
-define(DAILY_MAX_DRAW, 1).       % 一天内抽奖次数限制
-else.
-define(DAILY_MAX_DRAW, 1).        % 一天内抽奖次数限制
-endif.

%% 购买明日之礼
%% ** 对应活动公共模块回调接口 **
receive_reward(Player, Type, SubType, GradeId) when Type =:= ?CUSTOM_ACT_TYPE_HOPE_GIFT ->
    case do_receive_reward(Player, Type, SubType, GradeId) of
        {ok, NewPlayer} ->
            send_buy_result(Player#player_status.sid, [?SUCCESS, Type, SubType, GradeId]),
            {ok, NewPlayer};
        {false, ErrCode} when is_integer(ErrCode) ->
            send_buy_result(Player#player_status.sid, [ErrCode, Type, SubType, GradeId]);
        {false, Error} ->
            send_buy_result(Player#player_status.sid, [?ERRCODE(Error), Type, SubType, GradeId])
    end;
receive_reward(_Player, _Type, _SubType, _GradeId) ->
    ok.

%% 购买明日之礼
do_receive_reward(Player, Type, SubType, GradeId) when Type =:= ?CUSTOM_ACT_TYPE_HOPE_GIFT ->
    case lib_custom_act_util:get_custom_act_open_info(Type, SubType) of
        ActInfo = #act_info{etime = _EndTime} ->
            case lib_custom_act_util:get_act_reward_cfg_info(Type, SubType, GradeId) of
                #custom_act_reward_cfg{} = RewardCfg ->
                    case receive_status(Player, RewardCfg, ActInfo) of
                        {false, Error} ->
                            {false, Error};
                        true ->
                            Reward = lib_custom_act_util:count_act_reward(Player, ActInfo, RewardCfg),
                            CanGive = lib_goods_api:can_give_goods(Player, Reward),
                            if
                                CanGive =/= true ->
                                    %% 不能收纳道具（通常是背包空间不足）
                                    {false, err150_no_cell};
                                true  ->
                                    %% 扣东西 + 给奖励
                                    CustomActData = get_custom_act_data_with_check(ActInfo),
                                    buy_hope_gift(Player, RewardCfg, Reward, GradeId, CustomActData)
                            end
                    end;
                _ ->
                    {false, config_err}
            end;
        _False ->
            {false, err331_act_closed}
    end;
do_receive_reward(_Player, _Type, _SubType, _GradeId) ->
    {false, fail}.

%% 获取明日之礼档次购买状态（领取状态）
%% ** 对应活动公共模块回调接口 **
receive_status(Player, RewardCfg = #custom_act_reward_cfg{
        type = Type,
        subtype = SubType
    } ) ->
    ActInfo = lib_custom_act_util:get_custom_act_open_info(Type, SubType),
    receive_status(Player, RewardCfg, ActInfo).

receive_status(Player, #custom_act_reward_cfg{
        type = Type,
        subtype = SubType,
        grade = GradeId
    }, ActInfo) ->
    #figure{vip = VipLv} = Player#player_status.figure,
    #custom_act_data{
        act_data = ActData
    } = get_custom_act_data_with_check(ActInfo),
    #custom_hope_gift{buy_list = BuyList} = ActData,
    NeedVip =
    case lib_custom_act_util:keyfind_act_condition(Type, SubType, vip) of
        {vip, NeedVipX} -> NeedVipX;
        _ -> 0
    end,
    BuyData = lists:keyfind(GradeId, #custom_hope_gift_award.grade_id, BuyList),
    if
        VipLv < NeedVip ->
            % ?INFO("----------vip_limit-"),
            %% VIP等级不足
            {false, vip_limit};
        BuyData =/= false ->
            % ?INFO("-------Had Buy----"),
            %% 已经买过了
            {false, err331_over_limit_num};
        true ->
            % ?INFO("------OK-----"),
            true
    end.

%% 处理购买数据更新
buy_hope_gift(Player, RewardCfg, Reward, GradeId, CustomActData) ->
    #custom_act_reward_cfg{
        type = Type,
        subtype = SubType,
        condition = Condition
    } = RewardCfg,
    case lib_custom_act_check:check_act_condtion([hopegift_cost], Condition) of
        [HopeGiftCost] ->
            CostList = [{?TYPE_GOLD, ?GOODS_ID_GOLD, HopeGiftCost}],
            case lib_goods_api:cost_object_list_with_check(Player, CostList, hopegift_buy, "") of
                {true, PlayerAfCost, _} ->
                    #player_status{id = RoleId, sid = Sid, gold = OldGold,
                        figure = #figure{lv = Level, vip = Vip}
                    } = Player,
                    #custom_act_data{act_data = ActData} = CustomActData,
                    #custom_hope_gift{buy_list = BuyList} = ActData,
                    NowTime = utime:unixtime(),
                    GiftAward = #custom_hope_gift_award{
                        grade_id = GradeId,
                        buy_time = NowTime,
                        cost = HopeGiftCost,
                        got_count = 0
                    },
                    NewBuyList = [GiftAward | BuyList],
                    NewActData = ActData#custom_hope_gift{
                        buy_list = NewBuyList
                    },
                    NewCustomActData = CustomActData#custom_act_data{
                        act_data = NewActData
                        ,time = NowTime
                    },
                    lib_custom_act_data:save_custom_data(RoleId, NewCustomActData),
                    Produce = #produce{
                        type = hopegift_buy,
                        subtype = Type,
                        reward = Reward,
                        remark = util:term_to_string(SubType)
                    },
                    lib_log_api:log_hope_gift_buy(RoleId, SubType, GradeId,
                        HopeGiftCost, OldGold, Reward, Level, Vip, NowTime
                    ),
                    %% 发放奖励
                    NewPlayer = lib_goods_api:send_reward(PlayerAfCost, Produce),
                    %% 推送数据
                    send_round_data(Sid, NewCustomActData),
                    {ok, NewPlayer};
                {false, ErrCode, _NewPlayer} ->
                    {false, ErrCode}
            end;
        _False ->
            {false, config_err}
    end.

%% 获取抽奖轮次资料
get_round_data(Player, SubType) ->
    CustomActData = get_custom_act_data_with_check(?CUSTOM_ACT_TYPE_HOPE_GIFT, SubType),
    #player_status{sid = Sid} = Player,
    send_round_data(Sid, CustomActData).

%% 明日之礼：领取返还
%% -> {Result, NewPlayer}
get_hope_gift_return(Player, SubType) ->
    Type = ?CUSTOM_ACT_TYPE_HOPE_GIFT,
    case lib_custom_act_util:get_custom_act_open_info(Type, SubType) of
        #act_info{etime = _EndTime} = ActInfo ->
            CustomActData = #custom_act_data{
                act_data = ActData
            } = get_custom_act_data_with_check(ActInfo),
            #custom_hope_gift{
                buy_list = BuyList
            } = ActData,
            NowTime = utime:unixtime(),
            Midnight = utime:unixdate(NowTime),
            RewardCfgList = lib_custom_act_util:get_act_reward_cfg_list(Type, SubType),
            {
                NewBuyList, ReturnInfoList,
                _NowTime, _Midnight
            } = lists:foldl(
                fun return_update_buy_list/2,
                {BuyList, [], NowTime, Midnight},
                RewardCfgList
            ),
            case ReturnInfoList of
                [] ->   % 无可领取返还
                    %% 错误码暂时用已经领取替代
                    % GotStatus = to_got_status(GotStatusList),
                    {?ERRCODE(err331_already_get_reward), Player};
                _ ->
                    #player_status{id = RoleId} = Player,
                    ReturnListOfList = [
                        ReturnAwards ||
                        {_GradeId, ReturnAwards, _NewGotCount, _Total} <- ReturnInfoList
                    ],
                    ReturnListMerged = ulists:object_list_merge(lists:append(ReturnListOfList)),
                    %% 是不是可发放
                    CanGive = lib_goods_api:can_give_goods(Player, ReturnListMerged),
                    case CanGive =/= true of
                        true  ->
                            % GotStatus = to_got_status(GotStatusList),
                            {?ERRCODE(err150_no_cell), Player};
                        false ->
                            %% 保存活动数据
                            NewActData = ActData#custom_hope_gift{
                                buy_list = NewBuyList
                            },
                            NewCustomActData = CustomActData#custom_act_data{
                                act_data = NewActData
                                ,time = NowTime
                            },
                            lib_custom_act_data:save_custom_data(RoleId, NewCustomActData),
                            [{GradeId, _, _, _} | _] = ReturnInfoList,
                            %% 发放活动返还内容（批量领取，GradeId择其之一）
                            RewardCfg = #custom_act_reward_cfg{
                                type = Type, subtype = SubType, grade = GradeId
                                ,reward = ReturnListMerged
                            },
                            lib_log_api:log_hope_gift_return_batch(RoleId, SubType, ReturnInfoList, NowTime),
                            NewPlayer = lib_custom_act:custom_act_send_reward(Player, RewardCfg),
                            % NewGotStatus = to_got_status(GotStatusListUpdate ++ GotStatusList),
                            {?SUCCESS, NewPlayer}
                    end
            end;
        _ ->
            %% 活动未开
            {?ERRCODE(err331_act_closed), Player}
    end.

%% 检查是否可返还，并更新已购买列表等活动数据
%% GotStatusList用于统计当前领取状态列表
%% GotStatusListAf用于统计
%% ReturnInfoList用于统计本次会领取到的相关GradeId及奖励等相关信息
return_update_buy_list(RewardCfg, {
        BuyList, ReturnInfoList,
        NowTime, Midnight
    } = Acc) ->
    #custom_act_reward_cfg{
        grade = GradeId
        ,condition = Condition
    } = RewardCfg,
    case lists:keyfind(GradeId, #custom_hope_gift_award.grade_id, BuyList) of
        #custom_hope_gift_award{
            buy_time = _BuyTime,
            last_got_time = LastGotTime
            ,got_count = GotCount
        } = BuyData when LastGotTime < Midnight ->
            %% 当天尚未领取
            case lib_custom_act_check:check_act_condtion(
                    [return_total, return_day], Condition
                ) of
                [{_GoodsTypeId, Total}, _] when Total =< GotCount ->
                    %% 当前档次已经全部返还完
                    {
                        BuyList, ReturnInfoList,
                        NowTime, Midnight
                    };
                [{_, Total}, {GoodsTypeId, DailyCount}] when DailyCount > 0 ->
                    %% 可领取，需要更新领取数量、领取时间
                    % GetStartTime = case LastGotTime =:= 0 of
                    %     true  -> BuyTime;
                    %     false -> LastGotTime
                    % end,
                    % %% 购买当天，GetStartTime计算出DiffDay需要修正为1天
                    % DiffDay = erlang:max(utime:day_span(NowTime, GetStartTime) - 1, 1),
                    % TodayGet = DiffDay * DailyCount,
                    % 只领取当天数量，不进行未领天数累计领取
                    TodayGet = DailyCount,
                    NewCount = GotCount + TodayGet,
                    %% 实际可领数量
                    {NewGotCount, ReallyGet} =
                    case NewCount > Total of
                        true  -> {Total, Total - GotCount};
                        false -> {NewCount, TodayGet}
                    end,
                    NewBuyData = BuyData#custom_hope_gift_award{
                        last_got_time = NowTime
                        ,got_count = NewGotCount
                    },
                    NewBuyList = lists:keystore(
                        GradeId, #custom_hope_gift_award.grade_id,
                        BuyList, NewBuyData
                    ),
                    %% 支持配置几种货币及常规道具，但是通常一经配置则不允许变更类型
                    GainType =
                    case GoodsTypeId of
                        ?GOODS_ID_GOLD  -> ?TYPE_GOLD;
                        ?GOODS_ID_BGOLD -> ?TYPE_BGOLD;
                        ?GOODS_ID_COIN  -> ?TYPE_COIN;
                        ?GOODS_ID_HONOR -> ?TYPE_HONOUR;
                        _               -> ?TYPE_GOODS
                    end,
                    ReturnAwards = [{GainType, GoodsTypeId, ReallyGet}],
                    NewReturnInfoList = [{GradeId, ReturnAwards, NewGotCount, Total} | ReturnInfoList],
                    {
                        NewBuyList, NewReturnInfoList,
                        NowTime, Midnight
                    };
                _ ->
                    %% 配置有问题
                    Acc
            end;
        #custom_hope_gift_award{} ->
            %% 今天领取过了
            Acc;
        _ ->
            %% 没买这个档次
            Acc
    end.

%% 明日之礼：抽奖
%% -> {Result, GotIdList, IsDailyDrawLimit, NewPlayer}
hope_gift_draw(Player, SubType, _Num) ->
    Type = ?CUSTOM_ACT_TYPE_HOPE_GIFT,
    %% 忽略前端请求的次数，改成每天免费抽一次，且只能抽一次
    Num = 1,
    case lib_custom_act_util:get_custom_act_open_info(Type, SubType) of
        #act_info{etime = _EndTime} = ActInfo ->
            CustomActData = #custom_act_data{
                act_data = ActData
            } = get_custom_act_data_with_check(ActInfo),
            #custom_hope_gift{
                round = Round
                ,draw_got_ids = DrawGotIds
                ,draw_count = DrawCount
                ,draw_time = LastDrawTime
            } = ActData,
            NowTime = utime:unixtime(),
            Midnight = utime:unixdate(NowTime),
            TodayDrawCount = fix_daily_draw_count(LastDrawTime, Midnight, DrawCount),
            FixNum =
            case TodayDrawCount + Num > ?DAILY_MAX_DRAW of
                true  -> ?DAILY_MAX_DRAW - TodayDrawCount;
                false -> Num
            end,
            case FixNum > 0 of
                true  ->
                    case lib_custom_act_util:get_act_cfg_info(Type, SubType) of
                        #custom_act_cfg{name = ActName} = _CustomActCfg ->
                            %% 原本设计需要消耗道具(find_draw_goods)，
                            %% 已经改造为不消耗道具，增加限制：需要买齐全部档位
                            case check_buy_all_grade(Type, SubType, ActInfo) of
                                true  ->
                                    case check_round_finished(DrawGotIds, SubType, Round) of
                                        over  ->
                                            %% 全部抽取完成，不能再抽
                                            {?ERRCODE(err331_all_round_over), [], 0, Player};
                                        IsRoundOver ->
                                            NewRound =
                                            case IsRoundOver of
                                                true  -> Round + 1; % 开启新轮次
                                                false -> Round      % 继续当前轮次
                                            end,
                                            AwardIdWeightList = data_hope_gift:get_round_award_id(SubType, NewRound),
                                            RemainList = case IsRoundOver of
                                                true  -> AwardIdWeightList;
                                                false ->
                                                    [
                                                        WeightInfo || WeightInfo = {_, AwardIdX} <- AwardIdWeightList,
                                                        not lists:member(AwardIdX, DrawGotIds)
                                                    ]
                                            end,
                                            do_draw(Player, RemainList, CustomActData, ActName, NewRound, NowTime, TodayDrawCount, Num, FixNum)
                                    end;
                                false ->
                                    {?ERRCODE(err331_act_can_not_get), [], 0, Player}
                            end;
                        _ ->    %% 活动配置有问题
                            {?ERRCODE(config_err), [], 0, Player}
                    end;
                false ->
                    %% 通知没次数
                    {?ERRCODE(err331_daily_max_draw), [], 1, Player}
            end;
        _ ->
            %% 活动未开
            {?ERRCODE(err331_act_closed), [], 1, Player}
    end.

%% 执行抽奖具体的道具扣除、奖励发放及数据存储
do_draw(Player, RemainList = [_|_], CustomActData, ActName, NewRound, NowTime, TodayDrawCount, ReqtNum, FixNum) ->
    #custom_act_data{
        act_data = ActData
        ,subtype = SubType
    } = CustomActData,
    #custom_hope_gift{
        round = Round
        ,draw_got_ids = DrawGotIds
    } = ActData,
    %% 计算抽奖消耗
    RemainLen = length(RemainList),
    GetNum = erlang:min(RemainLen, FixNum),
    % {GoodsTypeId, CostNum} = CostGoods,
    % TotalCostNum = GetNum * CostNum,
    % CostList = [{?TYPE_GOODS, GoodsTypeId, TotalCostNum}],
    %% 计算抽奖产出
    AwardIdList = urand:list_rand_by_weight(RemainList, GetNum),
    {AwardList, TVList} = sum_award_list(AwardIdList, [], []),
    NewAwardList = lib_goods_util:merge_same_goods(AwardList),
    %% ?DEBUG_TTY("calc award: ~p,~n~p,~n~p", [AwardIdList, AwardList, NewAwardList]),
    %% 数据更新保存
    NewDrawGotIds = case Round =/= NewRound of
        true  -> AwardIdList;
        false -> AwardIdList ++ DrawGotIds
    end,
    NewActData = ActData#custom_hope_gift{
        draw_time = NowTime
        ,round = NewRound
        ,draw_got_ids = NewDrawGotIds
        ,draw_count = TodayDrawCount + GetNum
    },
    NewCustomActData = CustomActData#custom_act_data{
        act_data = NewActData
        ,time = NowTime
    },
    #player_status{id = RoleId, sid = Sid, figure = #figure{name = Name}} = Player,
    lib_custom_act_data:save_custom_data(RoleId, NewCustomActData),
    % %% 获取抽奖道具数量
    % [{_, RemainNum}] = lib_goods_api:get_goods_num(PlayerAfCost, [GoodsTypeId]),
    % ItemBefore = RemainNum + TotalCostNum,
    TotalCostNum = 0,
    ItemBefore = 0,
    lib_log_api:log_hope_gift_draw(RoleId, SubType,
        NewAwardList, NewRound, TotalCostNum, ItemBefore, NowTime
    ),
    %% 发放奖励
    NewPlayer = lib_goods_api:send_reward(Player, NewAwardList, hopegift_draw),
    %% 广播
    UniqueTVList = lib_goods_util:merge_same_goods(TVList),
    broadcast_draw_awards(RoleId, Name, ActName, SubType, UniqueTVList),
    %% ?DEBUG_TTY("send: ~p,~n~p", [NewAwardList, UniqueTVList]),
    case ReqtNum =/= FixNum of
        true ->
            %% 通知次数已满
            lib_player_check:send_error_to_sid(Sid, ?ERRCODE(err331_daily_max_draw));
        false ->
            ignore
    end,
    %% 返回结果
    {?SUCCESS, AwardIdList, 0, NewPlayer};
%% 配置错误，取不到有效的权重列表
do_draw(Player, _RemainList, _CustomActData, _ActName, _NewRound, _NowTime, _TodayDrawCount, _ReqtNum, _FixNum) ->
    {?ERRCODE(config_err), [], 0, Player}.

% %% 查找抽奖消耗道具
% find_draw_goods(#custom_act_cfg{condition = Condition}) ->
%     case lib_custom_act_util:keyfind_act_condition(Condition, draw_cost) of
%         {_, Goods = {_GoodsTypeId, _GoodsNum}} ->
%             Goods;
%         _False ->
%             false
%     end;
% find_draw_goods(_) ->
%     false.

%% 计算总奖励
sum_award_list([AwardId | AwardIdList], Acc, TVAcc) ->
    {AwardList, IsTV} = data_hope_gift:get_award(AwardId),
    NewAcc = AwardList ++ Acc,
    NewTVAcc = case IsTV =:= 1 of
        true  -> AwardList ++ TVAcc;
        false -> TVAcc
    end,
    sum_award_list(AwardIdList, NewAcc, NewTVAcc);
sum_award_list([], Acc, TVAcc) ->
    {Acc, TVAcc}.

%% 广播TV消息（即lib_chat send_TV的效果，合并了消息）
broadcast_draw_awards(RoleId, RoleName, ActName, SubType, TVList) ->
    BinDataAll = pack_awards_tv(RoleId, RoleName, ActName, SubType, TVList),
    lib_server_send:send_to_all(BinDataAll),
    ok.

%% 打包奖励列表的TV消息数据
pack_awards_tv(RoleId, Name, ActName, SubType, AwardList) ->
    BinDataList = [
        pack_award_tv(RoleId, Name, ActName, SubType, Award) ||
        Award = {_Type, _GoodsTypeId, _GoodsNum} <- AwardList
    ],
    list_to_binary(BinDataList).

pack_award_tv(_RoleId, Name, ActName, SubType, {_Type, GoodsTypeId, GoodsNum}) ->
    ModuleId = ?MOD_AC_CUSTOM,
    SubId = 2,
    Msg = [Name, GoodsTypeId, GoodsNum, ActName, SubType],
    lib_chat:make_tv(ModuleId, SubId, Msg).

%% 发送购买结果
send_buy_result(Sid, Data = [_ErrCode, _Type, _SubType, _GradeId]) ->
    {ok, BinData} = pt_331:write(33105, Data),
    lib_server_send:send_to_sid(Sid, BinData).

%% 发送抽奖轮次资料
send_round_data(Sid, CustomActData) ->
    #custom_act_data{
        subtype = SubType
        ,act_data = ActData
    } = CustomActData,
    #custom_hope_gift{
        round = Round
        ,buy_list = BuyList
        ,draw_got_ids = GotIdList
        ,draw_count = DrawCount
        ,draw_time = LastDrawTime
    } = ActData,
    Midnight = utime:unixdate(),
    TodayDrawCount = fix_daily_draw_count(LastDrawTime, Midnight, DrawCount),
    IsDailyDrawLimit =
    case TodayDrawCount >= ?DAILY_MAX_DRAW of
        true  -> 1;
        false -> 0
    end,
    GotList = to_get_list(BuyList, Midnight, []),
    {ok, BinData} = pt_331:write(33136, [SubType, Round, IsDailyDrawLimit, GotList, GotIdList]),
    lib_server_send:send_to_sid(Sid, BinData).

%% 根据时间信息修正当天抽奖次数
fix_daily_draw_count(LastDrawTime, Midnight, DrawCount) ->
    case LastDrawTime >= Midnight of
        true  -> DrawCount;
        false -> 0
    end.

%% 抽奖领取状态
to_get_list([BuyData = #custom_hope_gift_award{} | BuyList],
    Midnight, Acc) ->
    #custom_hope_gift_award{
        grade_id = GradeId,
        got_count = GotCount,
        last_got_time = LastGotTime
    } = BuyData,
    TodayGot =
    case LastGotTime >= Midnight of
        true  -> 1;
        false -> 0
    end,
    NewAcc = [ {GradeId, GotCount, TodayGot} | Acc],
    to_get_list(BuyList, Midnight, NewAcc);
to_get_list([_|BuyList], Midnight, Acc) ->
    to_get_list(BuyList, Midnight, Acc);
to_get_list([], _Midnight, Acc) ->
    Acc.

% %% GotStatusList转换数字，以按位分配的方式产生数字
% %% 例如：2#1001 表示4阶、1阶都领取过
% to_got_status(GotStatusList) ->
%     NewList = [GradeId || {GradeId, 1} <- GotStatusList],
%     UList = lists:usort(NewList),
%     to_got_status_2(UList, 0).
%
% to_got_status_2([GradeId | Others], Acc) ->
%     NewAcc = trunc(math:pow(2, GradeId - 1)) + Acc,
%     to_got_status_2(Others, NewAcc);
% to_got_status_2([], Acc) ->
%     Acc.

%% 检查某一轮次是否都抽完了
%% -> true本轮结束 | false本轮未结束 | over全结束
check_round_finished(DrawGotIds, SubType, 0) ->
    check_round_finished(DrawGotIds, SubType, 1);
check_round_finished(DrawGotIds, SubType, Round) ->
    AwardIdWeightList = data_hope_gift:get_round_award_id(SubType, Round),
    case length(DrawGotIds) >= length(AwardIdWeightList) of
        true  ->    % 本轮已经全部抽取完毕
            MaxRound = data_hope_gift:get_max_round(SubType),
            case Round >= MaxRound of
                true  ->    % 所有轮次全部抽取完
                    over;
                false ->    % 开启下一轮
                    true
            end;
        false ->    % 本轮尚未全部抽取完毕
            false
    end.

%% 检查是否购买了所有档次
check_buy_all_grade(Type, SubType, ActInfo) ->
    GradeList = lib_custom_act_util:get_act_reward_grade_list(Type, SubType),
    #custom_act_data{
        act_data = ActData
    } = get_custom_act_data_with_check(ActInfo),
    #custom_hope_gift{buy_list = BuyList} = ActData,
    lists:all(fun(GradeId) ->
                lists:keymember(GradeId, #custom_hope_gift_award.grade_id, BuyList)
        end, GradeList).

%% 角色进程中使用
%% 读取数据并做基本的初始检测
get_custom_act_data_with_check(Type, SubType) ->
    ActInfo = lib_custom_act_util:get_custom_act_open_info(Type, SubType),
    get_custom_act_data_with_check(ActInfo).

%% 读取数据并做基本的初始检测
get_custom_act_data_with_check(ActInfo = #act_info{}) ->
    CustomActData = #custom_act_data{
        act_data = ActData
    } = lib_custom_act_data:custom_act_data(ActInfo),
    case ActData of
        [] ->
            NewActData = #custom_hope_gift{round = 1},
            CustomActData#custom_act_data{
                act_data = NewActData
            };
        #custom_hope_gift{} ->
            CustomActData;
        _Err ->
            %% 可能是数据结构变动，为防止数据意外清空，需要手工管理数据版本变动
            ?ERR("invalid act data:~w", [ActData]),
            CustomActData
    end;
get_custom_act_data_with_check(_False) ->
    ActData = #custom_hope_gift{round = 1},
    #custom_act_data{
        act_data = ActData
    }.

handle_event(Player, #event_callback{type_id = ?EVENT_VIP}) ->
    Type = ?CUSTOM_ACT_TYPE_HOPE_GIFT,
    SubTypeList = lib_custom_act_util:get_subtype_list(Type),
    lists:foreach(fun(SubType) ->
                % ?INFO("vip up -- Type, SubType:~w", [{Type, SubType}]),
                pp_custom_act:handle(33104, Player, [Type, SubType])
        end, SubTypeList),
    {ok, Player};
handle_event(Player, _) ->
    {ok, Player}.

%% GM命令，查询数据用
%%
%% 打印活动数据 #custom_act_data{}
gm_get_act_data(RoleId, Type, SubType) ->
    F = fun(_PS) ->
            Data = lib_custom_act_data:custom_act_data(Type, SubType),
            io:format("[~w]custom_act_data: ~p", [RoleId, Data])
    end,
    gm_util:gm_role_replace_state(RoleId, F),
    ok.

%% 打印个人明日之礼活动领取状态数据
gm_get_receive_status(RoleId, SubType, Grade) ->
    F = fun(PS) ->
            RewardCfg = lib_custom_act_util:get_act_reward_cfg_info(?CUSTOM_ACT_TYPE_HOPE_GIFT, SubType, Grade),
            Ret = custom_act_hope_gift:receive_status(PS, RewardCfg),
            io:format("[~w]receive_status:~p~n", [RoleId, Ret])
    end,
    gm_util:gm_role_replace_state(RoleId, F),
    ok.

