%% ------------------------------------
%% module   :lib_dungeon_main_line.erl
%% desc     :新主线副本
%% author   :hh
%% time     :21/07/12
%% ------------------------------------

-module (lib_dungeon_main_line).

-export ([
    handle_wave_state/2,
    get_send_reward/2,
    get_role_rec/6,
    check_extra/2
    ,get_main_line_max/5
    ,get_open_main_line/2
    ,handle_event/2
    ,get_all_open_lv/0
    ,role_update_score_event_rewards_state/2
    ,get_dun_score_rewards/4
]).

-include ("dungeon.hrl").
-include ("common.hrl").
-include ("server.hrl").
-include ("errcode.hrl").
-include ("def_module.hrl").
-include ("figure.hrl").
-include ("def_event.hrl").
-include ("rec_event.hrl").
-include ("predefine.hrl").

handle_wave_state(State, [WaveState|_] = Args) ->
    if WaveState =/= ?DUN_PASS -> %% 下一波
            dungeon_default:handle_wave_state_normal(State, Args);
        true -> %% 通关
            State1 = dungeon_default:handle_wave_state_normal(State, Args),
            #dungeon_state{dun_id = DunId, role_list = [#dungeon_role{id = RoleId, grade_progress = GradeProgress, typical_data = TypicalData}|_]} = State1,
            case GradeProgress of
                #dungeon_role_grade{map = Maps} -> ok;
                _ -> Maps = #{}
            end,
            MaxStar = maps:get(?DUNGEON_REC_MAX_STARS, TypicalData, 0),
            {StarNum, _} = dungeon_default:calc_dun_score_event_id(Maps),
            if MaxStar < 3 andalso StarNum >= 3 ->
                    lib_player:apply_cast(RoleId, ?APPLY_CAST_STATUS, ?MODULE, role_update_score_event_rewards_state, [DunId]);
                true ->
                    skip
            end,
            State1
    end.

get_send_reward(State, _DungeonRole) ->
    #dungeon_state{result_type = ResultType, dun_id = DunId} = State,
    if
        ResultType == ?DUN_RESULT_TYPE_SUCCESS ->
            case data_dungeon:get_dun(DunId) of
                #dun_cfg{base_reward = BaseRewards} -> ok;
                _ -> BaseRewards = []
            end,
            BaseRewards;
        true ->
            []
    end.

get_role_rec(_DunType, _DunId, _Id, DungeonRec, _DunData, TypicalData) ->
    MaxStar =
        case lists:keyfind(?DUNGEON_REC_MAX_STARS, 1, DungeonRec) of
            {_, StarEvents} -> length(StarEvents);
            _ -> 0
        end,
    maps:put(?DUNGEON_REC_MAX_SCORE, MaxStar, TypicalData).

check_extra(_Player, _Dun) ->
    % #dun_cfg{id = DunId} = Dun,
    % #player_status{dungeon_record = DunRecs} = Player,
    % DunRec = maps:get(DunId, DunRecs, []),
    % case lists:keyfind(?DUNGEON_REC_MAX_STARS, 1, DunRec) of
    %     {_, ScoreEventIds} -> ok;
    %     _ -> ScoreEventIds = []
    % end,
    % StarNum = length(ScoreEventIds),
    if
    % StarNum >= 3 ->
    %     {false, ?ERRCODE(err610_dun_have_three_star)};
        true ->
            true
    end.

role_update_score_event_rewards_state(Player, DunId) ->
    #player_status{id = RoleId, dungeon_record = AllDunRec} = Player,
    DunRec = maps:get(DunId, AllDunRec, []),
    case lists:keyfind(?DUNGEON_REC_DATA, 1, DunRec) of
        {_, _} ->
            {ok, Player};
        false ->
            DunRec1     = lists:keystore(?DUNGEON_REC_DATA, 1, DunRec, {?DUNGEON_REC_DATA, 0}),
            lib_dungeon:save_dungeon_record(RoleId, DunId, DunRec1),
            AllDunRec1  = maps:put(DunId, DunRec1, AllDunRec),
            Player1     = Player#player_status{dungeon_record = AllDunRec1},
            {ok, Player1}
    end.

get_dun_score_rewards(RoleId, AllDunRecs, DunRec, DunId) ->
    DunRec1 = lists:keystore(?DUNGEON_REC_DATA, 1, DunRec, {?DUNGEON_REC_DATA, 1}),
    lib_dungeon:save_dungeon_record(RoleId, DunId, DunRec1),
    AllDunRecs1 = maps:put(DunId, DunRec1, AllDunRecs),
    AllDunRecs1.

