%%%-------------------------------------------------------------------
%%% @author liusl
%%% @copyright (C) 2020, <COMPANY>
%%% @doc
%%%     单人boss
%%% @end  ConnPid = spawn(fun() -> ok end)
%%% Created : 17. 2月 2020 14:57
%%%-------------------------------------------------------------------
-module(lib_dungeon_personal_boss).
-author("liusl").

%% API
-export([
    update_dungeon_record/2,
    get_create_mon_args/1,
    handle_enter_dungeon/2,
    handle_wave_state/2,
    handle_kill_mon_do/2,
    get_dun_result_succ_args/2
    ,player_kill_personal_boss/6
    ,player_after_cost_boss_times/4
    ,is_can_merge/2
    ,check_merge_count_condition/4
    ,get_role_typical_data/6
]).

-include("dungeon.hrl").
-include("figure.hrl").
-include("common.hrl").
-include("predefine.hrl").
-include("server.hrl").
-include("scene.hrl").
-include("drop.hrl").
-include("def_module.hrl").
-include("local_boss.hrl").
-include("def_fun.hrl").
-include("rec_event.hrl").
-include("errcode.hrl").

%% @doc  是否可以合并次数：历史最高波数达到5才可以合并
is_can_merge(Player, DunId) ->
    #player_status{dungeon_record = DunRecs} = Player,
    DunRec = maps:get(DunId, DunRecs, []),
    %% 历史最佳表示历史最大波数
    Key = ?DUNGEON_REC_MAX_SCORE,
    case lists:keyfind(Key, 1, DunRec) of
        {_, Wave} when Wave >= 5 ->
            true;
        _ ->
            false
    end.

