%% ---------------------------------------------------------------------------
%% @doc mod_dungeon_agenet.erl

%% @author  hjh
%% @email  hejiahua@163.com
%% @since  2017-02-14
%% @deprecated 副本管理进程:处理玩家上下线回去副本
%% ---------------------------------------------------------------------------
-module(mod_dungeon_agent).
-export([
        get_dungeon_record/1
        , reconnect/4
        , remove_dungeon_record/1
        , remove_dungeon_record/2
        , set_dungeon_record/1
    ]).

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

-include("common.hrl").
-include("dungeon.hrl").
-include("dun_guard.hrl").

%% 获取副本记录.
get_dungeon_record(RoleId)->
    gen_server:call(?MODULE, {'get_dungeon_record', RoleId}).

%% 断线重连(跨服)
reconnect(Node, RoleId, Sid, Xy) ->
    gen_server:cast(?MODULE, {'reconnect', Node, RoleId, Sid, Xy}).

%% 设置副本记录.
set_dungeon_record(DungeonRecord)->
    gen_server:cast(?MODULE, {'set_dungeon_record', DungeonRecord}).

%% 移除副本记录
remove_dungeon_record(RoleId) ->
    gen_server:cast(?MODULE, {'remove_dungeon_record', RoleId}).

%% 根据副本Pid,移除副本记录
remove_dungeon_record(RoleId, DunPid) ->
    gen_server:cast(?MODULE, {'remove_dungeon_record', RoleId, DunPid}).

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

init([]) ->
    process_flag(trap_exit, true),
    erlang:send_after(30 * 1000, self(), 'check_dungeon_alive'),
    {ok, ?MODULE}.

%% 获取副本记录.
handle_call({'get_dungeon_record', RoleId}, _From, State) ->
    case get(RoleId) of
        undefined ->
            {reply, [], State};
        DungeonRecord ->
            {reply, [DungeonRecord], State}
    end;

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

%% 设置副本记录.
handle_cast({'set_dungeon_record', DungeonRecord}, State) ->
    put(DungeonRecord#dungeon_record.role_id, DungeonRecord),
    {noreply, State};

%% 移除副本记录
handle_cast({'remove_dungeon_record', RoleId}, State) ->
    erase(RoleId),
    {noreply, State};

%% 移除副本记录
handle_cast({'remove_dungeon_record', RoleId, DunPid}, State) ->
    case get(RoleId) of
        undefined ->
            {noreply, State};
        #dungeon_record{dun_pid = DunPid} ->
            erase(RoleId),
            {noreply, State};
        _ ->
            {noreply, State}
    end;

%% 断线重连
handle_cast({'reconnect', Node, RoleId, Sid, {X, Y}}, State) ->
    case get(RoleId) of
        undefined ->
            clusters_center:apply_cast(Node, lib_scene, player_change_default_scene, [RoleId, [{change_scene_hp_lim, 0}]]),
            {noreply, State};
        DungeonRecord ->
            #dungeon_record{dun_pid = DunPid} = DungeonRecord,
            case misc:is_process_alive(DunPid) of
                true ->
                    mod_dungeon:reconnect(DunPid, RoleId, [{node, Node}, {sid, Sid}], {X, Y});
                false ->
                    clusters_center:apply_cast(Node, lib_scene, player_change_default_scene, [RoleId, [{change_scene_hp_lim, 0}]])
            end,
            {noreply, State}
    end;

handle_cast(Msg, State) ->
    catch ?ERR("mod_dungeon_agent:handle_cast not match: ~p", [Msg]),
    {noreply, State}.

%% 检测副本是否活着.
handle_info('check_dungeon_alive', State) ->
    %1.5分钟检测一次.
    erlang:send_after(5 * 60 * 1000, self(), 'check_dungeon_alive'),
    Time = utime:unixtime(),
    %2.定义检测副本存活函数.
    F = fun(DungeonRecord) ->
        DunPid = DungeonRecord#dungeon_record.dun_pid,
        RoleId = DungeonRecord#dungeon_record.role_id,
        case is_pid(DunPid) andalso misc:is_process_alive(DunPid) of
            true ->
                case Time - DungeonRecord#dungeon_record.end_time >= 300 of
                    true ->
                        mod_dungeon:close_dungeon(DunPid),
                        erase(RoleId);
                    false ->
                        skip
                end;
            false ->
                erase(RoleId)
        end
    end,
    %3.检测所有副本.
    AllRecord = get(),
    [F(DunRecord) || {Key, DunRecord} <- AllRecord, is_integer(Key)],
    {noreply, State};

handle_info(Info, State) ->
    catch ?ERR("mod_dungeon_agent:handle_info not match: ~p", [Info]),
    {noreply, State}.

terminate(_Reason, _State) ->
    ok.

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