%% ---------------------------------------------------------------------------
%% @doc 巅峰竞技跨服中心排行榜
%% @author hek
%% @since  2016-11-14
%% @deprecated
%% ---------------------------------------------------------------------------
-module(lib_top_pk_rank_center_mod).
-include("common.hrl").
-include("server_kv.hrl").
-include("top_pk.hrl").
-include("def_fun.hrl").
-include("def_gen_server.hrl").
-export([
    init/0,                     %% 进程初始化
    sync_rank_info/2,           %% 系统启动同步排行榜
    get_rank_info/5,            %% 获取排行榜
    upload_rank_to_center/2,    %% 上传排行数据到跨服中心
    refresh_rank/2,             %% 刷新排行榜
    act_end/1,                  %% 活动结束
    sync_rank/1,                %% 同步一次排行榜给所有节点
    save_rank_center/1,         %% 保存排行榜
    daily_update/1,             %% 凌晨更新
    update_role/3,              %% 更新排行玩家信息
    gm_season_end/1             %% GM结束赛季
]).

%% ---------------------------------------------------------------------------
%% @doc 进程初始化
-spec init() -> {ok, State} when
    State          :: list().
%% ---------------------------------------------------------------------------
init() ->
    {ok, RankList} = init_rank_list(),
    SeasonId = lib_server_kv:get_value(?SERVER_KV_TOP_PK_SEASON_ID, 0),
    mod_top_pk_rank_center:daily_update(),
    {ok, #rank_center_state{rank_list = RankList, season_id = SeasonId}}.

init_rank_list() ->
    List = lib_top_pk_util:db_select_rank_center(),
    RankList = [make_record(rank_role, T) || T <- List],
    RankList2 = lib_top_pk_util:sort_rank_list(RankList),
    LastRankList = case length(RankList2) > ?TOP_PK_KV_RANK_SIZE of
        false -> RankList2;
        true -> truncate_overflow_rank(RankList2)
    end,
    {ok, LastRankList}.

truncate_overflow_rank(RankList) ->
    LastRankList = lists:sublist(RankList, ?TOP_PK_KV_RANK_SIZE),
    F = fun() ->
        lib_top_pk_util:db_truncate_rank_center(),
        lib_top_pk_util:db_save_rank_center(LastRankList),
        ok
    end,
    case db:transaction(F) of
        ok -> ignore;
        Reason -> ?ERR("load_rank_info ~p~n", [Reason])
    end,
    LastRankList.

make_record(rank_role, [RoleId, RoleName, Career, Power, Platform, ServerNum, ServerId, Score, PkTime]) ->
    #rank_role{
        role_id = RoleId, role_name = RoleName, career = Career, power = Power, platform = Platform,
        server_num = ServerNum, server_id = ServerId, score = Score, pk_time = PkTime}.

%% ---------------------------------------------------------------------------
%% @doc 系统启动同步排行榜
-spec sync_rank_info(State, Node) -> ok when
    State          :: #rank_center_state{},
    Node           :: node().
