%%%-----------------------------------------------------------------------------
%%%	@Module  : lib_designation_api
%%% @Author  : liuxl
%%% @Email   : liuxingli@suyougame.com
%%% @Created : 2016-11-21
%%% @Description : 称号系统
%%%-----------------------------------------------------------------------------
-module(lib_designation_api).
-include("server.hrl").
-include("predefine.hrl").
-include("common.hrl").
-include("designation.hrl").
-include("def_event.hrl").
-include("rec_event.hrl").
-include("def_fun.hrl").
-include("def_goods.hrl").
%% -include_lib("stdlib/include/ms_transform.hrl").

-export([
         handle_event/2,            %% 事件回调
         batch_active_dsgt_common/2,%% 邮件通用批量激活称号
         active_dsgt_common/2,      %% 其他进程调用激活称号通用接口; 玩家进程调用激活称号:lib_designation:active_dsgt
         % active_dsgt_common/4,
         % active_global_dsgt/2,      %% 激活全局称号
         active_global_dsgt/4,      %% 激活全局称号
         cancel_dsgt/2,             %% 取消称号
         cancel_dsgt_online/2,      %% 取消称号(玩家在线的时候使用)
         get_dsgt_name/1
        ]).

-export([
    get_dsgt/1
    ]).

%% 玩家进程回调事件处理
handle_event(PS, _Event) ->
    {ok, PS}.

%% 是否是体验道具
is_dsgt_trial(GoodsId) ->
    TrialDsgt = data_designation:get_all_trial_goods(),
    lists:member(GoodsId, TrialDsgt).

get_dsgt_trial(GoodsId) ->
    case data_designation:get_trial_dsgt(GoodsId) of
        #base_dsgt_trial{dsgt_id = DsgtId, trial_time = TrialTime, is_overlay = IsOverlay} -> ok;
        _ -> DsgtId = 0, TrialTime = 0, IsOverlay = 0
    end,
    {DsgtId, TrialTime, IsOverlay}.

get_dsgt_permanent(GoodsId) ->
    case data_designation:get_designation_id(GoodsId) of
        [DsgtId|_] -> ok;
        _          -> DsgtId = 0
    end,
    {DsgtId, 0, 0}.

%% -----------------------------------------------
-spec get_dsgt(GoodsId) -> {DsgtId, TrialTime, OverLay} when
    GoodsId :: integer(),       %% 物品id
    DsgtId :: integer(),        %% 称号id
    TrialTime :: integer(),     %% 体验时间 0永久|非0限时
    OverLay :: integer().       %% 是否可叠加 0不可叠加|1可叠加
get_dsgt(GoodsId) ->
    case is_dsgt_trial(GoodsId) of
        true ->
            get_dsgt_trial(GoodsId);
        _ ->
            get_dsgt_permanent(GoodsId)
    end.

%%批量激活
batch_active_dsgt_common(_, [])->
    ignore;
batch_active_dsgt_common(RoleID, [H|T])->
    DesID = 
    case H of
        {?TYPE_DESIGN, D}    -> D;
        {?TYPE_DESIGN, D, _} -> D;
        _                         -> 0
    end,
    {DsgtId, LastTime, OverLay} = get_dsgt(DesID),
    active_dsgt_common(RoleID, DsgtId, DesID, LastTime, OverLay),
    batch_active_dsgt_common(RoleID, T).

%% -------------------------------------------------------
%% 其他进程调用发送称号接口
%% 一个称号可能对应体验或永久模式,因此改用物品id判断是哪种模式
%% -------------------------------------------------------
-spec active_dsgt_common(PlayerId, GoodsId) -> ReturnType when
    PlayerId :: integer(),      %% 玩家id
    GoodsId :: integer(),       %% 物品id
    ReturnType :: ok|skip|ignore.