%% @doc 副本通用派发方法，更新历史记录
update_dungeon_record(Player, #callback_dungeon_succ{help_type = ?DUN_TEAM_HELP_YES}) ->
    Player;
update_dungeon_record(Player, Data) ->
    #callback_dungeon_succ{dun_id = DunId, dun_wave = DunWave} = Data,
    #player_status{id = RoleId, dungeon_record = DunRecs} = Player,
    DunRec = maps:get(DunId, DunRecs, []),
    %% 历史最佳表示历史最大波数
    Key = ?DUNGEON_REC_MAX_SCORE,
    NewDunRec = case lists:keyfind(Key, 1, DunRec) of
        {_, OldMax} ->
            case DunWave > OldMax of
                true  ->
                    Update = true,
                    lists:keyreplace(Key, 1, DunRec, {Key, DunWave});
                false ->
                    Update = false,
                    DunRec
            end;
        _ ->
            Update = true,
            [{Key, DunWave}|DunRec]
    end,
    NewDunRecs = maps:put(DunId, NewDunRec, DunRecs),
    NewPlayer = Player#player_status{dungeon_record = NewDunRecs},
    Update andalso lib_dungeon:save_dungeon_record(RoleId, DunId, NewDunRec),
    NewPlayer.

%% @doc 副本派发方法：怪物创建参数，给掉落增加来源
get_create_mon_args(#dungeon_state{role_list = [#dungeon_role{typical_data = TypicalData}|_]}) ->
    [{origin, ?DROP_ORIGIN_PERSONAL_BOSS},
    {mod_args, #{?DROP_MERGE_MULTI_COUNT => maps:get(?DUN_ROLE_DAILY_ENTER_COUNT, TypicalData, 1)}}];
get_create_mon_args(_) -> [].

%% @doc 副本派发方法：所以进入触发的逻辑可以放这里
handle_enter_dungeon(Player, Dun) ->
    #player_status{id = RoleId} = Player,
    #dun_cfg{type = DunType} = Dun,
    lib_counter:increment(RoleId, ?MOD_DUNGEON, ?MOD_DUNGEON_PER_BOSS_ENTER, DunType),
    Player.

%% @doc 副本派发方法：波数通关，扣除副本次数才触发的逻辑可以放这里
handle_wave_state(State, [?WAVE_NEXT, 1|_] = Arg) ->
    case State of
        #dungeon_state{role_list = [#dungeon_role{id = RoleId, typical_data = TypicalData}|_], dun_id = DunId} ->
            MergeType = maps:get(?DUN_ROLE_COUNT_MERGE, TypicalData, 0),
            PlusCount = maps:get(?DUN_ROLE_DAILY_ENTER_COUNT, TypicalData, 1),
            %% 更新首次进入单个副本
            lib_player:apply_cast(RoleId, ?APPLY_CAST_STATUS, ?MODULE, player_after_cost_boss_times, [DunId, MergeType, PlusCount]);
        _ ->
            ok
    end,
    dungeon_default:handle_wave_state_normal(State, Arg);
handle_wave_state(State, Arg) ->
    dungeon_default:handle_wave_state_normal(State, Arg).


%% @doc 副本派发方法，击杀BOSS，每击杀一只触发一次，一个副本有5只，所以最多会触发5次
handle_kill_mon_do(DungeonState, [Mid, _Killer, _MonXys|_] = Arg) ->
    case DungeonState of
        #dungeon_state{start_time = StartTime, role_list = [#dungeon_role{id = RoleId, revive_count = ReviveCount}|_],
            wave_num = WaveNum, dun_id = DunId} ->
            lib_player:apply_cast(RoleId, ?APPLY_CAST_STATUS, ?MODULE, player_kill_personal_boss, [Mid, ReviveCount, StartTime, WaveNum, DunId]);
        _ ->
            ok
    end,
    dungeon_default:handle_kill_mon_do_normal(DungeonState, Arg).

get_dun_result_succ_args(DunRole, [_ResultSubType|_]) ->
    #dungeon_role{typical_data = TypicalData} = DunRole,
    PlusCount = maps:get(?DUN_ROLE_DAILY_ENTER_COUNT, TypicalData, 1),
    [PlusCount].

%% 幻魔宝典、嗨点、活动-冒险征途、七日目标、定制活动-全民动员、积分拼图
%% 成就、国家任务、首饰成长属性、TA幻魔归属上报
player_kill_personal_boss(Player, Mid, ReviveCount, StartTime, WaveNum, DunId) ->
    {ok, Player1} = lib_seven_days_goal:do_kill_boss(Player, ?MOD_LOCAL_BOSS, 1, Mid),
    case data_local_boss:get_personal_boss_info(Mid) of
        [{Grade, _}] -> ok;
        _ -> Grade = 0
    end,
    case data_mon:get(Mid) of
        #mon{lv = BossLv} -> ok;
        _ -> BossLv = 0
    end,
    Series = DunId rem 6000,
    lib_elite_assess_api:person_boss_event(Player1, {Series, WaveNum}),
    LeftCount = lib_counter:get_count(Player#player_status.id, ?MOD_LOCAL_BOSS, ?COUNT_REWARD_BOSS_COUNTER_KILL, Mid),
    IsFirstKill = ?IF(LeftCount == 0, true, false),
    UseTime = utime:unixtime() - StartTime,
    ta_agent_fire:single_boss_belong(Player1, [Mid, BossLv, Grade, IsFirstKill, ReviveCount, UseTime]),
    Player1.

%% 个人BOSS扣除次数时的统计
player_after_cost_boss_times(Player, DunId, _MergeType, PlusCount) ->
    #player_status{id = RoleId} = Player,
    DunType = ?DUNGEON_TYPE_PER_BOSS,
    LifeCount = lib_counter:get_count(RoleId, ?MOD_DUNGEON, ?MOD_DUNGEON_FIRTS_ENTER, DunId),
    case LifeCount =< 0 of
        true ->
            %% 首次进入
            lib_counter:increment(RoleId, ?MOD_DUNGEON, ?MOD_DUNGEON_FIRTS_ENTER, DunId);
        false ->
            %% 非首次进入才记录日常
            lib_activitycalen_api:role_success_end_activity(RoleId, ?MOD_LOCAL_BOSS, 1, PlusCount)
    end,
    %% 统计每日参与次数
    lib_daily:plus_count(RoleId, ?MOD_DUNGEON, ?MOD_DUN_TAKE_PART_IN, DunType, PlusCount),
    {ok, Player1} = lib_achievement_api:kill_per_boss_event(Player, PlusCount),
    Player2 = trigger_phantom_task(Player1, PlusCount),
    mod_hi_point:success_end(Player#player_status.id, ?MOD_LOCAL_BOSS, 1, PlusCount),
    custom_act_adventure:do_trigger_adventure_task(Player#player_status.id, ?MOD_LOCAL_BOSS, 1, PlusCount),

    Player3 = trigger_custom_act_slices(Player2, PlusCount),
    Player4 = lib_role_legion:trigger_task(Player3,?MOD_LOCAL_BOSS,1,PlusCount),
    Player5 = equipment_logic:kill_personal_boss(Player4, PlusCount),
    custom_act_mobilize:update_mobilize_task(Player5, killboss, PlusCount),
    Player5.

trigger_phantom_task(Player, 0) -> Player;
trigger_phantom_task(Player, MergeCount) ->
    {ok, Player1} = phantom_task_api:kill_person_boss_trigger(Player),
    trigger_phantom_task(Player1, MergeCount - 1).

trigger_custom_act_slices(Player, 0) -> Player;
trigger_custom_act_slices(Player, MergeCount) ->
    {ok, Player1} = lib_custom_act_slices:task_event(Player, ?MOD_LOCAL_BOSS,1),
    trigger_custom_act_slices(Player1, MergeCount - 1).

check_merge_count_condition(OpType, DunType, DunId, Player) ->
    #player_status{id = RoleId, figure = #figure{lv = RoleLv}} = Player,
    CheckList = [alive, safe_scene, action_free, dun_multi_match],
    if OpType > 0 ->
            IsCanMerge = is_can_merge(Player, DunId),
            CountType = lib_dungeon_api:get_daily_count_type(DunType, DunId),
            DailyCount = lib_daily:get_count(RoleId, ?MOD_DUNGEON, ?MOD_DUNGEON_ENTER, CountType),
            if
                not IsCanMerge ->
                    {false, ?ERRCODE(err610_boss_need_all_pass)};
                DailyCount =< 1 ->
                    {false, ?FAIL};
                true ->
                    MerCountLv = data_dungeon_special:get(DunType, merges_lv_1),
                    if is_integer(MerCountLv) ->
                            if RoleLv >= MerCountLv ->
                                    lib_player_check:check_list(Player, CheckList);
                                true ->
                                    {false, ?ERRCODE(err610_mer_lv_limit)}
                            end;
                        true ->
                            lib_player_check:check_list(Player, CheckList)
                    end
            end;
        true ->
            lib_player_check:check_list(Player, CheckList)
    end.

get_role_typical_data(RoleId, DunId, DunType, OpType, [{_, MaxNum}|_], TypicalData) ->
    TypicalData1 = maps:put(?DUN_ROLE_COUNT_MERGE, OpType, TypicalData),
    CountType = lib_dungeon_api:get_daily_count_type(DunType, DunId),
    % DailyCount = lib_daily:get_count(RoleId, ?MOD_DUNGEON, ?MOD_DUNGEON_ENTER, CountType),
    CountList = [
        {?MOD_DUNGEON, ?MOD_DUNGEON_BUY, CountType},
        {?MOD_DUNGEON, ?MOD_DUNGEON_ENTER, CountType},
        {?MOD_DUNGEON, ?MOD_DUNGEON_BUY_USE, CountType}
    ],
    case lib_daily:get_count(RoleId, CountList) of
        [{_, GoldBuy}, {_, DailyCount}, {_, BuyUseCount}] -> ok;
        _ -> DailyCount = BuyUseCount = GoldBuy = 0
    end,
    if OpType == 1 ->
            MergeEnterCount = MaxNum - DailyCount,
            MergeBuyCount   = GoldBuy - BuyUseCount,
            MergeCount      = MergeEnterCount + MergeBuyCount,
            TypicalData2 = maps:put(?DUN_ROLE_DAILY_ENTER_COUNT, MergeCount, TypicalData1),
            maps:put(?DUN_ROLE_DAILY_COUNTS, {MergeEnterCount, MergeBuyCount}, TypicalData2);
        true ->
            TypicalData2 = maps:put(?DUN_ROLE_DAILY_ENTER_COUNT, 1, TypicalData1),
            CostCountType = maps:get(?DUN_ROLE_COUNT_COST_TYPE, TypicalData),
            if CostCountType == ?MOD_DUNGEON_BUY_USE ->
                    maps:put(?DUN_ROLE_DAILY_COUNTS, {0, 1}, TypicalData2);
                true ->
                    maps:put(?DUN_ROLE_DAILY_COUNTS, {1, 0}, TypicalData2)
            end
    end.