handle_event(Player, #event_callback{type_id = ?EVENT_LV_UP})
    when is_record(Player, player_status) andalso Player#player_status.online =:= ?ONLINE_ON ->
    #player_status{figure = Figure} = Player,
    AllLvs = get_all_open_lv(),
    case lists:member(Figure#figure.lv, AllLvs) of
        true ->
            %% 只需要请求非限时活动就可以了，更新主线任务的次数
            pp_activitycalen:handle(15701, Player, [1]);
        _ ->
            ignore
    end,
    {ok, Player};
handle_event(Player, _) ->
    {ok, Player}.

%% 主线副本最大次数
%% 解锁之后最大上限需要调整
get_main_line_max(Module, ModuleSub, Player, Times, Max) ->
    #player_status{id = RoleId, figure = Figure} = Player,
    case lists:member({Module, ModuleSub}, [{?MOD_DUNGEON, 20}]) of
        true ->
            get_open_main_line(RoleId, Figure#figure.lv);
        _ ->
            {Times, Max}
    end.

get_open_main_line(RoleId, RoleLv) ->
    DunIds = data_dungeon:get_ids_by_type(20),
    case DunIds of
        [_|_] ->
            MinDunId = lists:min(DunIds),
            MaxDunId = lists:max(DunIds);
        _ ->
            MinDunId = 0, MaxDunId = 0
    end,
    DailyCountList = lib_daily:get_count(RoleId, ?MOD_DUNGEON, ?MOD_DUNGEON_ENTER, DunIds),
    HisCountList   = lib_counter:get_count(RoleId, ?MOD_DUNGEON, ?MOD_DUNGEON_SUCCESS, DunIds),
    {OpenDunId, FilterList} = filter_has_open_dun(HisCountList),
    Index = ulists:index_of(OpenDunId, DunIds),
    NextDunId = get_nth_dun(Index+1, DunIds),
    FilterList1 = case NextDunId =< MaxDunId of
                      true when NextDunId > 0 -> [{NextDunId, 1}|FilterList];
                      _ -> FilterList
                  end,
    OpenDay = util:get_open_day(),
    case OpenDunId > 0 of
        true ->
            UseTimes = lists:foldl(fun(CountInfo, TTimes) ->
                case CountInfo of
                    {_, Count} -> Count + TTimes;
                    _ -> TTimes
                end end, 0, DailyCountList),
            CfgTimes = lists:foldl(fun(CountInfo, TTimes) ->
                case CountInfo of
                    {DunId, _} ->
                        DunTimes = get_config_times(DunId, RoleLv, OpenDay),
                        DunTimes + TTimes;
                    _ -> TTimes
                end end, 0, FilterList1),
            {UseTimes, CfgTimes};
        _ ->
            {0, get_config_times(MinDunId, RoleLv, OpenDay)}
    end.

filter_has_open_dun(CountList) ->
    F = fun(CountInfo, {TDunId, TList}) ->
        case CountInfo of
            {DunId, Count} when Count > 0 ->
                {   DunId,
                    [CountInfo|TList]
                };
            _ ->
                {TDunId, TList}
        end end,
    lists:foldl(F, {0, []}, CountList).

get_config_times(DunId, RoleLv, OpenDay) ->
    case data_dungeon:get_dun(DunId) of
        #dun_cfg{count_cond = [{_, Times}], condition = Condition} ->
            NeedLv = case lists:keyfind(lv, 1, Condition) of
                         {_, TNeedLv} -> TNeedLv;
                         _ -> 0
                     end,
            NeedDay = case lists:keyfind(open_day, 1, Condition) of
                          {_, TNeedDay} -> TNeedDay;
                          _ -> 0
                      end,
            case RoleLv >= NeedLv andalso OpenDay >= NeedDay of
                true -> Times;
                _ -> 0
            end;
        _ -> 0
    end.

get_nth_dun(Index, List) ->
    F = fun(DunId, {TDunId, TNum}) ->
        TNum1 = TNum + 1,
        case TNum1 == Index of
            true -> {DunId, TNum1};
            _ -> {TDunId, TNum1}
        end end,
    {GetDunId, _} = lists:foldl(F, {0, 0}, List),
    GetDunId.

%% 获取副本的所有开放等级
get_all_open_lv() ->
    DunIds = data_dungeon:get_ids_by_type(20),
    F = fun(DunId, TList) ->
        case data_dungeon:get_dun(DunId) of
            #dun_cfg{condition = Condition} ->
                case lists:keyfind(lv, 1, Condition) of
                    {_, NeedLv} -> [NeedLv|TList];
                    _ -> TList
                end;
            _ -> TList
        end end,
    AllLv = lists:foldl(F, [], DunIds),
    lists:usort(AllLv).