%%%-------------------------------------------------------------------
%%% @author liushl
%%% @doc
%%%     离线托管，以假人形式创建，玩家并不上线
%%%     假人创建的时候并不扣除托管值，由调用方决定是否扣除托管值
%%% @end
%%%-------------------------------------------------------------------
-module(offline_hosting_dummy).
-author("liushl").

-include("role.hrl").
-include("mon.hrl").
-include("offline_hosting.hrl").
-include("common.hrl").
-include("figure.hrl").
-include("attr.hrl").
%% API
-export([]).
-compile(export_all).

%% @doc 创建假人参与玩法
%% mon_args
%%      delay_cost_value    延迟扣除托管值时间
take_part_in(Handler, Mod, SubMod, RoleId, Args) ->
    %% 如果有正在托管的需要先结束旧的托管
    #{
        scene_id := SceneId,
        scene_pool := ScenePoolId,
        copy_id := CopyId,
        x := X,
        y := Y
    } = Args,
    InitArgs  = maps:get(init_args, Args, []),
    OtherArgs = maps:get(mon_args, Args, []),
    MonArg =
        [
            {born_handler, {?MODULE, when_dummy_born, [Handler, Mod, SubMod, InitArgs]}},
            {change_scene_handler, {?MODULE, when_change_scene, []}},
            {die_handler, {?MODULE, when_dummy_die, []}},
            {stay_dead, 1}
        ] ++ OtherArgs,
    lib_dummy_api:create_role_dummy(RoleId, SceneId, ScenePoolId, CopyId, X, Y, MonArg).

%% @doc 通知假人结束托管状态-销毁
notice_logout(RoleId, MonPid, MonId) ->
    Figure = lib_role:get_role_figure(RoleId),
    case offline_hosting_data:hosting_log_save_db(Figure) of
        [Log] ->
            %% 如果玩家在线，通知玩家托管结束
            offline_hosting_api:notice_mon_hosting_end(RoleId, Log);
        _ ->
            ok
    end,
    %% 删除正在托管的数据信息
    offline_hosting_data:hosting_role_delete(RoleId),
    %% 清理假人
    mon_mgr:send(MonPid, MonId, {'stop', 1}).

%% @doc 扣除假人托管值
deduct_hosting_value(RoleId, Mod) ->
    case offline_hosting_data:hosting_role_lookup(RoleId) of
        [#ets_hosting_role{mod = Mod, sub_id = SubMod, cost_value = undefined} = RoleInfo] ->
            %% 扣除托管值
            Cost = offline_hosting_data:host_value_cost(RoleId, Mod, SubMod),
            %% 记录当前状态
            offline_hosting_data:hosting_role_save(
                RoleInfo#ets_hosting_role{
                    time = utime:unixtime(),
                    cost_value = Cost
                }
            );
        _ ->
            not_in_hosting
    end.

%% @doc 假人切换场景
host_behavior_change_scene(RoleId, SceneId, PoolId, CopyId, X, Y, Arg) ->
    case offline_hosting_data:hosting_role_lookup(RoleId) of
        [#ets_hosting_role{
            pid = MonPid,
            mon_id = MonId
        }] when MonId > 0 ->
            host_behavior_change_scene(MonPid, MonId, SceneId, PoolId, CopyId, X, Y, Arg);
        _ ->
            not_in_hosting
    end.
host_behavior_change_scene(MonPid, MonId, SceneId, PoolId, CopyId, X, Y, Arg) ->
    case lib_scene:is_clusters_scene(SceneId) of
        true -> clusters_node:apply_cast(mon_mgr, send, [MonPid, MonId, {change_scene, SceneId, PoolId, CopyId, X, Y, Arg}]);
        _ -> mon_mgr:send(MonPid, MonId, {change_scene, SceneId, PoolId, CopyId, X, Y, Arg})
    end.

