%%%------------------------------------
%%% @Module  : lib_arena_util
%%% @Author  :  fwx
%%% @Created :  2017-03-23
%%% @Description: arena
%%%------------------------------------
-module(lib_arena_util).
-export([]).

-compile(export_all).

-include("common.hrl").
-include("arena.hrl").
-include("attr.hrl").
-include("fake_role.hrl").
-include("def_module.hrl").
-include("figure.hrl").

%% ---------------------------------
do_init() ->
    MaxRank = ?ARENA_MAX_RANK_TRULY,
    RoleListDB = db_get_real_role(MaxRank),

    F1 = fun([RoleId, Rank]) -> {Rank, RoleId} end,
    RankList = lists:map(F1, RoleListDB),
    RankMaps = maps:from_list(RankList),

    %% 加载赛季信息
    Sql = io_lib:format(?sql_select_db_arena_season_info, []),
    SeasonId = case db:get_all(Sql) of
        [[Id]] -> Id;
        _ -> 1
    end,
    State = #arena_state{
        rank_maps = RankMaps, season = SeasonId
    },
    NewState = set_season_settlement_timer(State),
    NewState.


%% ---------------------------------------------------------------------------
%% @doc 设置赛季结算定时器
-spec set_season_settlement_timer(State) -> NewState when
    State       :: #arena_state{},
    NewState    :: #arena_state{}.
%% ---------------------------------------------------------------------------
get_day_cur() ->
    MergeDay = util:get_merge_day(),
    case MergeDay > 0 of
        true  -> MergeDay;
        false -> util:get_open_day()
    end.

%% 开服或者合服第 N+1 天的 4 点结算
set_season_settlement_timer(State) ->
    #arena_state{season = SeasonId, season_ref = OldRef} = State,
    NowDay = get_day_cur(),
    SeasonCfgList = get_season_config_list(SeasonId),
    Ref = set_settlement_timer(SeasonId, NowDay, SeasonCfgList),
    util:cancel_timer(OldRef),
    State#arena_state{season_ref = Ref}.

set_settlement_timer(_SeasonId, _OpenDay, []) ->
    Now = utime:unixtime(),
    DateTime = utime:unixtime({tomorrow, Now}),
    NextCheckTime = DateTime - Now,
    erlang:send_after((NextCheckTime * 1000), self(), {season_settlement});
set_settlement_timer(SeasonId, OpenDay, [{Id, NeedOpenDay} | T]) ->
    case SeasonId > Id of
        true -> %% 已经结算过了
            set_settlement_timer(SeasonId, OpenDay, T);
        false ->
            SettlementHour = 4,
            Now = utime:unixtime(),
            NextCheckTime = if
                OpenDay > NeedOpenDay ->
                    %% 已经过了结算天数，那就马上结算，可能是跨天的时候服务器停服了
                    (60 * 10);
                OpenDay =:= NeedOpenDay ->
                    %% 正好是计算当天
                    Date = erlang:date(),
                    %% 结算时间是当天4点
                    SettlementTime = utime:unixtime({Date, {SettlementHour, 0, 0}}),
                    case SettlementTime =< Now of
                        true  ->
                            %% 已经过了计算时间点，那就马上结算
                            (60 * 10);
                        false ->
                            %% 时刻未到，定时到4点
                            SettlementTime - Now
                    end;
                true -> %% 还没达到开服天数
                    LogicMidNight = utime:get_logic_midnight(Now, SettlementHour),
                    case Now >= LogicMidNight of
                        true -> %% 明天凌晨4点再检查
                            NextMidNight = utime:get_next_logic_midnight(Now, SettlementHour),
                            NextMidNight - Now;
                        _ -> %% 凌晨4点再检查
                            LogicMidNight - Now
                    end
            end,
            erlang:send_after((NextCheckTime * 1000), self(), {season_settlement})
    end.

%% ---------------------------------------------------------------------------
%% @doc 尝试赛季结算
-spec season_settlement(State) -> NewState when
    State       :: #arena_state{},
    NewState    :: #arena_state{}.
%% ---------------------------------------------------------------------------
season_settlement(State) ->
    #arena_state{season = SeasonId} = State,
    CheckDay = get_day_cur(),
    SeasonCfgList = get_season_config_list(SeasonId),
    case lists:keyfind(SeasonId, 1, SeasonCfgList) of
        {SeasonId, NeedDay} when CheckDay >= NeedDay -> %% 可以结算
            season_settlement_do(State);
        _ ->
            set_season_settlement_timer(State)
    end.

%% 赛季配置
get_season_config_list(CurSea) ->
    [[{InitS,RepD}]|_] = data_arena:get_arena_value(?ARENA_SEASON_CONFIG),
    SeasonCfgList = calc_season(InitS,CurSea,RepD),
    %% 要第二天才发奖励，所以配置里面的开服天数+1
    SeasonCfgList2 = [
        {SeasonId, NeedOpenDay + 1} || {SeasonId, NeedOpenDay} <- SeasonCfgList
    ],
    lists:keysort(1, SeasonCfgList2).

