%%% -------------------------------------------------------
%%% @author huangyongxing@yeah.net
%%% @doc
%%% 珍宝阁（留存抽奖）
%%% @end
%%% -------------------------------------------------------
-module(treasure_house_mgr).

-behaviour(gen_server).

%% API
-export([
        start_link/0
        ,record_awards/4
        ,query_award_record/1
    ]).

%% gen_server callbacks
-export([init/1,
        handle_call/3,
        handle_cast/2,
        handle_info/2,
        terminate/2,
        code_change/3
    ]).
-include("common.hrl").
-include("treasure_house.hrl").

-define(SERVER, ?MODULE).

%% 抽奖记录最大条目数
-define(ITEM_COUNT_MAX, 50).           % 标准最大值（每次处理截断时的最大值）
-define(ITEM_COUNT_MAX_REAL, 80).      % 实际最大值（弹性的最大值）

%% 进程状态数据
-record(proc_state, {
        award_records = []
        ,count = 0
    }).

%%%===================================================================
%%% API
%%%===================================================================

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

%% 记录“抽奖产出”
record_awards(RoleId, RoleName, Awards, Time) ->
    GoodsList = [{GoodsTypeId, GoodsNum} || {_, GoodsTypeId, GoodsNum} <- Awards],
    gen_server:cast(?SERVER, {record_awards, RoleId, RoleName, GoodsList, Time}).

%% 查询“珍宝阁产出记录”
query_award_record(RoleSid) ->
    gen_server:cast(?SERVER, {query_award_record, RoleSid}).

%%%===================================================================
%%% gen_server callbacks
%%%===================================================================

init([]) ->
    process_flag(trap_exit, true),
    % AwardRecords = load_data(),
    AwardRecords = [],
    Count = length(AwardRecords),
    {ok, #proc_state{
            award_records = AwardRecords
            ,count = Count
        }}.

handle_call(_Request, _From, State) ->
    {noreply, State}.

handle_cast(Msg, State) ->
    try
        do_handle_cast(Msg, State)
    catch
        ?EXCEPTION(_ErrorClass, _Error, _Stacktrace) ->
            ?ERR("handle_cast Msg:~w, Error:~w, ~w", [Msg, _Error, ?GET_STACK(_Stacktrace)]),
            {noreply, State}
    end.

handle_info(_Info, State) ->
    {noreply, State}.

terminate(_Reason, _State = #proc_state{award_records = _AwardRecords}) ->
    % db_save_award_records(AwardRecords),
    ok.

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

%% 记录产出奖励信息
do_handle_cast({record_awards, RoleId, RoleName, GoodsList, Time}, State) ->
    AddAwardRecords = [
        to_award_record(RoleId, RoleName, GoodsTypeId, GoodsNum, Time) ||
        {GoodsTypeId, GoodsNum} <- GoodsList
    ],
    #proc_state{
        award_records = AwardRecords
        ,count = Count
    } = State,
    TmpAwardRecords = AddAwardRecords ++ AwardRecords,
    {NewCount, NewAwardRecords} =
    case Count >= ?ITEM_COUNT_MAX_REAL of
        true  ->
            {?ITEM_COUNT_MAX, lists:sublist(TmpAwardRecords, ?ITEM_COUNT_MAX)};
        false ->
            {Count + length(AddAwardRecords), TmpAwardRecords}
    end,
    NewState = State#proc_state{
        award_records = NewAwardRecords
        ,count = NewCount
    },
    send_award_records(all, false, AddAwardRecords),
    {noreply, NewState};

%% 查询抽奖/累计次数奖励记录
do_handle_cast({query_award_record, RoleSid}, State = #proc_state{
        award_records = AwardRecords
        ,count = Count
    }) ->
    VisibleLen = erlang:min(Count, ?ITEM_COUNT_MAX),
    DataList =
    case Count > VisibleLen of
        true  -> lists:sublist(AwardRecords, VisibleLen);
        false -> AwardRecords
    end,
    send_award_records(RoleSid, true, DataList),
    {noreply, State};

do_handle_cast(_, State) ->
    {noreply, State}.

%%%===================================================================
%%% Internal functions
%%%===================================================================

% load_data() ->
%     Sql = util:fmt_bin(?SQL_SELECT_PELLET_AWARD_RECORD_RECENTLY, [?ITEM_COUNT_MAX]),
%     DbDataList = db:get_all(Sql),
%     [
%         erlang:apply(fun to_award_record/6, Data) || Data = [_,_,_,_,_,_] <- DbDataList
%     ].

to_award_record(RoleId, RoleName, GoodsTypeId, GoodsNum, Time) ->
    #thouse_award_record{
        role_id = RoleId
        ,name = RoleName
        ,goods_type_id = GoodsTypeId
        ,goods_num = GoodsNum
        ,time = Time
    }.

to_cli_data(#thouse_award_record{
        role_id = RoleId
        ,name = RoleName
        ,goods_type_id = GoodsTypeId
    }) ->
    {RoleId, RoleName, GoodsTypeId}.

send_award_records(NoticeObject, IsAll, AwardRecords) ->
    Cmd =
    case IsAll of
        true  -> 10406;
        false -> 10407
    end,
    DataList = [
        to_cli_data(AwardRecord) || AwardRecord <- AwardRecords
    ],
    {ok, BinData} = pt_104:write(Cmd, [DataList]),
    case NoticeObject of
        all -> lib_server_send:send_to_all(BinData);
        _   -> lib_server_send:send_to_sid(NoticeObject, BinData)
    end.

% db_save_award_records(AwardRecords) ->
%     DataFmtFun = fun fmt_award_record/1,
%     SqlPrefix = ?SQL_REPLACE_PELLET_AWARD_RECORD_HEAD,
%     udb:save_data_list(AwardRecords, SqlPrefix, DataFmtFun).
% 
% fmt_award_record(#pellet_award_record{
%         role_id = RoleId
%         ,name = RoleName
%         ,goods_type_id = GoodsTypeId
%         ,goods_num = GoodsNum
%         ,get_type = GetType
%         ,time = Time
%     }) ->
%     util:fmt_bin("(~w,'~ts',~w,~w,~w,~w)", [
%             RoleId, RoleName, GoodsTypeId, GoodsNum, GetType, Time
%         ]).