%% @doc 战斗
host_behavior_battle(RoleId, SceneId) ->
    case offline_hosting_data:hosting_role_lookup(RoleId) of
        [#ets_hosting_role{
            pid = MonPid,
            mon_id = MonId
        }] when MonId > 0 ->
            host_behavior_battle(MonPid, MonId, SceneId);
        _ ->
            not_in_hosting
    end.
host_behavior_battle(MonPid, MonId, SceneId) ->
    case lib_scene:is_clusters_scene(SceneId) of
        true -> clusters_node:apply_cast(mon_mgr, send, [MonPid, MonId, {offline_hosting_behavior, 'ATTACK', []}]);
        _ ->  mon_mgr:send(MonPid, MonId, {offline_hosting_behavior, 'ATTACK', []})
    end.

%%%-------------------------------------------------------------------
%% 假人进程处理
%%%-------------------------------------------------------------------
%% 假人出生监听
when_dummy_born(init, State, [Handler, Mod, SubMod, Arg]) ->
    {ok, State1} = host_behavior('LOGIN', State, [Handler, Mod, SubMod, Arg]),
    State1;

%% 复活监听
when_dummy_born(revive, State, _) ->
    {ok, State1} = host_behavior('REVIVE', State, []),
    State1.

%% 假人死亡监听
when_dummy_die(State, KList, Atter, AtterSign, Args) ->
    {ok, State1} = host_behavior('DIE', State, [KList, Atter, AtterSign, Args]),
    State1.

%% 切换场景
when_change_scene(State, _) ->
    {ok, State1} = host_behavior('CHANGE_SCENE', State, []),
    State1.

%% 延迟扣除托管值
delay_cost_value(State, Time) ->
    NewState = mon_state_util:update_general_driven(State, [{Time, {offline_hosting_behavior, 'DEDUCT', []}}]),
    NewState.

%% 取消旧行为定时器
cancel_behavior_timer(State) ->
    #ob_act{
        general_driven = OldGeneralDriven
    } = State,
    GeneralDriven = mon_state_util:remove_driven_info(hosting_behavior, OldGeneralDriven),
    {ok, State#ob_act{general_driven = GeneralDriven}}.

%% 延迟执行某一行为
%% NextBehavior
%% BehaviorArg [term()]
%% DelayTime ms
host_behavior_delay(State, NextBehavior, BehaviorArg, 0) ->
    NewState = mon_state_util:update_general_driven(State, [{0, {offline_hosting_behavior, NextBehavior, BehaviorArg}, update}]),
    {ok, NewState};
host_behavior_delay(State, NextBehavior, BehaviorArg, DelayTime) ->
    NewState = mon_state_util:update_general_driven(State, [{DelayTime, {offline_hosting_behavior, NextBehavior, BehaviorArg}, update}]),
    {ok, NewState}.

%% 获取托管代理模块
get_handler(State) -> State#ob_act.offline_hosting#offline_hosting_dummy.handler.
%%%-------------------------------------------------------------------
%%% @doc
%%%     行为执行并切换处理
%%% @end
%%%-------------------------------------------------------------------
%% 这些行为全部只在托管状态才生效
host_behavior(_Any, #ob_act{offline_hosting = Hosting} = State, _Arg)
    when not is_record(Hosting, offline_hosting_dummy) ->
    {ok, State};

%% 怪物创建-登陆
host_behavior('LOGIN', State, [Handler, Mod, SubMod, Arg]) ->
    #ob_act{
        object = #scene_object{
            figure = #figure{id = RoleId},
            id = MonId,
            aid = Aid,
            dummy = #scene_dummy{node = Node}
        }
    } = State,
    case clusters_api:is_center() of
        true  ->
            clusters_center:apply_cast(Node, ?MODULE, host_dummy_create, [RoleId, Mod, SubMod, Aid, MonId]);
        false ->
            host_dummy_create(RoleId, Mod, SubMod, Aid, MonId)
    end,
    OfflineHosting =
        #offline_hosting_dummy{
            handler = Handler           %% 玩法代理
            , module_id = Mod           %% 功能id
        },
    State1 = State#ob_act{offline_hosting = OfflineHosting},
    {ok, State2} = host_behavior(login, State1, Arg),
    {ok, State2};