%% ---------------------------------------------------------------------------
sync_rank_info(State, Node) ->
    Packet = lib_top_pk_util:pack_role_rank(State#rank_center_state.rank_list),
    clusters_center:apply_cast(Node, mod_top_pk_local, apply_cast, [{'sync_rank_info', Packet}]),
    ok.

%% ---------------------------------------------------------------------------
%% @doc 获取排行榜
-spec get_rank_info(State, Node, PlayerId, Page, PageSize) -> ok when
    State          :: #rank_center_state{},
    Node           :: node(),
    PlayerId       :: integer(),
    Page           :: integer(),
    PageSize       :: integer().
%% ---------------------------------------------------------------------------
get_rank_info(State, Node, PlayerId, Page, PageSize) ->
    RankList = State#rank_center_state.rank_list,
    Length = erlang:length(RankList),
    PageNums = (Length div PageSize) + 1,
    case Page > PageNums of
        true -> SubRankList = RankList;
        false ->
            Pos = (Page - 1)*PageSize +1,
            SubRankList = lists:sublist(RankList, Pos, PageSize)
    end,
    case lists:keyfind(PlayerId, #rank_role.role_id, RankList) of
        #rank_role{rank_id = MyRankId} -> skip;
        _ -> MyRankId = 0
    end,
    ListData = [{RankId, RoleId, RoleName, Career, Power, Platform, ServerNum, Score} ||
        #rank_role{
            rank_id = RankId, role_id = RoleId, role_name = RoleName, career = Career,
            power = Power, platform = Platform, server_num = ServerNum, score = Score} <- SubRankList],
    {ok, Bin} = pt_281:write(28115, [Page, PageSize, Length, ?ACT_CLS_CENTER, ListData, MyRankId]),
    clusters_api:send_to_uid(Node, PlayerId, Bin),
    ok.

%% 上传排行数据到跨服中心
%% 单服开启跨服的时候将本服排行数据上传到跨服中心
upload_rank_to_center(State, Msg) ->
    RankList = State#rank_center_state.rank_list,
    List = lib_top_pk_util:unpacket_role_rank(Msg),
    NewRankList = lists:reverse(List ++ RankList),
    NewRankList2 = lib_top_pk_util:sort_rank_list(NewRankList),
    LastRankList = lists:sublist(NewRankList2, ?TOP_PK_KV_RANK_SIZE),
    {ok, State#rank_center_state{rank_list = LastRankList} }.

%% ---------------------------------------------------------------------------
%% @doc 刷新排行榜
-spec refresh_rank(State, RankRole) -> {ok, NewState} when
    State          :: #rank_center_state{},
    RankRole       :: #rank_role{},
    NewState       :: #rank_center_state{}.
%% ---------------------------------------------------------------------------
refresh_rank(State, RankRole) ->
    RankList = State#rank_center_state.rank_list,
    NewRankList = lib_top_pk_util:refresh_rank(RankList, RankRole),
    {ok, State#rank_center_state{rank_list = NewRankList} }.

%% ---------------------------------------------------------------------------
%% @doc 活动结束,同步一次排行榜
-spec act_end(State) -> NewState when
    State          :: #rank_center_state{},
    NewState       :: #rank_center_state{}.
%% ---------------------------------------------------------------------------
act_end(State) ->
    Packet = lib_top_pk_util:pack_role_rank(State#rank_center_state.rank_list),
    clusters_center:apply_to_all_node(mod_top_pk_local, apply_cast, [{'sync_rank_info', Packet}], 50),
    erlang:send_after(180*1000, self(), 'save_rank_center'),
    erlang:send_after(120*1000, self(), 'sync_rank'),
    State#rank_center_state{is_db = 1}.

%% 保存排行榜（建议活动结束3分钟后再保存排行榜，错开峰值）
save_rank_center(State) ->
    RankList = State#rank_center_state.rank_list,
    lib_top_pk_util:db_save_rank_center(RankList),
    % ?PRINT("####### save_rank_center:~p~n", [{length(RankList)}]),
    ok.

%% 同步一次排行榜给所有节点
sync_rank(State) ->
    Packet = lib_top_pk_util:pack_role_rank(State#rank_center_state.rank_list),
    clusters_center:apply_to_all_node(mod_top_pk_local, apply_cast, [{'sync_rank_info', Packet}], 50),
    ok.

%% ---------------------------------------------------------------------------
%% @doc 凌晨更新
-spec daily_update(State) -> {ok, NewState} when
    State           :: #rank_center_state{},
    NewState        :: #rank_center_state{}.
%% ---------------------------------------------------------------------------
daily_update(State) ->
    #rank_center_state{season_id = SeasonId} = State,
    CurSeasonId = lib_top_pk_util:get_cur_season_id(),
    if
        SeasonId =/= CurSeasonId -> start_new_season(State, CurSeasonId);
        true -> {ok, State}
    end.

%% 跨服开启新赛季
start_new_season(State, CurSeasonId) ->
    NowTime = utime:unixtime(),
    #rank_center_state{season_id = OldSeasonId} = State,
    SeasonServerKv = #server_kv{key = ?SERVER_KV_TOP_PK_SEASON_ID, value = CurSeasonId, time = NowTime},
    %% 清理上一个赛季排行数据、初始化新赛季信息
    F = fun() ->
        lib_top_pk_util:db_truncate_rank_center(),
        lib_server_kv:update_server_kv_db(SeasonServerKv),
        ok
    end,
    NewState = case db:transaction(F) of
        ok ->
            lib_server_kv:update_server_kv_ets(SeasonServerKv),
            State#rank_center_state{season_id = CurSeasonId, rank_list = []};
        Err -> ?ERR("error:~p~n", [Err]), State
    end,

    %% 发放上一个赛季排名奖励(前10名)
    RankList = lib_top_pk_util:sort_rank_list(State#rank_center_state.rank_list),
    AwardRankList = lists:sublist(RankList, ?TOP_PK_KV_SEASON_RANK_AWARD_NUM),
    send_season_rank_reward(AwardRankList, OldSeasonId),
    ?INFO("center start_new_season:~p~n", [NowTime]),
    {ok, NewState}.

send_season_rank_reward(RankList, OldSeasonId) ->
    spawn(fun() -> do_send(RankList, OldSeasonId, 1) end).

do_send([], OldSeasonId, _Index) ->
    clusters_center:apply_to_all_node(mod_top_pk_local, apply_cast, [{'start_local_new_season', OldSeasonId+1}], 50);
do_send([One | Rest], OldSeasonId, Index) ->
    case Index rem 10 == 0 of
        true  -> timer:sleep(50);
        false -> skip
    end,
    #rank_role{role_id = RoleId, server_id = ServerId, rank_id = RankId, score = Score} = One,
    clusters_center:apply_cast(ServerId, mod_top_pk_local, apply_cast,
                        [{'send_local_rank_reward', RoleId, RankId, Score}]),
    do_send(Rest, OldSeasonId, Index+1).

%% ---------------------------------------------------------------------------
%% @doc 更新排行玩家信息
-spec update_role(State, RoleId, KeyValueList) -> {ok, NewState} when
    State          :: #rank_center_state{},
    RoleId         :: integer(),
    KeyValueList   :: [{Key::atom(), Value::term()}],
    NewState       :: #rank_center_state{}.
%% ---------------------------------------------------------------------------
update_role(State, RoleId, KeyValueList) ->
    #rank_center_state{rank_list = RankList} = State,
    {Flag, NewRole, NewRankList} = lib_top_pk_util:update_rank_role(RoleId, KeyValueList, RankList),
    case Flag of
        true ->
            lib_top_pk_util:db_save_rank_center([NewRole]),
            Packet = lib_top_pk_util:pack_role_rank(NewRankList),
            clusters_center:apply_to_all_node(mod_top_pk_local, apply_cast, [{'sync_rank_info', Packet}], 50);
        _ -> skip
    end,
    {ok, State#rank_center_state{rank_list = NewRankList}}.

%% GM结束赛季
gm_season_end(State) ->
    CurSeasonId = lib_top_pk_util:get_cur_season_id(),
    {ok, NewState} = start_new_season(State, CurSeasonId),
    {ok, NewState}.
