%% ---------------------------------------------------------------------------
%% @doc mod_dungeon.erl

%% @author  hjh
%% @email  hejiahua@163.com
%% @since  2017-02-14
%% @deprecated 副本进程
%% ---------------------------------------------------------------------------
-module(mod_dungeon).
-export([]).

-compile(export_all).

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

-include("dungeon.hrl").
-include("common.hrl").
-include("predefine.hrl").
-include("errcode.hrl").
-include("chat.hrl").
-include("def_goods.hrl").
%% ====================
%% 副本普通流程接口
%% ====================

%% 开启副本
start(TeamId, From, DunId, RoleList, Args) ->
    {ok, Pid} = gen_server:start(?MODULE, [DunId, TeamId, RoleList, Args], []),
    [unode:apply(Role#dungeon_role.node, lib_player, update_player_info, [Role#dungeon_role.id, [{copy_id, Pid}]]) || Role <- RoleList, Role#dungeon_role.pid =/= From],
    Pid.


%% 重连
reconnect(DunPid, RoleId, Args, Xy) ->
    gen_server:cast(DunPid, {'reconnect', RoleId, Args, Xy}).

%% 延迟登出
delay_logout(DunPid, RoleId, Hp, HpLim) ->
    gen_server:cast(DunPid, {'delay_logout', RoleId, Hp, HpLim}).

%% 副本内登出
logout(DunPid, RoleId, Hp, HpLim) ->
    gen_server:cast(DunPid, {'logout', RoleId, Hp, HpLim}).

%% 主动退出副本
active_quit(DunPid, RoleId) ->
    gen_server:cast(DunPid, {'active_quit', RoleId}).

%% 关闭副本
close_dungeon(DunPid) ->
    gen_server:cast(DunPid, {'close_dungeon'}).

handle_enter_fail(DunPid, RoleId, Why) ->
    gen_server:cast(DunPid, {handle_enter_fail, RoleId, Why}).

enter_next_dun(DunPid, List) ->
    gen_server:cast(DunPid, {enter_next_dun, List}).

alloc_drop(DunPid, MonArgs, Alloc, AtterId, Klist) ->
    gen_server:cast(DunPid, {alloc_drop, MonArgs, Alloc, AtterId, Klist}).

get_dummy_id(DunPid, Id, OldDummyId) ->
    gen_server:cast(DunPid, {get_dummy_id, Id, OldDummyId}).

%% ====================
%% 玩家请求数据
%% ====================

%% 副本信息
send_dungeon_info(DunPid, Roleid, Node) ->
    gen_server:cast(DunPid, {'send_dungeon_info', Roleid, Node}).

%% 获取副本评分信息
get_dun_score_info(DunPid, RoleId, Node) ->
    gen_server:cast(DunPid, {'get_dun_score_info', RoleId, Node}).


%% 推送结算
push_settlement(DunPid, RoleId) ->
    gen_server:cast(DunPid, {'push_settlement', RoleId}).

%% 退出副本时间
send_flow_quit_time(DunPid, RoleId, Node) ->
    gen_server:cast(DunPid, {'send_flow_quit_time', RoleId, Node}).

%% 鼓舞
encourage(DunPid, RoleId, CostType, Num) ->
    gen_server:cast(DunPid, {'encourage', RoleId, CostType, Num}).

%% 设置鼓舞次数
setup_encourage_count(DunPid, RoleId, CostType, Count) ->
    gen_server:cast(DunPid, {'setup_encourage_count', RoleId, CostType, Count}).

get_mon_kill_info(DunPid, {RoleId, Node}) ->
    gen_server:cast(DunPid, {'get_mon_kill_info', RoleId, Node}).


get_mon_hurt_info(DunPid, Sid, Node) ->
    gen_server:cast(DunPid, {'get_mon_hurt_info', Sid, Node}).

get_dun_rating_info(DunPid, {RoleId, Node}) ->
    gen_server:cast(DunPid, {'get_dun_rating_info', RoleId, Node}).

%% 前端完成场景加载
fin_change_scene(DunPid, RoleId) ->
    gen_server:cast(DunPid, {fin_change_scene, RoleId}).

%% 击杀怪物
kill_mon(DunPid, Args) ->
    gen_server:cast(DunPid, {'kill_mon', Args}).

%% 停止怪物
stop_mon(DunPid, AutoId, Mid, DieSign, CreateKey, OwnId, Hp, HpLim) ->
    gen_server:cast(DunPid, {'stop_mon', AutoId, Mid, DieSign, CreateKey, OwnId, Hp, HpLim}).

%% 对象死亡
object_die(DunPid, AutoId, OwnId, ObjId) ->
    gen_server:cast(DunPid, {'object_die', AutoId, OwnId, ObjId}).

%% 对象停止
object_stop(DunPid, AutoId, OwnId, Hp, HpLim) ->
    gen_server:cast(DunPid, {'object_stop', AutoId, OwnId, Hp, HpLim}).

%% 玩家死亡
player_die(DunPid, RoleId, HpLim, DeadCount, AttrList) ->
    gen_server:cast(DunPid, {'player_die', RoleId, HpLim, DeadCount, AttrList}).

%% 玩家复活
player_revive(DunPid, RoleId, ReviveType, Args) ->
    gen_server:cast(DunPid, {'player_revive', RoleId, ReviveType, Args}).

%% 更新玩家数据
update_dungeon_role(DunPid, RoleId, AttrList) ->
    gen_server:cast(DunPid, {'update_dungeon_role', RoleId, AttrList}).


%% 更新怪物信息
update_mon_info(DunPid, Id, Mid, Aid, Hp, HpLim) ->
    gen_server:cast(DunPid, {update_mon_info, Id, Mid, Aid, Hp, HpLim}).

update_role_lv(DunPid, RoleId, Lv) ->
    gen_server:cast(DunPid, {update_role_lv, RoleId, Lv}).

%% 新增掉落
goods_drop(CopyId, RoleId, NewGoodsDrop) ->
    gen_server:cast(CopyId, {'goods_drop', RoleId, NewGoodsDrop}).

%% 拾取掉落
drop_choose(CopyId, RoleId, Data) ->
    gen_server:cast(CopyId, {'drop_choose', RoleId, Data}).

collect_mon_goods(CopyId, RoleId, GoodsList) ->
    gen_server:cast(CopyId, {'collect_mon_goods', RoleId, GoodsList}).

handle_special(DunPid, RoleId, Node, Cmd, Args) ->
    gen_server:cast(DunPid, {handle_special, RoleId, Node, Cmd, Args}).

apply(DunPid, Mod, Fun, Args) ->
    gen_server:cast(DunPid, {apply, Mod, Fun, Args}).

dispatch_dun_event(DunPid, Msg) ->
    gen_server:cast(DunPid, {dispatch_dun_event, Msg}).

%% 人物被攻击
role_be_hurted(DunPid, RoleId, Hp, HpLim, Type) ->
    gen_server:cast(DunPid, {'role_be_hurted', RoleId, Hp, HpLim, Type}).

%% 怪物被攻击
mon_be_hurt(DunPid, AtterId, AttSign, AtterName, Hurt) ->
    gen_server:cast(DunPid, {'mon_be_hurt', AtterId, AttSign, AtterName, Hurt}).

%% 秘籍结束副本
gm_close_dungeon(DunPid, RoleId, ResultType) ->
    gen_server:cast(DunPid, {'gm_close_dungeon', RoleId, ResultType}).

%% 特效结束通知
animation_notice(DunPid, Sid) ->
    gen_server:cast(DunPid, {animation_notice, Sid}).

%% 数据初始化
init([DunId, TeamId, RoleList, Args]) ->
    {ok, NewState} = dungeon_logic:init_dun(DunId, TeamId, RoleList, Args),
    {ok, NewState}.

handle_call(Request, From, State) ->
    mod_dungeon_call:handle_call(Request, From, State).


handle_cast({'test', A}, State) ->
    timer:sleep(2000),
    case A == 2 of
        true -> ?PRINT("tests :~p ~n", [A]), {stop, normal, State};
        false -> ?PRINT("tests :~p ~n", [A]), {noreply, State}
    end;
handle_cast({'get_state'}, State) ->
    ?INFO("State:~w", [State]),
    {noreply, State};
handle_cast(Msg, State) ->
    mod_dungeon_cast:handle_cast(Msg, State).

handle_info(Info, State) ->
    mod_dungeon_info:handle_info(Info, State).

terminate(Reason, State) ->
    ?PRINT("_Reason :~p ~n", [Reason]),
    #dungeon_state{team_id = TeamId, role_list = RoleList,
        dun_type = _DunType, dun_id = DunId, scene_id = SceneId,
        scene_pool_id = ScenePoolId, force_quit_ref = ForceQuitRef, 
        create_gap_ref = GapRefL, wave_ref = WaveRefs
        } = State,
    case Reason of
        normal -> skip;
        _      ->
            F = fun(#dungeon_role{id = RoleId, is_end_out = IsEndOut, node = Node}) ->
                case IsEndOut == ?DUN_IS_END_OUT_NO of
                    true ->
                        {ErrorCodeInt, ErrorCodeArgs} = util:parse_error_code(?ERRCODE(err610_dungeon_error)),
                        {ok, BinData} = pt_110:write(11017, [?FLOAT_TEXT_ONLY, ErrorCodeInt, ErrorCodeArgs]),
                        lib_server_send:send_to_uid(RoleId, BinData),
                        lib_player:apply_cast(Node, RoleId, ?APPLY_CAST_SAVE, ?NOT_HAND_OFFLINE, lib_dungeon, close_dungeon, [[SceneId], self()]);
                    false ->
                        skip
                end
            end,
            lists:foreach(F, RoleList)
    end,
    %%通知组队大厅退出副本
    if
        TeamId > 0 -> %% 跨服队伍
            lib_dun_multi_cluster:cast_dun_multi_hall_cluster(DunId, {change_team_state, TeamId, DunId, _Type = 0});
        true ->
            ok
    end,

    % 清理定时器
    F2 = fun(#dungeon_role{revive_ref = ReviveRef}) ->
        util:cancel_timer(ReviveRef)
    end,
    lists:foreach(F2, RoleList),
    util:cancel_timer(ForceQuitRef),
    lists:map(fun(TGapRef) -> util:cancel_timer(TGapRef) end, GapRefL),
    lists:map(fun(WaveRef) -> util:cancel_timer(WaveRef) end, WaveRefs),

    % 清理副本记录
    [mod_dungeon_agent:remove_dungeon_record(Role#dungeon_role.id, self())||Role<-RoleList],
    
    % 清理场景数据(延迟3秒清理场景数据,防止怪物还在异步生成,导致没有清理)
    Pid = self(),
    spawn(fun() ->
        timer:sleep(3*1000),
        [lib_scene:clear_scene_room(SceneIdX, ScenePoolId, Pid)||SceneIdX<-[SceneId]]
    end),
    
    ok.

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