%% 这些行为全部只在托管状态才生效
host_behavior(_Any, #ob_act{offline_hosting = Hosting} = State, _Arg)
    when not is_record(Hosting, offline_hosting_dummy) ->
    {ok, State};

host_behavior(Any, #ob_act{offline_hosting = #offline_hosting_dummy{handler = undefined}} = State, Arg) ->
    ?ERR("missing handler![~p, ~p]", [Any, Arg]),
    {ok, State};

%% 扣除托管值-由假人进程触发
host_behavior('DEDUCT', State, _) ->
    #ob_act{
        object = #scene_object{
            figure = #figure{id = RoleId},
            dummy = #scene_dummy{node = Node}
        },
        offline_hosting = #offline_hosting_dummy{module_id = Mod}
    } = State,
    case clusters_api:is_center() of
        true  ->
            clusters_center:apply_cast(Node, ?MODULE, deduct_hosting_value, [RoleId, Mod]);
        false ->
            deduct_hosting_value(RoleId, Mod)
    end,
    {ok, State};

%% 切换场景
host_behavior('CHANGE_SCENE', State, _) ->
    #ob_act{
        object = #scene_object{
            figure = #figure{id = RoleId},
            id = MonId,
            aid = Aid,
            dummy = #scene_dummy{node = Node}
        }
    } = State,
    case clusters_api:is_center() of
        true  ->
            clusters_center:apply_cast(Node, ?MODULE, host_dummy_change_scene, [RoleId, Aid, MonId]);
        false ->
            host_dummy_change_scene(RoleId, Aid, MonId)
    end,
    {ok, State1} = host_behavior(change_scene, State, []),
    {ok, State1};

%% 攻击
host_behavior('ATTACK', State, _) ->
    NewState = mon_state_util:update_state_driven(State, {0, 'find_target'}),
    {ok, NewState};

%% 死亡-如果想自定义复活时间可修改 #ob_act.revive_time
%% 怪物内部驱动会自动进行到 'REVIVE'
host_behavior('DIE', State, [KList, Atter, _AtterSign, _Args]) ->
    {ok, State1} = host_behavior(die, State, [KList, Atter]),
    {ok, State1};

%% 复活-默认是原地复活/如果是安全区复活，需要自定义坐标通知前端假人消失
%% 复活后会默认攻击
host_behavior('REVIVE', State, _) ->
    {ok, State1} = host_behavior(revive, State, []),
    {ok, State1};

%% 怪物执行某行为
%% Arg [term()]
host_behavior(Behavior, State, Arg) ->
    Handler = get_handler(State),
    apply(Handler, host_behavior, [Behavior, State, Arg]).

%%%-------------------------------------------------------------------
%%% @doc
%%%     假人触发修改托管数据
%%% @end
%%%-------------------------------------------------------------------
%% 假人创建
host_dummy_create(RoleId, Mod, SubMod, Aid, MonId) ->
    %% 扣除托管值
    %Cost = offline_hosting_data:host_value_cost(RoleId, Mod, SubMod),
    %% 记录当前状态
    offline_hosting_data:hosting_role_save(
        #ets_hosting_role{
            role_id = RoleId,
            mod = Mod,
            sub_id = SubMod,
            mon_id = MonId,
            pid = Aid,
            time = utime:unixtime()
        }
    ).

%% 假人切换场景
host_dummy_change_scene(RoleId, Aid, MonId) ->
    case offline_hosting_data:hosting_role_lookup(RoleId) of
        [RoleInfo] ->
            offline_hosting_data:hosting_role_save(
                RoleInfo#ets_hosting_role{
                    mon_id = MonId,
                    pid = Aid
                }
            );
        _ ->
            ok
    end.