%%%------------------------------------
%%% module  : mod_scene_agent_info
%%% @author  : xyao
%%% email   : jiexiaowen@gmail.com
%%% Created : 2012.05.18
%%% description: 场景管理info处理
%%%------------------------------------
-module(mod_scene_agent_info).
-include("scene.hrl").
-include("battle.hrl").
-include("common.hrl").
-include("attr.hrl").
-include("team.hrl").
-include("predefine.hrl").
-include("figure.hrl").

-export([handle_info/2]).

%% 定时器返回
handle_info({timeout, TimeRef, {'timer_call_back', TimeoutEvl}}, State = #scene_state{scene = EtsScene}) ->
    case catch lib_scene_agent:timer_call_back(TimeRef, TimeoutEvl, EtsScene) of
        {'EXIT', Reason} ->
            ?ERR("scene_timer_call_back event:~p~n reason:~p~n", [TimeoutEvl, Reason]);
        _ -> skip
    end,
    {noreply, State};
handle_info({timeout, TimeRef, {ai_buff_timer, TimeoutArgs}}, State = #scene_state{scene = EtsScene}) ->
    lib_scene_agent:ai_buff_timer(TimeRef, TimeoutArgs, EtsScene),
    {noreply, State};

%% 特殊关闭场景进程
handle_info({'init_close_scene'}, State) ->
    %% []代表清理所有房间怪物
    lib_scene_object_agent:clear_scene_object(?BATTLE_SIGN_MON, [], 1),
    {stop, normal, State};

%% 定期监控玩家进程已失效的玩家数据
handle_info('clear_dirty', State) ->
    %% 顺便校正一遍场景人数
    AllUsers    = lib_scene_agent:get_scene_user(),
    ScenePid    = self(),
    %% 因为misc:is_process_alive/1可能检查其他节点进程，
    %% 所以另起新进程检查，检查结果通过消息发送回场景进程处理，避免单次占用场景进程太多执行时间
    spawn(fun() ->
                [
                    ScenePid ! {'clear_dirty', UserId, UserPid}
                    || #ets_scene_user{id = UserId, pid = UserPid} <- AllUsers,
                    not misc:is_process_alive(UserPid)
                ]
        end),
    {noreply, State};

%% 此接口不再检测UserPid是否存活，需要由发送消息方先确认UserPid已经失效
handle_info({'clear_dirty', UserId, UserPid}, State) ->
    case lib_scene_agent:get_user(UserId) of
        #ets_scene_user{pid = UserPid} ->
            %% UserPid数据符合的才处理
            lib_scene_agent:del_user(UserId);
        _ -> ignore
    end,
    {noreply, State};

%% 场景gc接口（由管理器定期调用进行）
handle_info({timeout, _Timer, gc}, State = #scene_state{mon_mgr_pid = MonMgrPid}) ->
    ScenePid = self(),
    spawn(fun() ->
                %% 延迟，使场景进程本身执行完此{timeout, _Timer, gc}请求，再检查进程status
                timer:sleep(100),
                %% 场景进程如果是waiting状态，才执行内存GC
                {status, ProcStatus} = erlang:process_info(ScenePid, status),
                ProcStatus =:= waiting andalso erlang:garbage_collect(ScenePid),
                %% 怪物管理进程如果消息队列少于10个，则执行内存GC
                {message_queue_len, MessageLenM} = erlang:process_info(MonMgrPid, message_queue_len),
                MessageLenM < 10 andalso erlang:garbage_collect(MonMgrPid),
                ok
        end),
    {noreply, State};

%% 离线托管
handle_info({'battle', PlayerId, FindType}, State = #scene_state{scene = EtsScene}) ->
    case lib_scene_agent:get_user(PlayerId) of
        #ets_scene_user{online=?ONLINE_OFF_HOSTING}=User ->
            Ref = offline_hosting_battle:start_battle(User, FindType, EtsScene),
            put({onhook_ref, PlayerId}, Ref);
        _ -> skip
    end,
    {noreply, State};

%% 离线托管
handle_info({'combo', PlayerId, Args}, State = #scene_state{scene = EtsScene}) ->
    case lib_scene_agent:get_user(PlayerId) of
        #ets_scene_user{online=?ONLINE_OFF_HOSTING}=User ->
            offline_hosting_battle:combo(Args, User, EtsScene);
        _ -> skip
    end,
    {noreply, State};

%% 离线托管
handle_info({'host_battle_info', Return, PlayerId, FindType}, State = #scene_state{scene = EtsScene}) ->
    case lib_scene_agent:get_user(PlayerId) of
        #ets_scene_user{online = ?ONLINE_OFF_HOSTING}=User ->
            OnhookRef = offline_hosting_battle:host_battle_info(User, EtsScene, Return, FindType),
            put({onhook_ref, PlayerId}, OnhookRef);
        _Other ->
            erase({onhook_ref, PlayerId})
    end,
    {noreply, State};

%% 离线托管-丢失攻击目标
handle_info({hosting_lost_target, RoleId}, State = #scene_state{scene = _EtsScene}) ->
    case lib_scene_agent:get_user(RoleId) of
        #ets_scene_user{online = ?ONLINE_OFF_HOSTING}=_User ->
            ok;
        %offline_hosting_madness_land:when_lost_target(EtsScene, User);
        _ ->
            ok
    end,
    {noreply, State};

%% 默认匹配
handle_info(Info, State) ->
    catch ?ERR("mod_scene_agent_info not match: ~p", [Info]),
    {noreply, State}.
