%% ---------------------------------------------------------------------------
%% @doc lib_dungeon_api.erl

%% @author  hjh
%% @email  hejiahua@163.com
%% @since  2017-02-23
%% @deprecated 副本接口
%% ---------------------------------------------------------------------------
-module(lib_dungeon_api).
-export([
        kill_mon/7
        , stop_mon/8
        ,collect_mon_goods/3
        , handle_event/2
        , get_dungeon_type_by_scene/1 %%通过场景id获取副本类型
    ]).

-compile(export_all).

-include("server.hrl").
-include("dungeon.hrl").
-include("scene.hrl").
-include("attr.hrl").
-include("battle.hrl").
-include("rec_event.hrl").
-include("def_event.hrl").
-include("common.hrl").
-include("def_module.hrl").
-include("team.hrl").
-include("figure.hrl").
-include("predefine.hrl").
-include("custom_act.hrl").
-include("def_fun.hrl").
-include("dungeon_multi.hrl").

%% 受攻击
player_be_hurted(PS) ->
    #player_status{id=RoleId, dungeon=StatusDun, copy_id=CopyId, battle_attr = BA} = PS,
    #status_dungeon{dun_id = DunId} = StatusDun,
    IsAvlive = misc:is_process_alive(CopyId),
    IsOnDun = lib_dungeon:is_on_dungeon(PS),
    case data_dungeon:get_dun(DunId) of
        #dun_cfg{type = DunType} when IsAvlive == true andalso IsOnDun == true ->
            case lib_dungeon_distribute:get_special_api_mod(DunType, role_be_hurted, 4) of
                undefined ->
                    case check_dun_hp_event(DunId, PS#player_status.figure#figure.lv) of
                        false -> ok;
                        _     -> mod_dungeon:role_be_hurted(CopyId, RoleId, BA#battle_attr.hp, BA#battle_attr.hp_lim, DunType)
                    end;
                _Mod -> mod_dungeon:role_be_hurted(CopyId, RoleId, BA#battle_attr.hp, BA#battle_attr.hp_lim, DunType)
            end;
        _ -> ok
    end.

%% 攻击怪物(计算伤害)
%  怪物mod_args参数配置9999则为统计伤害列表
mon_be_hurt(SceneId, CopyId, AtterId, AttSign, AtterName, Hurt, _) ->
    case data_scene:get(SceneId) of
        #ets_scene{type = ?SCENE_TYPE_DUNGEON} ->
            case misc:is_process_alive(CopyId) of
                true -> mod_dungeon:mon_be_hurt(CopyId, AtterId, AttSign, AtterName, Hurt);
                false -> skip
            end;
        _ ->
            skip
    end.

%% 击杀怪物
kill_mon(SceneId, CopyId, AutoId, DieSign, Mon, SkillOwner, KillArgs) ->
    #scene_mon{mid = Mid, create_key = CreateKey} = Mon,
    case is_record(SkillOwner, skill_owner) of
        true -> OwnId = SkillOwner#skill_owner.id;
        false -> OwnId = 0
    end,
    case data_scene:get(SceneId) of
        #ets_scene{type = ?SCENE_TYPE_DUNGEON} ->
            case misc:is_process_alive(CopyId) of
                true ->
                    Args = [AutoId, Mid, DieSign, CreateKey, OwnId, KillArgs],
                    mod_dungeon:kill_mon(CopyId, Args);
                false -> skip
            end;
        _ ->
            skip
    end.

%% 怪物被停止
stop_mon(SceneId, CopyId, AutoId, Sign, Mon, SkillOwner, Hp, HpLim) ->
    #scene_mon{mid = Mid, create_key = CreateKey} = Mon,
    case is_record(SkillOwner, skill_owner) of
        true -> OwnId = SkillOwner#skill_owner.id;
        false -> OwnId = 0
    end,
    case data_scene:get(SceneId) of
        #ets_scene{type = ?SCENE_TYPE_DUNGEON} ->
            case misc:is_process_alive(CopyId) of
                true -> mod_dungeon:stop_mon(CopyId, AutoId, Mid, Sign, CreateKey, OwnId, Hp, HpLim);
                false -> skip
            end;
        _ ->
            skip
    end.

%% 采集怪
collect_mon_goods(CopyId, RoleId, GoodsList) ->
    case misc:is_process_alive(CopyId) of
        true ->
            mod_dungeon:collect_mon_goods(CopyId, RoleId, GoodsList);
        _ ->
            skip
    end.

%% 对象(假人)死亡
object_die(Object) ->
    #scene_object{sign = Sign, id = AutoId, scene = SceneId, copy_id = CopyId, figure = #figure{id = ObjId}, skill_owner = SkillOwner} = Object,
    case is_record(SkillOwner, skill_owner) of
        true -> OwnId = SkillOwner#skill_owner.id;
        false -> OwnId = 0
    end,
    case data_scene:get(SceneId) of
        #ets_scene{type = ?SCENE_TYPE_DUNGEON} when Sign == ?BATTLE_SIGN_DUMMY ->
            case misc:is_process_alive(CopyId) of
                true -> mod_dungeon:object_die(CopyId, AutoId, OwnId, ObjId);
                false -> skip
            end;
        _ ->
            skip
    end.

%% 对象(假人)停止
object_stop(Object) ->
    #scene_object{sign=_Sign, id = AutoId, scene = SceneId, copy_id = CopyId, skill_owner = SkillOwner, battle_attr = BA} = Object,
    case is_record(SkillOwner, skill_owner) of
        true -> OwnId = SkillOwner#skill_owner.id;
        false -> OwnId = 0
    end,
    case data_scene:get(SceneId) of
        #ets_scene{type = ?SCENE_TYPE_DUNGEON} ->
            case misc:is_process_alive(CopyId) of
                true -> mod_dungeon:object_stop(CopyId, AutoId, OwnId, BA#battle_attr.hp, BA#battle_attr.hp_lim);
                false -> skip
            end;
        _ ->
            skip
    end.

%% 玩家死亡(死亡次数以副本记录的为准，因为重登后玩家进程中的可能重设为0)
handle_event(Player, #event_callback{type_id = ?EVENT_PLAYER_DIE}) when is_record(Player, player_status) ->
    case lib_dungeon:is_on_dungeon(Player) of
        true ->
            #player_status{id = RoleId, copy_id = CopyId, dungeon = StatusDun, battle_attr = #battle_attr{hp_lim = HpLim} } = Player,
            #status_dungeon{dun_id = DunId, dead_count = DeadCount} = StatusDun,
            %% 更新玩家死亡状态数据
            NewDeadCount = DeadCount + 1,
            NewDeadTime  = utime:unixtime(),
            NewStatusDun = StatusDun#status_dungeon{dead_time = NewDeadTime, dead_count = NewDeadCount},
            NewPlayer    = Player#player_status{dungeon = NewStatusDun},
            % ?ERR("die type9:~p type1:~p dead_time:~p", [Count1, Count2, NewDeadTime]),
            case data_dungeon:get_dun(DunId) of
                #dun_cfg{} ->
                    lib_dungeon:send_reveive_info(NewPlayer),
                    mod_dungeon:player_die(CopyId, RoleId, HpLim, NewDeadCount, [{hp, 0}, {dead_time, NewDeadTime}]),
                    % 注意顺序,把死亡信息发送出去再复活成幽灵
                    % {_, NewPlayer2} = lib_revive:revive(NewPlayer, ?REVIVE_GHOST),
                    {ok, NewPlayer};
                _ ->
                    {ok, NewPlayer}
            end;
        false ->
            {ok, Player}
    end;

%% 玩家复活
handle_event(Player, #event_callback{type_id = ?EVENT_REVIVE, data = ReviveType}) when is_record(Player, player_status) ->
    #player_status{id = RoleId, copy_id = CopyId, battle_attr = #battle_attr{hp_lim = HpLim}, dungeon = Dungeon} = Player,
    case lib_dungeon:is_on_dungeon(Player) of
        true ->
            #status_dungeon{dun_id = DunId, revive_count = ReviveCount, cost_revive_count = CostReviveCount} = Dungeon,
            DunType = data_dungeon:get_dun_type(DunId),
            if ReviveType == 1 andalso DunType == ?DUNGEON_TYPE_GUARD ->
                    NewPlayer = Player#player_status{dungeon = Dungeon#status_dungeon{cost_revive_count = CostReviveCount+1}},
                    Args = [{cost_revive_count, CostReviveCount+1}, {hp, HpLim}];
                ReviveType == 9 andalso DunType  == ?DUNGEON_TYPE_GUARD ->
                    NewPlayer = Player#player_status{dungeon = Dungeon#status_dungeon{revive_count = ReviveCount+1}},
                    Args = [{revive_count, ReviveCount+1}, {hp, HpLim}];
                true ->
                    NewPlayer = Player#player_status{dungeon = Dungeon#status_dungeon{revive_count = ReviveCount+1}},
                    Args = [{revive_count, ReviveCount+1}, {hp, HpLim}]
            end,
            mod_dungeon:player_revive(CopyId, RoleId, ReviveType, Args),
            {ok, NewPlayer};
        false ->
            {ok, Player}
    end;

%% 完成场景的切换
handle_event(Player, #event_callback{type_id = ?EVENT_FIN_CHANGE_SCENE}) when is_record(Player, player_status) ->
    #player_status{id = RoleId, scene = Scene, copy_id = CopyId} = Player,
    IsDungeonScene = lib_scene:is_dungeon_scene(Scene),
    NewPlayer1 =
    if
        IsDungeonScene ->
            case lib_dungeon:is_on_dungeon(Player) of
                true ->
                    mod_dungeon:fin_change_scene(CopyId, RoleId),
                    Player;
                false -> Player
            end;
        true ->
            Player
    end,
    {ok, NewPlayer1};

%% 副本通关
handle_event(Player, #event_callback{type_id = ?EVENT_DUNGEON_SUCCESS, data = Data})  ->
    #player_status{id = RoleId, figure = #figure{name = RoleName, lv = RoleLv}} = Player,
    #callback_dungeon_succ{
        help_type=HelpType, dun_id = DunId, dun_type = DunType, dun_wave = DunWave, other = Other} = Data,
    if
        HelpType == ?HELP_TYPE_NO ->
            TmpPlayer = lib_dungeon:update_dungeon_record(Player, Data),
            case Other of
                [PlusCount|_] when DunType == ?DUNGEON_TYPE_CRUSADE orelse DunType == ?DUNGEON_TYPE_PER_BOSS -> ok;
                _ -> PlusCount = 1
            end,
            lib_dungeon:handle_task_trigger(TmpPlayer, Data#callback_dungeon_succ{distribute=?DUN_TASK_PASS_TRIGGER}),
            if DunType == ?DUNGEON_TYPE_PER_BOSS ->
                    BefNum = lib_daily:get_count(RoleId, ?MOD_DUNGEON, ?MOD_DUNGEON_SUCCESS, DunId),
                    PermanentCount = lib_counter:get_count(RoleId, ?MOD_DUNGEON, ?MOD_DUNGEON_PER_BOSS_ENTER, DunType);
                true ->
                    BefNum = 0, PermanentCount = 0
            end,
            %% 终生次数&每日次数+1
            lib_counter:plus_count(RoleId, ?MOD_DUNGEON, ?MOD_DUNGEON_SUCCESS, DunId, PlusCount),
            % DailyCountType = lib_dungeon_api:get_daily_pass_type(DunType, DunId),
            lib_daily:plus_count(RoleId, ?MOD_DUNGEON, ?MOD_DUNGEON_SUCCESS, DunId, PlusCount),
            case DunType of
                ?DUNGEON_TYPE_TOWER ->
                    case lib_dungeon_tower:is_diffcult_dun(DunId) of
                        true  ->
                            case Other of
                                [_, 3] ->
                                    lib_daily:increment(RoleId, ?MOD_DUNGEON, ?MOD_DUN_TOWER_3_STAR);
                                _ ->
                                    ignore
                            end;
                        false ->
                            lib_daily:increment(RoleId, ?MOD_DUNGEON, ?MOD_DUNGEON_SUCCESS, DunType)
                    end;
                _ ->
                    ignore
            end,
            DunPlayer = lib_dungeon:handle_achievement(TmpPlayer, DunId, [PlusCount]),
            contract_task_api:dun_task_trigger(RoleId, DunId, DunType, PlusCount),
            DunType == ?DUNGEON_TYPE_CRUSADE andalso lib_role_legion:trigger_task(DunPlayer, 215, 1, PlusCount),
            HiPointIsEnterTrigger = lists:member(DunType, ?HI_POINT_DUNGEON_SCORE_TRIGGER),
            if
                HiPointIsEnterTrigger ->
                    mod_hi_point:success_end(RoleId, ?MOD_DUNGEON, DunType, PlusCount),
                    custom_act_adventure:do_trigger_adventure_task(RoleId, ?MOD_DUNGEON, DunType, PlusCount);
                true ->
                    skip
            end,
            SevenDayIsEnterTrigger = lists:member(DunType, ?SEVEN_DAY_GOAL_DUNGEON_TRIGGER),
            if
                DunType =:= ?DUNGEON_TYPE_MATERIAL ->
                    lib_role_legion:trigger_task(DunPlayer, ?MOD_DUNGEON, 1),
                    {ok, NewPlay} = lib_seven_days_goal:do_finish_task(DunPlayer, ?MOD_DUNGEON, DunId);
                SevenDayIsEnterTrigger ->
                    {ok, NewPlay} = lib_seven_days_goal:finish_dungeon_task(DunPlayer, ?MOD_DUNGEON, DunType, DunWave);
                true ->
                    NewPlay = DunPlayer
            end,
            lib_activitycalen_api:success_finish_dungeon(RoleId, ?MOD_DUNGEON, DunType, DunId, PlusCount),
            custom_act_mobilize:finish_dungeon(RoleId,DunType,DunId),
            lib_custom_act_slices:finish_dungeon(RoleId,DunType),
            NewPlayer2 = lib_child_task:finish_multi_dun(NewPlay, DunType, DunId, PlusCount),
            NowTime = utime:unixtime(),
            DunType == ?DUNGEON_TYPE_PER_BOSS andalso begin
                AfterNum = lib_daily:get_count(RoleId, ?MOD_DUNGEON, ?MOD_DUNGEON_SUCCESS, DunId),
                IsFirstKill = ?IF(PermanentCount == 0, 1, 0),
                SvrNum = config:get_server_num(),
                case data_dungeon_wave:get_dun_wave(DunId, 1) of
                    #base_dun_wave_cfg{mon_list = [{BossId, _, _, _, _}|_]} -> ok;
                    _ -> BossId = 0
                end,
                case data_mon:get(BossId) of
                    #mon{lv = BossLv} -> ok;
                    _ -> BossLv  = 0
                end,
                lib_log_api:log_boss_change([RoleId, RoleName, 6, AfterNum, BefNum, 1, DunId, NowTime]),
                lib_log_api:log_boss_belong([RoleId, RoleName, 0, SvrNum, RoleLv, 6, BossLv, BossId, [], IsFirstKill, NowTime])
            end,
            ta_dun_ret_trigger(NewPlayer2, DunType, ?DUN_RESULT_TYPE_SUCCESS, Data),
            NewPlayer2;
        true ->
            NewPlayer2 = Player
    end,
    {ok, NewPlayer2};

handle_event(Player, #event_callback{type_id = ?EVENT_DUNGEON_FAIL, data = Data}) ->
    #player_status{id = RoleId} = Player,
    #callback_dungeon_succ{
        help_type=HelpType, dun_type = DunType, dun_wave = DunWave} = Data,
    if
        HelpType == ?HELP_TYPE_NO ->
            SevenDayIsEnterTrigger = lists:member(DunType, ?SEVEN_DAY_GOAL_DUNGEON_TRIGGER),
            if
                SevenDayIsEnterTrigger ->
                    {ok, NewPlayer} = lib_seven_days_goal:finish_dungeon_task(Player, ?MOD_DUNGEON, DunType, DunWave);
                true ->
                    NewPlayer = Player
            end;
      true ->
          NewPlayer = Player
    end,
    case DunType == ?DUNGEON_TYPE_PER_BOSS of
        true  ->
            NewPlayer1 = lib_dungeon:update_dungeon_record(NewPlayer, Data);
        false ->
            NewPlayer1 = NewPlayer
    end,
    
    lib_dungeon:handle_task_trigger(NewPlayer1, Data#callback_dungeon_succ{distribute=?DUN_TASK_ENTER_TRIGGER}),
    lib_custom_act_slices:enter_dungeon(RoleId, Data#callback_dungeon_succ.dun_type),
    ta_dun_ret_trigger(NewPlayer1, DunType, ?DUN_RESULT_TYPE_FAIL, Data),
    {ok, NewPlayer1};

%% 拾取掉落
% handle_event(Player, #event_callback{type_id = ?EVENT_DROP_CHOOSE, data = Data}) when is_record(Player, player_status) ->
%     #player_status{id = RoleId, copy_id = CopyId} = Player,
%     % #{goods := ObjectList, id := DropId} = Data,
%     case lib_dungeon:is_on_dungeon(Player) of
%         true ->
%             mod_dungeon:drop_choose(CopyId, RoleId, Data);
%         false -> skip
%     end,
%     {ok, Player};

handle_event(Player, #event_callback{type_id = ?EVENT_LV_UP}) when is_record(Player, player_status) ->
    #player_status{id = RoleId, copy_id = CopyId, figure = #figure{lv = Lv}} = Player,
    case lib_dungeon:is_on_dungeon(Player) of
        true -> mod_dungeon:update_dungeon_role(CopyId, RoleId, [{lv, Lv}]);
        false -> skip
    end,
    {ok, Player};

handle_event(Player, #event_callback{type_id = ?EVENT_LOGIN_CAST}) when is_record(Player, player_status) ->
    % {ok, NewPlayer} = lib_dungeon_stone:handle_daily_reward(Player, login),
    % {ok, NewPlayer2} = lib_dungeon_god_rune:handle_daily_reward(NewPlayer1, login),
    {ok, Player};

handle_event(PS, #event_callback{type_id = ?EVENT_DISCONNECT} = CallBack) when is_record(PS, player_status) ->
    {ok, NewPS} = lib_dungeon_flop:handle_event(PS, CallBack),
    case lib_dungeon:is_on_dungeon(NewPS) of
        true ->
            #player_status{id = RoleId, dungeon = StatusDun} = NewPS,
            #status_dungeon{dun_id = DunId} = StatusDun,
            case lib_dungeon:is_cluster_dungeon_by_dun_id(DunId) of
                true -> %% 跨服组队副本
                    {ok, NewPS1} = lib_dungeon:immediate_quit_dungeon(NewPS, ?DUN_RESULT_TYPE_FAIL),
                    ets:delete(?DUN_MULTI_ROLE_ETS, RoleId);
                _ -> NewPS1 = NewPS
            end;
        _    -> NewPS1 = NewPS
    end,
    {ok, NewPS1};

handle_event(Player, _EventCallback) ->
    {ok, Player}.

role_daily_reset(Player) ->
    NewPlayer = lib_dungeon_visus:logic_daily_reset(Player),
    NewPlayer.


%% 日常挑战次数类型
get_daily_count_type(_DunType = ?DUNGEON_TYPE_MATERIAL, DunId) ->
    DunId;
get_daily_count_type(_DunType = ?DUNGEON_TYPE_VIP, DunId) ->
    DunId;
get_daily_count_type(_DunType = ?DUNGEON_TYPE_CRUSADE, DunId) ->
    data_dun_multi_team:get_dun_act_type(DunId);
get_daily_count_type(_DunType = ?DUNGEON_TYPE_MAIN_LINE, DunId) ->
    DunId;
get_daily_count_type(DunType, _DunId) ->
    DunType.

%% 日常完成次数
get_daily_pass_type(_DunType = ?DUNGEON_TYPE_VIP, DunId) ->
    DunId;
get_daily_pass_type(_DunType = ?DUNGEON_TYPE_MATERIAL, DunId) ->
    DunId;
get_daily_pass_type(_DunType = ?DUNGEON_TYPE_TOWER, DunId) ->
    DunId;
get_daily_pass_type(DunType, _DunId) ->
    DunType.

%% 日常助战次数类型
get_daily_help_type(DunType, _DunId) ->
    DunType.

%% 日常重置次数类型
get_daily_reset_type(DunType, _DunId) ->
    DunType.

%% 日常购买次数类型
get_daily_buy_type(_DunType = ?DUNGEON_TYPE_MATERIAL, DunId) ->
    DunId;
get_daily_buy_type(_DunType = ?DUNGEON_TYPE_VIP, DunId) ->
    DunId;
get_daily_buy_type(DunType, _DunId) ->
    DunType.

%% 日常扫荡次数类型
get_daily_sweep_type(DunType, _DunId) ->
    DunType.

%% 日常层数通关类型
get_daily_level_type(DunType, _DunId) ->
    DunType.

%% 每日已挑战次数
get_daily_count_type_list(DunType) ->
    case get_daily_count_type(DunType, -1) of
        DunType ->
            [{?MOD_DUNGEON, ?MOD_DUNGEON_ENTER, DunType}];
        _ ->
            [{?MOD_DUNGEON, ?MOD_DUNGEON_ENTER, Id} || Id <- data_dungeon:get_ids_by_type(DunType)]
    end.

%% 每日VIP购买的次数
get_daily_buy_type_list(DunType) ->
    case get_daily_count_type(DunType, -1) of
        DunType ->
            [{?MOD_DUNGEON, ?MOD_DUNGEON_BUY, DunType}];
        _ ->
            [{?MOD_DUNGEON, ?MOD_DUNGEON_BUY, Id} || Id <- data_dungeon:get_ids_by_type(DunType)]
    end.


%% 每日VIP购买次数已使用次数
get_vip_use_type_list(DunType) ->
    case get_daily_count_type(DunType, -1) of
        DunType ->
            [{?MOD_DUNGEON, ?MOD_DUNGEON_BUY_USE, DunType}];
        _ ->
            [{?MOD_DUNGEON, ?MOD_DUNGEON_BUY_USE, Id} || Id <- data_dungeon:get_ids_by_type(DunType)]
    end.

%% return false|true
check_ever_finish(#player_status{id = RoleId} = Player, DunId) ->
    case data_dungeon:get_dun(DunId) of
        #dun_cfg{type = DunType} ->
            case lib_dungeon_distribute:get_special_api_mod(DunType, update_dungeon_record, 2) of
                undefined ->
                    check_ever_finish(RoleId, DunId);
                _ ->
                    case Player#player_status.dungeon_record of
                        undefined ->
                            % lib_player:apply_cast(RoleId, ?APPLY_CAST_STATUS, lib_dungeon, load_dungeon_record, []),
                            check_ever_finish(RoleId, DunId);
                        Rec ->
                            maps:is_key(DunId, Rec)
                    end
            end;
        _ ->
            false
    end;

%% 判断副本是否曾经完成过
check_ever_finish(RoleId, DunId) when is_integer(RoleId) ->
    Count = lib_counter:get_count_offline(RoleId, ?MOD_DUNGEON, ?MOD_DUNGEON_SUCCESS, DunId),
    Count > 0.

%% 判断副本今天是否挑战过
check_today_playered(RoleId, DunId) ->
    Count = lib_daily:get_count_offline(RoleId, ?MOD_DUNGEON, ?MOD_DUNGEON_ENTER, DunId),
    Count > 0.

%% 判断副本今天是否通关过
check_today_passed(RoleId, DunId) ->
    Count = lib_daily:get_count_offline(RoleId, ?MOD_DUNGEON, ?MOD_DUNGEON_SUCCESS, DunId),
    Count > 0.

%% 获取副本的定制活动多倍掉落倍数(旧代码,已经废弃)
get_custom_act_drop_times(DunType) ->
    case lib_custom_act_api:get_open_custom_act_infos(?CUSTOM_ACT_TYPE_DUN_MUL_DROP) of
        [#act_info{key = {ActId, SubId}}|_] ->
            case lib_custom_act_util:get_act_cfg_info(ActId, SubId) of
                #custom_act_cfg{condition = Condition} ->
                    case lists:keyfind(types, 1, Condition) of
                        {types, Types} ->
                            case lists:keyfind(DunType, 1, Types) of
                                {DunType, N} ->
                                    N;
                                _ ->
                                    1
                            end;
                        _ ->
                            1
                    end;
                _ ->
                    1
            end;
        _ ->
            1
    end.

%% 获取副本的定制活动多倍掉落倍数
get_custom_act_exp_ratio(DunType) ->
    case lib_custom_act_api:get_open_custom_act_infos(?CUSTOM_ACT_TYPE_DUN_MUL_EXP) of
        [#act_info{key = {ActId, SubId}}|_] ->
            case lib_custom_act_util:get_act_cfg_info(ActId, SubId) of
                #custom_act_cfg{condition = Condition} ->
                    case lists:keyfind(types, 1, Condition) of
                        {types, Types} ->
                            case lists:keyfind(DunType, 1, Types) of
                                {DunType, N} ->
                                    case lists:keyfind(time, 1, Condition) of
                                        {time, {{H1, M1, S1}, {H2, M2, S2}}} ->
                                            S = utime:get_seconds_from_midnight(),
                                            if
                                                H1*3600 + M1*60 + S1 =< S andalso S =< H2*3600 + M2*60 + S2 ->
                                                    N;
                                                true ->
                                                    0
                                            end;
                                        _ ->
                                            N
                                    end;
                                _ ->
                                    0
                            end;
                        _ ->
                            0
                    end;
                _ ->
                    0
            end;
        _ ->
            0
    end.

%% 获取副本的定制活动多倍奖励倍数
get_custom_act_reward_times(DunType, DunId, RoleLv) ->
    NowTime  = utime:unixtime(),
    UnixDate = utime:unixdate(NowTime),
    case lib_custom_act_api:get_open_custom_act_infos(?CUSTOM_ACT_THEME_DUN_MUL_REWARD) of
        [#act_info{}|_] = ActInfoList ->
            ForFun = fun(#act_info{key = {ActId, SubId}, stime = STime, etime = ETime}, Times) ->
                case lib_custom_act_util:get_act_cfg_info(ActId, SubId) of
                    #custom_act_cfg{condition = Condition, optime = OpTime} ->
                        %% 判断真实控制时间段是否满足
                        case OpTime =/= [] of
                            true ->
                                OpTimeL = lib_custom_act_util:format_time(OpTime, UnixDate);
                            _ ->
                                OpTimeL = []
                        end,
                        IsOpen = case OpTimeL of
                                     [{StartTime, EndTime}|_] when NowTime >= StartTime andalso NowTime < EndTime ->
                                        true;
                                     [] when NowTime >= STime andalso NowTime < ETime ->
                                        true;
                                     _ ->
                                        false
                                 end,
                        case IsOpen of
                            true ->
                                %% 判断是否满足等级条件
                                case lists:keyfind(role_lv, 1, Condition) of
                                    {_, OpenLv} when RoleLv >= OpenLv ->
                                        case lists:keyfind(type, 1, Condition) of
                                            {type, DunType} ->
                                                case lists:keyfind(multiple, 1, Condition) of
                                                    {_, N} ->
                                                        N;
                                                    _ ->
                                                        Times
                                                end;
                                            {type, DunType, DunId} ->
                                                case lists:keyfind(multiple, 1, Condition) of
                                                    {_, N} ->
                                                        N;
                                                    _ ->
                                                        Times
                                                end;
                                            _ ->
                                                Times
                                        end;
                                    _ ->
                                        Times
                                end;
                            _ ->
                                Times
                        end;
                    _ ->
                        Times
                end end,
            lists:foldl(ForFun, 1, ActInfoList);
        _ ->
            1
    end.

%% 计算多倍奖励
calc_multi_times_goods(GoodsList, MultiTimes) ->
    ForFun = fun(GoodsInfo, TGoodsList) ->
        case GoodsInfo of
            {GoodType, GoodsTypeId, GoodsNum} ->
                [{GoodType, GoodsTypeId, GoodsNum*max(1, MultiTimes-1)}|TGoodsList];
            {GoodType, GoodsTypeId, GoodsNum, Args} ->
                [{GoodType, GoodsTypeId, GoodsNum*max(1, MultiTimes-1), Args}|TGoodsList];
            _ ->
                TGoodsList
        end end,
    NewGoodsList = lists:foldl(ForFun, [], GoodsList),
    NewGoodsList.

get_dungeon_name(DunId) ->
    case data_dungeon:get_dun(DunId) of
        #dun_cfg{name = Name} ->
            util:make_sure_binary(Name);
        _ ->
            <<"">>
    end.

get_dungeon_condition_lv(DunId) ->
    case data_dungeon:get_dun(DunId) of
        #dun_cfg{condition = Conditions} ->
            case lists:keyfind(lv, 1, Conditions) of
                {lv, Lv} ->
                    Lv;
                _ ->
                    0
            end;
        _ ->
            0
    end.

get_min_condition_lv(DunType) ->
    case data_dungeon:get_ids_by_type(DunType) of
        [] ->
            0;
        List ->
            lists:min([get_dungeon_condition_lv(DunId) || DunId <- List])
    end.

% get_dun_left_count(RoleId, DunIds) ->
%     lib_dungeon:get_dungeon_count(RoleId, DunIds).

%%获取副本类型
get_dungeon_type_by_scene(SceneId) ->
    DungeonTypeList = data_dungeon:get_type_by_scene(SceneId),
    case DungeonTypeList of
        [DungeonType|_T] -> DungeonType;
        _ -> 0
    end.

get_need_lv(DunId) ->
    case data_dungeon:get_dun(DunId) of
        #dun_cfg{condition = Conditions} ->
            case lists:keyfind(lv, 1, Conditions) of
                {lv, NeedLv} ->
                    NeedLv;
                _ -> 1
            end;
        _ ->
            1
    end.

check_dun_hp_event(DunId, RoleLv) ->
    case data_dungeon_grade:get_dungeon_grade(DunId, RoleLv) of
        #dungeon_grade{condition = Conditions} ->
            lists:keymember(rest_hp, 2, Conditions);
        _ -> false
    end.

ta_dun_ret_trigger(Player, DunType, ResultType, Data) ->
    #callback_dungeon_succ{dun_id = DunId, pass_time = UseTime, other = Other} = Data,
    if DunType == ?DUNGEON_TYPE_MATERIAL ->
            ta_dun_ret(Player, DunType, [DunId, false, ResultType, 1]);
        DunType == ?DUNGEON_TYPE_TOWER ->
            case data_tower_dun:get_diffcult_dun(DunId) of
                [_|_] -> DunLevel = 2;
                _ -> DunLevel = 1
            end,
            #dun_cfg{recommend_power = PowerAdvice} = data_dungeon:get_dun(DunId),
            [ResultSubType, DunStar|_] = Other,
            if DunLevel == 1 orelse ResultType == ?DUN_RESULT_TYPE_FAIL -> 
                    DunStar1 = 0;
                true -> DunStar1 = DunStar
            end,
            ta_dun_ret(Player, DunType, [DunId, DunLevel, ResultType, ResultSubType, DunStar1, PowerAdvice, UseTime]);
        DunType == ?DUNGEON_TYPE_VISUS ->
            [ResultSubType, OldDunWave, NewDunWave, LastWaveRet] = Other,
            ta_dun_ret(Player, DunType, [DunId, OldDunWave, NewDunWave, LastWaveRet, ResultSubType, UseTime]);
        DunType == ?DUNGEON_TYPE_EXP ->
            [ResultSubType, OldDunWave, NewDunWave, LastWaveRet] = Other, 
            case data_dungeon_wave:get_dun_wave(DunId, OldDunWave) of
                #base_dun_wave_cfg{recommend_power = PowerAdvice} -> ok;
                _ -> PowerAdvice = 0
            end,
            ta_dun_ret(Player, DunType, [OldDunWave, NewDunWave, PowerAdvice, LastWaveRet, ResultSubType, UseTime]);
        true -> skip
    end.

%% 副本TA数据上报接口
-spec ta_dun_ret(Player, DunType, DunRetArgs) -> ok when
    Player :: #player_status{},
    DunType     :: 
        ?DUNGEON_TYPE_MATERIAL | ?DUNGEON_TYPE_TOWER | ?DUNGEON_TYPE_VISUS |
        ?DUNGEON_TYPE_EXP      | ?DUNGEON_TYPE_GUARD,
    DunRetArgs  :: list().
ta_dun_ret(Player, ?DUNGEON_TYPE_MATERIAL, [DunId, IsSweep, ResultType, DunTimes|_]) ->
    ta_agent_fire:foster_dungeon(Player, [DunId, IsSweep, ResultType, DunTimes]);
ta_dun_ret(Player, ?DUNGEON_TYPE_TOWER, [DunId, DunLevel, ResultType, ResultSubType, DunStar, PowerAdvice, UseTime]) ->
    ta_agent_fire:tower_dungeon(Player, [DunId, DunLevel, ResultType, ResultSubType, DunStar, PowerAdvice, UseTime]);
ta_dun_ret(Player, ?DUNGEON_TYPE_VISUS, [DunId, OldDunWave, NewDunWave, ResultType, ResultSubType, UseTime]) ->
    ta_agent_fire:llusory_light(Player, [DunId, OldDunWave, NewDunWave, ResultType, ResultSubType, UseTime]);
ta_dun_ret(Player, ?DUNGEON_TYPE_EXP, [OldDunWave, NewDunWave, PowerAdvice, ResultType, ResultSubType, UseTime]) ->
    ta_agent_fire:exp_dungeon(Player, [OldDunWave, NewDunWave, PowerAdvice, ResultType, ResultSubType, UseTime]);
ta_dun_ret(_Player, _DunType, _DunRetArgs) ->
    ok.

ta_multi_dun_ret(Player, ?DUNGEON_TYPE_CRUSADE, [MaxRating, DunId, ResultSubType, PassTime, SingleMode, PlayerNum, RobotNum, AssistNum]) ->
    ta_agent_fire:multi_dungeon(Player, [MaxRating, DunId, ResultSubType, PassTime, SingleMode, PlayerNum, RobotNum, AssistNum]),
    ok;
ta_multi_dun_ret(Player, ?DUNGEON_TYPE_GUARD, 
    [ReviveCount, IsLeader, PlayerNum, RobotNum, PowerNeed, DunId, Role2Power, Role3Power, ResultSubType, PassTime, DunWave, HpTop, HpMid, HpBot|_]) ->
    ta_agent_fire:guard_dungeon(Player, 
        [ReviveCount, IsLeader, PlayerNum, RobotNum, PowerNeed, DunId, Role2Power, Role3Power, ResultSubType, PassTime, DunWave, HpTop, HpMid, HpBot]),
    ok;
ta_multi_dun_ret(_Player, _DunType, _) ->
    ?ERR("~p", [_DunType]),
    ok.
