%%-----------------------------------------------------------------------------
%% @Module  :       mod_smashed_egg
%% @Author  :       Czc
%% @Email   :       389853407@qq.com
%% @Created :       2018-03-01
%% @Description:    砸蛋
%%-----------------------------------------------------------------------------
-module(mod_smashed_egg).

-include("custom_act.hrl").
-include("smashed_egg.hrl").
-include("common.hrl").
-include("errcode.hrl").
-include("def_fun.hrl").
-include("def_module.hrl").
-include("goods.hrl").
-include("predefine.hrl").
-include("def_goods.hrl").
-behaviour(gen_server).

-export([start_link/0]).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).

-export([
    send_act_info/5
    , refresh_egg/4
    , smashed_egg/10
    , receive_cumulate_reward/5
    , update_online_time/3
    , act_end/2
    , daily_clear/1
    , check_refresh_egg/4
    , check_smashed_egg/7
    , send_reward_info/3
    , receive_reward/4
    , clean_player_reward/4
    ]).

start_link() ->
    gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).

init([]) ->
    State = lib_smashed_egg:init(#act_state{}),
    {ok, State}.

send_act_info(Type, SubType, RoleId, RoleLv, LastLoginTime) ->
    gen_server:cast(?MODULE, {'send_act_info', Type, SubType, RoleId, RoleLv, LastLoginTime}).

refresh_egg(Type, SubType, RoleId, RoleLv) ->
    gen_server:cast(?MODULE, {'refresh_egg', Type, SubType, RoleId, RoleLv}).

smashed_egg(Type, SubType, RoleId, RoleName, SmashedType, Index, SmashedEggNum, UseFreeTimes, AutoBuy, RealCostList) ->
    gen_server:cast(?MODULE, {'smashed_egg', Type, SubType, RoleId, RoleName, SmashedType, Index, SmashedEggNum, UseFreeTimes, AutoBuy, RealCostList}).

receive_cumulate_reward(Type, SubType, RoleId, RoleLv, Times) ->
    gen_server:cast(?MODULE, {'receive_cumulate_reward', Type, SubType, RoleId, RoleLv, Times}).

%% 玩家每次下线的时候会更新累计的在线时间
update_online_time(RoleId, OnlineFlag, LastLoginTime) ->
    case OnlineFlag of
        ?ONLINE_ON ->
            gen_server:cast(?MODULE, {'update_online_time', RoleId, LastLoginTime});
        _ -> skip
    end.

act_end(EndType, ActInfo) ->
    gen_server:cast(?MODULE, {'act_end', EndType, ActInfo}).

daily_clear(_DelaySec) ->
    gen_server:cast(?MODULE, {'daily_clear'}).

%% 检查刷新金蛋
check_refresh_egg(Type, SubType, RoleId, RoleLv) ->
    gen_server:call(?MODULE, {'check_refresh_egg', Type, SubType, RoleId, RoleLv}).

%% 检查砸金蛋
check_smashed_egg(Type, SubType, RoleId, RoleLv, SmashedType, Index, LastLoginTime) ->
    gen_server:call(?MODULE, {'check_smashed_egg', Type, SubType, RoleId, RoleLv, SmashedType, Index, LastLoginTime}).

%% 发送未领取的奖励列表
send_reward_info(RoleId, Type, SubType) ->
    gen_server:cast(?MODULE, {'send_reward_info', RoleId, Type, SubType}).

%% 一键领取奖励
receive_reward(RoleId, Type, SubType, GoodsId) ->
    gen_server:cast(?MODULE, {'receive_reward', RoleId, Type, SubType, GoodsId}).

%% 清理玩家奖励
clean_player_reward(RoleId, Type, SubType, GoodsId) ->
    gen_server:cast(?MODULE, {'clean_player_reward', RoleId, Type, SubType, GoodsId}).


handle_cast(Msg, State) ->
    case catch do_handle_cast(Msg, State) of
        {ok, NewState} when is_record(NewState, act_state) ->
            {noreply, NewState};
        Err ->
            ?ERR("handle_cast Msg:~p error:~p~n", [Msg, Err]),
            {noreply, State}
    end.

%% 获取活动界面信息
do_handle_cast({'send_act_info', Type, SubType, RoleId, RoleLv, LastLoginTime}, State) ->
    NowTime = utime:unixtime(),
    case lib_smashed_egg:check_act(Type, SubType, RoleLv, NowTime) of
        {true, ActInfo, MaxFreeSmashedTimes, _PaySmashedTimesLim} ->
            #act_info{wlv = WorldLv, stime = Stime, etime = Etime} = ActInfo,
            #act_state{role_map = RoleMap, record_map = RecordMap} = State,
            RoleInfoL = maps:get(RoleId, RoleMap, []),
            case lists:keyfind({Type, SubType}, #role_info.key, RoleInfoL) of
                #role_info{
                    online_time = OnlineTime,
                    lfree_smashed_time = LastFreeSmashedTime,
                    utime = Utime
                } = RoleInfo when Utime >= Stime andalso Utime < Etime ->
                    % RealOnlineTime = max(0, OnlineTime + NowTime - max(Stime, LastLoginTime));
                    RealOnlineTime = max(0, OnlineTime + NowTime - max(max(Stime, LastLoginTime), LastFreeSmashedTime));
                _ ->
                    RoleInfo = lib_smashed_egg:make_role_info(Type, SubType, RoleId, WorldLv, NowTime),
                    RealOnlineTime = max(0, NowTime - max(Stime, LastLoginTime))
            end,
            #role_info{
                eggs = EggsList,
                refresh_times = RefreshTimes,
                % add_refresh_times = AddRefreshTimes,
                smashed_times = SmashedTimes,
                free_smashed_times = FreeSmashedTimes,
                cumulate_reward = CumulateReward
                % show_ids = ShowIds
            } = RoleInfo,
            case data_smashed_egg:get_free_need_oltime(FreeSmashedTimes + 1) of
                false -> %% 没有免费次数了
                    HasFreeTimes = 0,
                    NextFreeSmashedTime = 0;
                NeedOLTime ->
                    HasFreeTimes = lib_smashed_egg:get_free_time(RealOnlineTime, FreeSmashedTimes),
                    NextFreeSmashedTime = NowTime + max(0, NeedOLTime - RealOnlineTime)
            end,
            RecordList = maps:get({Type, SubType}, RecordMap, []),
            RemainFreeRefreshTimes = max(0, MaxFreeSmashedTimes - RefreshTimes),
            % RemainFreeRefreshTimes = max(0, MaxFreeSmashedTimes - RefreshTimes) + AddRefreshTimes,

            % PackShowL = lib_smashed_egg:pack_show_list(ShowIds),
            PackShowL = [],
            PackEggsL = lib_smashed_egg:pack_eggs_list(EggsList),
            PackRecordL = lib_smashed_egg:pack_record_list(RecordList),
            PackCumulateRewardL = lib_smashed_egg:pack_cumulate_reward_list(SmashedTimes, WorldLv, CumulateReward), %% 打包当前奖励列表
            {ok, BinData} = pt_331:write(33120, [Type, SubType, HasFreeTimes, NextFreeSmashedTime, FreeSmashedTimes, RealOnlineTime, RemainFreeRefreshTimes, SmashedTimes, PackShowL, PackEggsL, PackRecordL, PackCumulateRewardL]),
            lib_server_send:send_to_uid(RoleId, BinData),

            NewRoleInfoL = [RoleInfo|lists:keydelete({Type, SubType}, #role_info.key, RoleInfoL)],
            NewRoleMap = maps:put(RoleId, NewRoleInfoL, RoleMap),
            NewState = State#act_state{role_map = NewRoleMap};
        {false, ErrCode} ->
            lib_server_send:send_to_uid(RoleId, pt_331, 33100, [ErrCode]),
            NewState = State;
        _ ->
            NewState = State
    end,
    {ok, NewState};

%% 刷新金蛋
do_handle_cast({'refresh_egg', Type, SubType, RoleId, RoleLv}, State) ->
    NowTime = utime:unixtime(),
    case lib_smashed_egg:check_act(Type, SubType, RoleLv, NowTime) of
        {true, #act_info{wlv = WorldLv, etime = Etime}, MaxFreeSmashedTimes, _PaySmashedTimesLim} when NowTime < Etime ->
            #act_state{role_map = RoleMap} = State,
            RoleInfoL = maps:get(RoleId, RoleMap, []),
            case lists:keyfind({Type, SubType}, #role_info.key, RoleInfoL) of
                RoleInfo when is_record(RoleInfo, role_info) -> skip;
                _ ->
                    RoleInfo = lib_smashed_egg:make_role_info(Type, SubType, RoleId, WorldLv, NowTime)
            end,
            #role_info{
                refresh_times = RefreshTimes,
                add_refresh_times = AddRefreshTimes,
                eggs = Eggs
            } = RoleInfo,
            IsAllSmashed = lib_smashed_egg:is_all_smashed(Eggs),
            case IsAllSmashed of
                true ->
                    NewRefreshTimes = RefreshTimes,
                    NewAddRefreshTimes = AddRefreshTimes;
                _ ->
                    NewAddRefreshTimes = case MaxFreeSmashedTimes >= RefreshTimes of
                        true -> AddRefreshTimes; %% 优先消耗配置的免费次数
                        false -> max(0, AddRefreshTimes - 1)
                    end,
                    NewRefreshTimes = RefreshTimes + 1
            end,
            NewRoleInfo = RoleInfo#role_info{refresh_times = NewRefreshTimes, add_refresh_times = NewAddRefreshTimes, eggs = [#egg_info{id = Index} || Index <- lists:seq(1, ?EGG_NUM)], utime = NowTime},
            lib_smashed_egg:save_role_info(NewRoleInfo), %% 更新数据
            lib_server_send:send_to_uid(RoleId, pt_331, 33121, [?SUCCESS]),
            NewRoleInfoL = [NewRoleInfo|lists:keydelete({Type, SubType}, #role_info.key, RoleInfoL)],
            NewRoleMap = maps:put(RoleId, NewRoleInfoL, RoleMap),
            NewState = State#act_state{role_map = NewRoleMap};
        false ->
            lib_server_send:send_to_uid(RoleId, pt_331, 33100, [?ERRCODE(err331_act_closed)]),
            NewState = State
    end,
    {ok, NewState};

%% 砸蛋
do_handle_cast({'smashed_egg', Type, SubType, RoleId, RoleName, SmashedType, Index, SmashedEggNum, UseFreeTimes, AutoBuy, RealCostList}, State) ->
    NowTime = utime:unixtime(),
    case lib_custom_act_util:get_custom_act_open_info(Type, SubType) of
        #act_info{wlv = WorldLv, etime = Etime} when NowTime < Etime ->
            #act_state{role_map = RoleMap, record_map = RecordMap} = State,
            RoleInfoL = maps:get(RoleId, RoleMap, []),
            RecordL = maps:get({Type, SubType}, RecordMap, []),
            %% 找玩家数据，当玩家第一次玩的时候，新建玩家数据
            case lists:keyfind({Type, SubType}, #role_info.key, RoleInfoL) of
                RoleInfo when is_record(RoleInfo, role_info) -> skip;
                _ ->
                    RoleInfo = lib_smashed_egg:make_role_info(Type, SubType, RoleId, WorldLv, NowTime)
            end,
            #role_info{
                add_refresh_times = AddRefreshTimes,
                lfree_smashed_time = LastFreeSmashedTime,
                free_smashed_times = FreeSmashedTimes,
                online_time = OnlineTime,
                smashed_times = SmashedTimes,
                eggs = EggsL,
                reward_list = OldRewardList
            } = RoleInfo,
            NewFreeSmashedTimes = FreeSmashedTimes + UseFreeTimes,
            NewSmashedTimes = SmashedTimes + SmashedEggNum,
            NewAddRefreshTimes = ?IF(SmashedEggNum == ?EGG_NUM, AddRefreshTimes + 1, AddRefreshTimes), %% 全砸赠送一次刷新次数
            case UseFreeTimes > 0 of
                true ->
                    NewLastFreeSmashedTime = LastFreeSmashedTime,
                    % NewLastFreeSmashedTime = NowTime,
                    NewOnlineTime = OnlineTime;
                _ ->
                    NewLastFreeSmashedTime = LastFreeSmashedTime,
                    NewOnlineTime = OnlineTime
            end,
            case SmashedType of
                ?SMASHED_TYPE_ONE ->
                    {NewEggsL, NewRecordL, TvArgs, RewardL, SmashedResultL} = lib_smashed_egg:smashed_one(RoleId, RoleName, WorldLv, NowTime, Index, EggsL, RecordL);
                _ ->
                    {NewEggsL, NewRecordL, TvArgs, RewardL, SmashedResultL} = lib_smashed_egg:smashed_more(EggsL, RoleId, RoleName, WorldLv, NowTime, RecordL, [], [], [], [])
            end,
            NewRewardList = ulists:object_list_merge(OldRewardList ++ RewardL),
            NewRoleInfo = RoleInfo#role_info{
                add_refresh_times = NewAddRefreshTimes,
                lfree_smashed_time = NewLastFreeSmashedTime,
                free_smashed_times = NewFreeSmashedTimes,
                online_time = NewOnlineTime,
                smashed_times = NewSmashedTimes,
                eggs = NewEggsL,
                utime = NowTime,
                reward_list = NewRewardList
            },
            %% 存数据库
            lib_smashed_egg:save_role_info(NewRoleInfo),
            lib_smashed_egg:save_role_reward_info(RoleId, SubType, NewRewardList),
            NewRoleInfoL = [NewRoleInfo|lists:keydelete({Type, SubType}, #role_info.key, RoleInfoL)],
            NewRoleMap = maps:put(RoleId, NewRoleInfoL, RoleMap),
            NewRecordMap = maps:put({Type, SubType}, NewRecordL, RecordMap),
            lib_server_send:send_to_uid(RoleId, pt_331, 33122, [?SUCCESS, SmashedResultL]),
            %% 日志
            FreeTimesLogTag = ?IF(UseFreeTimes > 0, 1, 0),
            lib_log_api:log_smashed_egg(RoleId, SmashedType, SmashedEggNum, Index, FreeTimesLogTag, AutoBuy, RealCostList, RewardL),
            %% 发传闻
            lib_smashed_egg:send_tv(TvArgs, RoleId, RoleName),
            %% 发奖励（现在改成不立即发，要玩家手动领取）
            % Produce = #produce{type = smashed_egg, title = utext:get(3310008), content = utext:get(204), show_tips = 1, reward = RewardL, remark = "smashed_egg"},
            % lib_goods_api:send_reward_with_mail(RoleId, Produce, ?MOD_AC_CUSTOM),
            % lib_goods_api:send_reward_by_id(RewardL, smashed_egg, 0, RoleId, 1),
            NewState = State#act_state{role_map = NewRoleMap, record_map = NewRecordMap};
        false ->
            lib_server_send:send_to_uid(RoleId, pt_331, 33122, [?ERRCODE(err331_act_closed), []]),
            NewState = State
    end,
    {ok, NewState};

%% 领取累计奖励
do_handle_cast({'receive_cumulate_reward', Type, SubType, RoleId, RoleLv, Times}, State) ->
    NowTime = utime:unixtime(),
    case lib_smashed_egg:check_act(Type, SubType, RoleLv, NowTime) of
        {true, #act_info{wlv = WorldLv}, _MaxFreeSmashedTimes, _PaySmashedTimesLim} ->
            #act_state{role_map = RoleMap} = State,
            RoleInfoL = maps:get(RoleId, RoleMap, []),
            case data_smashed_egg:get_cumulate_reward(Times, WorldLv) of
                #cumulate_reward_cfg{reward = RewardL} ->
                    case lists:keyfind({Type, SubType}, #role_info.key, RoleInfoL) of
                        #role_info{
                            smashed_times = SmashedTimes,
                            cumulate_reward = CumulateRewardL
                        } = RoleInfo when SmashedTimes >= Times ->
                            case lists:member(Times, CumulateRewardL) of
                                false ->
                                    NewRoleInfo = RoleInfo#role_info{
                                        cumulate_reward = [Times|CumulateRewardL],
                                        utime = NowTime
                                    },
                                    lib_smashed_egg:save_role_info(NewRoleInfo),
                                    NewRoleInfoL = [NewRoleInfo|lists:keydelete({Type, SubType}, #role_info.key, RoleInfoL)],
                                    NewRoleMap = maps:put(RoleId, NewRoleInfoL, RoleMap),
                                    PackCumulateRewardL = lib_smashed_egg:pack_cumulate_reward_list(SmashedTimes, WorldLv, CumulateRewardL),
                                    lib_server_send:send_to_uid(RoleId, pt_331, 33123, [?SUCCESS, PackCumulateRewardL]),
                                    lib_goods_api:send_reward_by_id(RewardL, smashed_egg_cumulate_reward, 0, RoleId, 1),
                                    NewState = State#act_state{role_map = NewRoleMap};
                                _ ->
                                    lib_server_send:send_to_uid(RoleId, pt_331, 33100, [?ERRCODE(err331_already_get_reward)]),
                                    NewState = State
                            end;
                        _ ->
                            lib_server_send:send_to_uid(RoleId, pt_331, 33100, [?ERRCODE(err331_act_can_not_get)]),
                            NewState = State
                    end;
                _ ->
                    lib_server_send:send_to_uid(RoleId, pt_331, 33100, [?ERRCODE(err331_no_act_reward_cfg)]),
                    NewState = State
            end;
        {false, ErrCode} ->
            lib_server_send:send_to_uid(RoleId, pt_331, 33100, [ErrCode]),
            NewState = State
    end,
    {ok, NewState};

do_handle_cast({'update_online_time', RoleId, LastLoginTime}, State) ->
    OpenActInfoL = lib_custom_act_api:get_open_custom_act_infos(?CUSTOM_ACT_TYPE_SMASHED_EGG),
    NowTime = utime:unixtime(),
    F = fun(T, TmpState) ->
        case T of
            #act_info{key = {Type, SubType}, wlv = WorldLv, stime = Stime, etime = _Etime} ->
                #act_state{role_map = RoleMap} = State,
                RoleInfoL = maps:get(RoleId, RoleMap, []),
                case lists:keyfind({Type, SubType}, #role_info.key, RoleInfoL) of
                    #role_info{
                        online_time = OnlineTime,
                        lfree_smashed_time = _LastFreeSmashedTime
                    } = RoleInfo ->
                        NeedUpdate = true,
                        RealOnlineTime = max(0, OnlineTime + NowTime - max(Stime, LastLoginTime));
                        % RealOnlineTime = max(0, OnlineTime + NowTime - max(max(Stime, LastLoginTime), LastFreeSmashedTime));
                    _ ->
                        NeedUpdate = false,
                        RoleInfo = lib_smashed_egg:make_role_info(Type, SubType, RoleId, WorldLv, NowTime),
                        RealOnlineTime = max(0, NowTime - max(Stime, LastLoginTime))
                end,
                NewRoleInfo = RoleInfo#role_info{
                    online_time = RealOnlineTime,
                    utime = NowTime
                },
                case NeedUpdate of
                    true ->
                        lib_smashed_egg:save_role_info(NewRoleInfo);
                    _ -> skip
                end,
                NewRoleInfoL = [NewRoleInfo|lists:keydelete({Type, SubType}, #role_info.key, RoleInfoL)],
                NewRoleMap = maps:put(RoleId, NewRoleInfoL, RoleMap),
                State#act_state{role_map = NewRoleMap};
            _ -> TmpState
        end
    end,
    NewState = lists:foldl(F, State, OpenActInfoL),
    {ok, NewState};

do_handle_cast({'act_end', EndType, #act_info{key = {Type, SubType}} = ActInfo}, State) ->
    db:execute(io_lib:format(?sql_delete_smashed_egg, [SubType])),
    #act_state{role_map = RoleMap, record_map = RecordMap} = State,
    case EndType of
        ?CUSTOM_ACT_STATUS_CLOSE ->
            spawn(fun() ->
                timer:sleep(60 * 1000),
                lib_smashed_egg:auto_send_unreceive_reward(maps:to_list(RoleMap), [ActInfo])
            end);
        _ -> skip
    end,
    F = fun(_Key, RoleInfoL) ->
        [T|| T <- RoleInfoL, T#role_info.key =/= {Type, SubType}]
    end,
    NewRoleMap = maps:map(F, RoleMap),
    NewRecordMap = maps:remove({Type, SubType}, RecordMap),
    NewState = State#act_state{role_map = NewRoleMap, record_map = NewRecordMap},
    {ok, NewState};

do_handle_cast({'daily_clear'}, State) ->
    NowTime = utime:unixtime(),
    EggsL = [#egg_info{id = Index} || Index <- lists:seq(1, ?EGG_NUM)],
    EggArgs = [{Id, Status, GoodsId, GoodsNum, Effect} || #egg_info{id = Id, status = Status, goods_id = GoodsId, goods_num = GoodsNum, effect = Effect} <- EggsL],
    db:execute(io_lib:format(?sql_reset_smashed_egg, [0, 0, 0, 0, 0, util:term_to_string(EggArgs), NowTime])),
    #act_state{role_map = RoleMap} = State,
    F1 = fun(RoleInfo) ->
        RoleInfo#role_info{
            online_time = 0,
            lfree_smashed_time = NowTime,
            refresh_times = 0,
            add_refresh_times = 0,
            free_smashed_times = 0,
            eggs = EggsL,
            utime = NowTime
        }
    end,
    F = fun(_RoleId, RoleInfoL) ->
        lists:map(F1, RoleInfoL)
    end,
    NewRoleMap = maps:map(F, RoleMap),
    NewState = State#act_state{role_map = NewRoleMap},
    {ok, NewState};

%% 查看未领取的砸蛋奖励
do_handle_cast({'send_reward_info', RoleId, Type, SubType}, State) ->
    #act_state{role_map = RoleMap} = State,
    RoleInfoL = maps:get(RoleId, RoleMap, []),
    case lists:keyfind({Type, SubType}, #role_info.key, RoleInfoL) of
        #role_info{reward_list = RewardList} -> skip;
        _ -> RewardList = []
    end,
    lib_server_send:send_to_uid(RoleId, pt_331, 33124, [RewardList]),
    {ok, State};

%% 领取所有砸蛋奖励
do_handle_cast({'receive_reward', RoleId, Type, SubType, GoodsId}, State) ->
    #act_state{role_map = RoleMap} = State,
    RoleInfoL = maps:get(RoleId, RoleMap, []),
    case lists:keyfind({Type, SubType}, #role_info.key, RoleInfoL) of
        #role_info{reward_list = RewardList} ->
            lib_player:apply_cast(RoleId, ?APPLY_CAST_SAVE, lib_smashed_egg, receive_reward, [Type, SubType, GoodsId, RewardList]);
        _ ->
            skip
    end,
    {ok, State};

%% 清理玩家奖励数据
do_handle_cast({'clean_player_reward', RoleId, Type, SubType, GoodsId}, State) ->
    #act_state{role_map = RoleMap} = State,
    RoleInfoL = maps:get(RoleId, RoleMap, []),
    case lists:keyfind({Type, SubType}, #role_info.key, RoleInfoL) of
        #role_info{reward_list = OldRewardList} = RoleInfo ->
            %% 清理奖励数据
            if
                GoodsId == 0 -> %% 清空所有
                    NewRoleInfo = RoleInfo#role_info{reward_list = []},
                    db:execute(io_lib:format(?sql_delete_smashed_reward, [RoleId, SubType]));
                true ->
                    NewRoleInfo = RoleInfo#role_info{reward_list = lists:keydelete(GoodsId, 2, OldRewardList)},
                    db:execute(io_lib:format(?sql_delete_smashed_reward_by_goods_id, [RoleId, SubType, GoodsId]))
            end,
            NewRoleInfoL = [NewRoleInfo|lists:keydelete({Type, SubType}, #role_info.key, RoleInfoL)],
            NewRoleMap = maps:put(RoleId, NewRoleInfoL, RoleMap),
            NewState = State#act_state{role_map = NewRoleMap};
        _ ->
            NewState = State
    end,
    {ok, NewState};

do_handle_cast(_Msg, State) -> {ok, State}.

handle_info(Info, State) ->
    case catch do_handle_info(Info, State) of
        {ok, NewState} when is_record(NewState, act_state)->
            {noreply, NewState};
        Err ->
            ?ERR("handle_info Info:~p error:~p~n", [Info, Err]),
            {noreply, State}
    end.

do_handle_info(_Info, State) -> {ok, State}.

handle_call(Request, _From, State) ->
    case catch do_handle_call(Request, State) of
        {ok, Reply} ->
            {reply, Reply, State};
        Err ->
            ?ERR("handle_call Request:~p error:~p~n", [Request, Err]),
            {noreply, State}
    end.

%% 检查刷新金蛋
do_handle_call({'check_refresh_egg', Type, SubType, RoleId, RoleLv}, State) ->
    NowTime = utime:unixtime(),
    case lib_smashed_egg:check_act(Type, SubType, RoleLv, NowTime) of
        {true, _ActInfo, MaxFreeSmashedTimes, PaySmashedTimesLim} ->
            #act_state{role_map = RoleMap} = State,
            RoleInfoL = maps:get(RoleId, RoleMap, []),
            case lists:keyfind({Type, SubType}, #role_info.key, RoleInfoL) of
                #role_info{
                    refresh_times = RefreshTimes,
                    free_smashed_times = FreeSmashedTimes,
                    smashed_times = SmashedTimes,
                    eggs = Eggs
                } ->
                    PaySmashedTimes = SmashedTimes - FreeSmashedTimes,
                    %% 查看是否还有免费砸蛋次数
                    case data_smashed_egg:get_free_need_oltime(FreeSmashedTimes + 1) of
                        false -> HasFreeTimes = 0;
                        _NeedOLTime -> HasFreeTimes = 1
                    end,
                    if
                        PaySmashedTimes >= PaySmashedTimesLim andalso HasFreeTimes == 0 ->
                            {ok, {false, ?ERRCODE(err331_smashed_egg_refresh_fail)}};
                        true ->
                            IsAllSmashed = lib_smashed_egg:is_all_smashed(Eggs),
                            if
                                IsAllSmashed -> {ok, {ok, free}};
                                true ->
                                    RemainFreeRefreshTimes = max(0, MaxFreeSmashedTimes - RefreshTimes),
                                    case RemainFreeRefreshTimes > 0 of
                                        true ->
                                            {ok, {ok, free}};
                                        _ ->  %% 钻石刷新
                                            case lib_custom_act_util:keyfind_act_condition(Type, SubType, refresh_cost) of
                                                {refresh_cost, RefreshCost} -> {ok, {ok, [{?TYPE_GOLD, 0, RefreshCost}]}};
                                                _ -> {ok, {false, ?FAIL}}
                                            end
                                    end
                            end
                    end;
                _ -> {ok, {false, ?FAIL}}
            end;
        {false, ErrCode} -> {ok, {false, ErrCode}};
        _ -> {ok, {false, ?FAIL}}
    end;

%% 砸蛋检查
do_handle_call({'check_smashed_egg', Type, SubType, RoleId, RoleLv, SmashedType, Index, LastLoginTime}, State) ->
    NowTime = utime:unixtime(),
    case lib_smashed_egg:check_act(Type, SubType, RoleLv, NowTime) of
        {true, #act_info{stime = Stime}, _MaxFreeSmashedTimes, PaySmashedTimesLim} ->
            #act_state{role_map = RoleMap} = State,
            RoleInfoL = maps:get(RoleId, RoleMap, []),
            case lists:keyfind({Type, SubType}, #role_info.key, RoleInfoL) of
                #role_info{
                    eggs = EggsL,
                    online_time = OnlineTime,
                    lfree_smashed_time = LastFreeSmashedTime,
                    free_smashed_times = FreeSmashedTimes,
                    smashed_times = SmashedTimes
                } ->
                    % RealOnlineTime = OnlineTime + NowTime - max(Stime, LastLoginTime),
                    RealOnlineTime = OnlineTime + NowTime - max(max(Stime, LastLoginTime), LastFreeSmashedTime),
                    {smash_goods_num, OneUseNum} = lib_custom_act_util:keyfind_act_condition(Type, SubType, smash_goods_num),
                    case SmashedType of
                        ?SMASHED_TYPE_ALL ->
                            F = fun(#egg_info{status = EggStatus}, AccNum) ->
                                case EggStatus of
                                    ?NOT_SMASHED -> AccNum + 1;
                                    _ -> AccNum
                                end
                            end,
                            SmashedEggNum = lists:foldl(F, 0, EggsL),
                            IsSmashed = ?IF(SmashedEggNum > 0, 0, 1),
                            {all_use_num, AllUseNum} = lib_custom_act_util:keyfind_act_condition(Type, SubType, all_use_num),
                            CostNum = ?IF(SmashedEggNum == ?EGG_NUM, AllUseNum, SmashedEggNum * OneUseNum);
                        _ ->
                            IsSmashed = case lists:keyfind(Index, #egg_info.id, EggsL) of
                                #egg_info{status = ?HAS_SMASHED} -> 1;
                                _ -> 0
                            end,
                            SmashedEggNum = 1, CostNum = OneUseNum
                    end,
                    PaySmashedTimes = SmashedTimes - FreeSmashedTimes,
                    if
                        IsSmashed == 1 -> {ok, {false, ?ERRCODE(err331_egg_has_smashed)}};
                        PaySmashedTimes + SmashedEggNum > PaySmashedTimesLim ->
                            {ok, {false, ?ERRCODE(err331_smashed_egg_times_lim)}};
                        true ->
                            FreeTimes = lib_smashed_egg:get_free_time(RealOnlineTime, FreeSmashedTimes),
                            case CostNum - FreeTimes * OneUseNum > 0 of
                                true ->
                                    {smash_goods, GoodsId} = lib_custom_act_util:keyfind_act_condition(Type, SubType, smash_goods),
                                    CostL = [{?TYPE_GOODS, GoodsId, CostNum - FreeTimes * OneUseNum}],
                                    {ok, {ok, CostL, SmashedEggNum, FreeTimes}};
                                false ->
                                    {ok, {ok, free, SmashedEggNum, min(util:ceil(CostNum / OneUseNum), FreeTimes)}}
                            end
                    end;
                _ -> {ok, {false, ?FAIL}}
            end;
        {false, ErrCode} -> {ok, {false, ErrCode}};
        _ -> {ok, {false, ?FAIL}}
    end;

do_handle_call(_Request, _State) -> {ok, ok}.

terminate(_Reason, _State) ->
    ok.

code_change(_OldVsn, State, _Extra) ->
    {ok, State}.