calc_season(InitS,InitS,RepD)->
    [{InitS,RepD}];
calc_season(InitS,CurS,RepD)->
    CurD  = CurS*RepD,
    NextS = CurS+1,
    NextD = NextS*RepD,
    [{InitS,RepD},{CurS,CurD},{NextS,NextD}].


%% ---------------------------------------------------------------------------
%% @doc 竞技场是否开启
-spec is_arena_open() -> true | false.
%% ---------------------------------------------------------------------------
is_arena_open() ->
    true.

%% ---------------------------------------------------------------------------
%% @doc 赛季结算
-spec season_settlement_do(State) -> NewState when
    State       :: #arena_state{},
    NewState    :: #arena_state{}.
%% ---------------------------------------------------------------------------
season_settlement_do(State) ->
    #arena_state{season = SeasonId, rank_maps = RankMaps} = State,
    spawn(?MODULE, season_settlement_done, [SeasonId, RankMaps]),
    NewSeasonId = SeasonId + 1,
    NewState = State#arena_state{season = NewSeasonId},
    Now = utime:unixtime(),
    Sql = io_lib:format(?sql_replace_db_arena_season_info, [NewSeasonId, Now]),
    db:execute(Sql),
    set_season_settlement_timer(NewState).

%% 赛季结算
season_settlement_done(SeasonId, RankMaps) ->
    NSeasonId = get_conf_season_id(SeasonId),
    season_settlement_done(NSeasonId, RankMaps, 1, true).

season_settlement_done(_SeasonId, _RankMaps, _Rank, false) ->
    ok;
season_settlement_done(SeasonId, RankMaps, Rank, _IsContinue) ->
    NewIsContinue = case data_arena:get_season_award(SeasonId, Rank) of
        #arena_season_award{award = Award, rare_award = RareAward} ->
            BadgeAward = data_arena:get_badge_award(Rank),
            AwardList = RareAward ++ Award ++ BadgeAward,
            season_settlement_award(SeasonId, RankMaps, Rank, AwardList),
            true;
        _ -> %% 发到最后一名了
            false
    end,
    timer:sleep(10),
    case Rank rem 10 of
        0 ->
            timer:sleep(100);
        _ ->
            ok
    end,
    season_settlement_done(SeasonId, RankMaps, Rank + 1, NewIsContinue).

%% 发送赛季奖励
season_settlement_award(_SeasonId, RankMaps, Rank, AwardList) ->
    case mod_arena_cast:get_rank_role(RankMaps, Rank) of
        RoleId when RoleId =/= 0 ->
            %% 发送邮件
            Content = utext:get(2800004, [Rank]),
            lib_mail_api:send_sys_mail(
                [RoleId], ?MOD_ARENA, utext:get(2800003), Content, AwardList
            ),
            LogData = [
                RoleId, Rank, utime:unixtime(), util:term_to_string(AwardList)
            ],
            lib_log_api:log_arena_season_award(LogData);
        _ -> %% 是假人
            ok
    end.

rank_log_data(_SeasonId, _Now, _RankMaps, Rank, MaxRank, LogList) when Rank > MaxRank ->
    LogList;
rank_log_data(SeasonId, Now, RankMaps, Rank, NewMaxRank, LogList) ->
    LogList2 = case mod_arena_cast:get_rank_role(RankMaps, Rank) of
                   RoleId when RoleId =/= 0 ->
                        [[SeasonId, RoleId, Rank, Now] | LogList];
                    _ -> %% 是假人
                        LogList
                end,
    rank_log_data(SeasonId, Now, RankMaps, Rank + 1, NewMaxRank, LogList2).

%% 生成假人形象
make_fake_man_figure(Rank) ->
    [Name] = data_arena:get_arena_value(?ARENA_ROBOT_NMAE), %% 获取假人名字
    case data_arena:get_fake_role_cfg(Rank) of
        #arena_fake_role_cfg{combat = Combat, fake_role_lv = Lev, fake_role_carrer=Career} ->
            Turn = 1,
            Sex = data_career:get_carerr_sex(Career),
            LvModel = lib_player:get_model_list(Career, Sex, Turn, Lev),
            #figure{
                name = Name, sex = Sex, turn = 1, career = Career, lv = Lev, lv_model = LvModel,
                power = Combat
            };
        _ ->
            #figure{name = Name, lv = 80, career = 1, sex = 1}
    end.

%% 如果当前赛季没有配置，就用已配置的最大值
get_conf_season_id(SeasonId) ->
    min(SeasonId, data_arena:get_max_season_id()).

%% 读取配置
get_arena_cfg(Key, Default) ->
    case data_arena:get_arena_value(Key) of
        [Value] -> Value;
        _ -> Default
    end.
%% ---------------------------sql-------------------------------------
db_get_real_role(MaxRank) ->
    Sql = io_lib:format(?sql_select_db_real_role, [MaxRank]),
    db:get_all(Sql).