active_dsgt_common(PlayerId, GoodsId) ->
    {DsgtId, TrialTime, OverLay} = get_dsgt(GoodsId),
    case data_designation:get_by_id(DsgtId) of
        #base_designation{is_global = Global} ->
            % EndTime = ?IF(TrialTime == 0, 0, utime:unixtime() + TrialTime),
            if Global > 0 ->
                    active_global_dsgt(DsgtId, [PlayerId], Global, {GoodsId, TrialTime, OverLay});
                true ->
                    active_dsgt_cast(PlayerId, #active_para{id=DsgtId, goods_id = GoodsId, expire_time = TrialTime, is_overlay = OverLay})
            end;
        _ ->
            skip
    end.

%%--------------------------------------------------
%% 其他进程调用发送称号接口
%%--------------------------------------------------
-spec active_dsgt_common(PlayerId, DsgtId, GoodsId, LastTime, OverLay) -> ReturnType when
    PlayerId :: integer(),
    DsgtId :: integer(),
    GoodsId :: integer(),
    LastTime :: integer(),
    OverLay :: integer(),
    ReturnType :: ok|skip|ignore.
active_dsgt_common(PlayerId, DsgtId, GoodsId, LastTime, OverLay) ->
    case data_designation:get_by_id(DsgtId) of
        #base_designation{is_global = Global}->
            if Global > 0 ->
                    active_global_dsgt(DsgtId, [PlayerId], Global, {GoodsId, LastTime, OverLay});
                true ->
                    active_dsgt_cast(PlayerId, #active_para{id=DsgtId, goods_id = GoodsId, expire_time = LastTime, is_overlay = OverLay})
            end;
        _ ->
            skip
    end.

%% 激活玩家全局称号
% -spec active_global_dsgt(Id, PlayerIdList) -> ReturnType when
%     Id :: integer(),            %% 称号对应物品id
%     PlayerIdList :: list(),     %% 玩家列表
%     ReturnType :: atom().
% active_global_dsgt(Id, PlayerIdList) ->
    % case data_designation:get_by_id(Id) of
    %     #base_designation{expire_time = ExpireTime, is_global = Global} ->
    %         EndTime = ?IF(ExpireTime == 0, 0, utime:unixtime() + ExpireTime),
    %         active_global_dsgt(Id, PlayerIdList, Global, EndTime);
    %     _ ->
    %         ok
    % end.

%% 激活全局称号
active_global_dsgt(DsgtId, PlayerIdList, Global, {GoodsId, ExpireTime, OverLay}) ->
    %% 删除称号的玩家
    OwnerList = lib_designation_util:get_dsgt_owner(DsgtId),
    NewOwnerList = lists:filter(fun([_, _, IsReplace]) -> IsReplace =:= 1 end, OwnerList),
    DeleteList = lib_designation_util:find_delete_list(NewOwnerList, PlayerIdList, Global),
    DelArgs = #active_para{id = DsgtId},
    [cancel_global_dsgt(DelId, DelArgs) || DelId <- DeleteList],
    %% 激活称号
    ActiveArgs = #active_para{id = DsgtId, goods_id = GoodsId, expire_time = ExpireTime, is_overlay = OverLay},
    [active_dsgt_cast(PlayerId, ActiveArgs) || PlayerId <- PlayerIdList].

%% 转发到玩家进程处理
active_dsgt_cast(PlayerId, ActivePara) ->
    case misc:get_player_process(PlayerId) of
        Pid when is_pid(Pid) ->
            case misc:is_process_alive(Pid) of
                true ->
                    gen_server:cast(Pid, {'apply_cast', ?APPLY_CAST_SAVE, lib_designation, active_dsgt, [ActivePara]});
                false ->
                    ?ERR("active_dsgt not found player process, RoleId:~p~n",[PlayerId])
            end;
        _ ->
            %% 离线激活
            lib_designation:active_dsgt_not_online(PlayerId, ActivePara)
    end.

%% 取消称号，到结束时效时被调用
cancel_dsgt(PlayerId, DsgtId) ->
    Pid = misc:get_player_process(PlayerId),
    case misc:is_process_alive(Pid) of
        true ->
            gen_server:cast(Pid, {'apply_cast', ?APPLY_CAST_SAVE, lib_designation, cancel_dsgt, [DsgtId]});
        _ -> %% 离线取消
            NowTime = utime:unixtime(),
            case lib_designation_util:select_dsgt_by_id(PlayerId, DsgtId) of
                [_Status, EndTime] ->
                    case EndTime < NowTime + 5 of
                        true ->
                            %% 社团竞榜特殊处理 - 可以强制删除数据库
                            case data_designation:get_by_id(DsgtId) of
                                #base_designation{force_cancel = CanCancel} when CanCancel == 1 ->
                                    Sql = io_lib:format(?SQL_DSGT_DELETE, [PlayerId, DsgtId]),
                                    db:execute(Sql);
                                    % lib_designation:delete_designation(PlayerId,DsgtId);
                                _ ->
                                    skip
                            end,
                            lib_designation:log_active_dsgt(?OP_REMOVE, PlayerId, DsgtId, NowTime, 0, 0);
                        false ->
                            skip
                    end;
                _ ->
                    skip
            end
    end.

%% 在线取消称号 只有玩家在线的时候才操作
cancel_dsgt_online(PlayerId, DsgtId) ->
    Pid = misc:get_player_process(PlayerId),
    case misc:is_process_alive(Pid) of
        true ->
            gen_server:cast(Pid, {'apply_cast', ?APPLY_CAST_SAVE, lib_designation, cancel_dsgt, [DsgtId]});
        _ ->
            skip
    end.

%% 取消称号，全局称号被其他人替换的时候调用
cancel_global_dsgt(PlayerId, #active_para{id=Id}=ActivePara) ->
    case misc:get_player_process(PlayerId) of
        Pid when is_pid(Pid) ->
            case misc:is_process_alive(Pid) of
                true ->
                    gen_server:cast(Pid, {'apply_cast', ?APPLY_CAST_SAVE, lib_designation, cancel_dsgt_by_id, [ActivePara]});
                false ->
                    ?ERR("cancel_dsgt not found player process, RoleId:~p~n",[PlayerId])
            end;
        _ ->
            lib_designation_util:update_dsgt_state(PlayerId,Id, ?STATUS_UNUSED),
            Now = utime:unixtime(),
            lib_designation:log_active_dsgt(?OP_REPLACE, PlayerId, Id, Now, 0, 0),
            false
    end.

get_dsgt_name(DsgtId) ->
    case data_designation:get_by_id(DsgtId) of
        #base_designation{name = Name} ->
            util:make_sure_binary(Name);
        _ -> <<>>
    end.
