%%% ----------------------------------------------------
%%% @Module:        lib_3v3_local
%%% @Author:        zhl
%%% @Description:   跨服3v3
%%% @Created:       2017/07/05
%%% ----------------------------------------------------

-module(lib_3v3_local).
-export([
        load_act_time/0,

        login/1,                              %% 玩家上线
        daily_check/1,                        %% 日常更新
        calc_tier_by_star/2,                  %% 根据星数计算段位
        reconnect/2,                          %% 重连
        logout/1,                             %% 玩家下线
        handle_player_disconnect/2,           %% 玩家关闭客户端当下线
        leave_pk_room/1,                      %% 跨服3v3 - 离开战场
        % enter_pk_room/1,                      %% 跨服3v3 - 重登进入战场
        % player_die/3,                         %% 玩家死亡

        change_status/2,                      %% 修改玩家状态
        cast_change_status/2,
        clear_role_status/1,

        replace_role_3v3/2,                   %% 更新数据库

        send_team_data/2,                     %% 推送队伍信息
        send_team_list/2,                     %% 推送队伍列表
        send_power_contrast/1,                %% 推送双方的战力对比
        send_battle_info/1,                   %% 推送战场信息
        send_page_rank/1,                     %% 获取荣誉排行榜
        cast_send_page_rank/2,
        send_pk_result/1,                     %% 推送战斗结算
        cast_send_pk_result/2,
        send_rank_rewards/1,                  %% 发送周榜奖励
        send_msg_to_team/1,                   %% 接受队伍消息

        pack_team_info/1,                     %% 打包队伍信息
        pack_team_info/2,
        pack_team_list/3,                     %% 打包队伍列表
        pack_team_data/1,                     %% 打包队伍信息

        is_in_team/1,                         %% 是否在队伍中

        kick_out_room/2,                      %% 将房间内所有玩家踢出场景
        cast_kick_out_room/2,                 %% 将房间内所有玩家踢出场景 - cast

        get_unite_role_data/1,                %% 获取玩家参与数据
        get_unite_team_data/1,                %% 找到玩家的队伍数据
        to_role_data/2                        %% 转换#role_data{}
        ,fix_bug/0

        % open_call_member/1,                   %% 公开招募队友
%%        zero_time/1
    ]).

%% 修复逻辑
-export([
    get_tier_respond/3
    ,setup_player_tier/3
    ,repair_tier/1
]).

-include("server.hrl").
%%-include("train.hrl").
-include("battle.hrl").
-include("predefine.hrl").
-include("guild.hrl").
-include("3v3.hrl").
-include("figure.hrl").
-include("scene.hrl").
-include("errcode.hrl").
-include("common.hrl").
-include("goods.hrl").
-include("def_goods.hrl").
-include("def_event.hrl").
-include("def_module.hrl").
-include("def_fun.hrl").

%% 读取活动时间
load_act_time() ->
    ActList = data_3v3:get_act_list(),
    DayOfWeek = utime:day_of_week(),
    NowSec = utime:get_seconds_from_midnight(),
    F = fun(ActID, List) ->
        case data_3v3:get_act_info(ActID) of
            #act_info{week = WeekList, time = [StarTime, EndTime]} ->
                IsToday = lists:member(DayOfWeek, WeekList),
                StTime = calendar:time_to_seconds(StarTime),
                EdTime = calendar:time_to_seconds(EndTime),
                IsNotEnd = EdTime > NowSec,
                if
                    IsToday andalso IsNotEnd ->
                        [{StTime, EdTime} | List];
                    true ->
                        List
                end;
            _ ->
                List
        end
    end,
    case sort_time(lists:foldl(F, [], ActList)) of
        [] -> [];
        [ActTime | _] -> ActTime
    end.

sort_time(TimeList) ->
    F = fun({StTime1, _}, {StTime2, _}) ->
        StTime1 < StTime2
    end,
    lists:sort(F, TimeList).

daily_check(Player) ->
    #role_3v3{
        old_tier = OldTier, old_star = OldStar, tier = Tier, star = Star,
        continued_win = ContinuedWin, daily_win = DailyWin, daily_pk = DailyPK,
        daily_honor = DailyHonor, pack_time = PackTime, pack_reward = PackReward,
        daily_time = DailyTime, season_pk = SeasonPk
    } = Player#player_status.role_3v3,
    Role3v3 = calc_inherit_tier(Player#player_status.id,[OldTier, OldStar, Tier, Star, ContinuedWin, DailyWin,
        DailyPK, DailyHonor, PackReward, PackTime, SeasonPk], DailyTime),
    NewPlayer = Player#player_status{role_3v3 = Role3v3},
    pp_3v3:handle(65000, NewPlayer, []),
    NewPlayer.

%% 玩家上线
login([RoleID]) ->
    case db:get_row(io_lib:format(?SQL_SELECT_3V3_ROLE, [RoleID])) of
        [
            OldTier, OldStar, Tier, Star, ContinuedWin, DailyWin,
            DailyPK, DailyHonor, PackRewardBin, PackTime, DailyTime, SeasonPk
        ] ->
            calc_inherit_tier(RoleID, [OldTier, OldStar, Tier, Star, ContinuedWin, DailyWin,
                DailyPK, DailyHonor, util:bitstring_to_term(PackRewardBin), PackTime, SeasonPk], DailyTime);
        [] ->
            InitRole3v3 = #role_3v3{pack_reward = [{I, 0} || I <- data_3v3:get_act_rewards_list()], daily_time = utime:unixtime()},
            case data_3v3:get_tier_info(InitRole3v3#role_3v3.old_tier) of
                #tier_info{daily_reward = NewDailyHonor} -> ok;
                _ -> NewDailyHonor = 0
            end,
            InitRole3v3#role_3v3{daily_honor = NewDailyHonor}
    end.

calc_inherit_tier(RoleID, [OldTier, OldStar, Tier, Star, ContinuedWin, DailyWin,
    DailyPK, DailyHonor, PackReward0, PackTime, SeasonPk], DailyTime) ->
    NowTime = utime:unixtime(),
    IsToday = utime:is_today(DailyTime),
    IsSameMonth = utime:is_same_month(DailyTime, NowTime),
    Role3v3 = if
        IsToday ->
            RwIds = data_3v3:get_act_rewards_list(),
            PackReward = lists:foldr(fun(I, Acc) ->
                case lists:keyfind(I, 1, PackReward0) of
                    {I, C} ->
                        [{I, C}|Acc];
                    _ ->
                        [{I, 0}|Acc]
                end
            end, [], RwIds),
            #role_3v3{
                old_tier = OldTier, old_star = OldStar, tier = Tier, star = Star,
                continued_win = ContinuedWin, daily_win = DailyWin, daily_pk = DailyPK,
                daily_honor = DailyHonor, pack_time = PackTime, pack_reward = PackReward
                , daily_time = DailyTime, season_pk = SeasonPk
            };
        IsSameMonth == false -> %% 不是同一周的话，昨日跟今日段位是继承后的段位
            case data_3v3:get_inherit_tier(Tier) of
                false -> %% 没有配置
                    NTier = ?DEFAULT_TIER, NStar = ?DEFAULT_STAR;
                NTier ->
                    TierInfo = data_3v3:get_tier_info(NTier),
                    NStar = ?IF(is_record(TierInfo, tier_info), TierInfo#tier_info.star, 0)
            end,
            lib_log_api:log_3v3(RoleID, 2, Tier, Star, NTier, NStar, 0, 0), %% 3v3段位继承日志
            #role_3v3{old_tier = NTier, old_star = NStar, tier = NTier, star = NStar,
                pack_reward = [{I, 0} || I <- data_3v3:get_act_rewards_list()]
                , daily_time = NowTime};
        true ->
            #role_3v3{old_tier = Tier, old_star = Star, tier = Tier, star = Star,
                pack_reward = [{I, 0} || I <- data_3v3:get_act_rewards_list()]
                , daily_time = NowTime, season_pk = SeasonPk}
    end,
    #role_3v3{tier = NTier2, star = NStar2} = Role3v3,
    {NTier3, NStar3} = calc_tier_by_star(max(NTier2, ?DEFAULT_TIER), max(NStar2, ?DEFAULT_STAR)),
    NewRole3v3 = Role3v3#role_3v3{tier = NTier3, star = NStar3},
    case not IsToday orelse NTier3 =/= Tier orelse NStar3 =/= Star of
        true ->
            replace_role_3v3(RoleID, NewRole3v3);
        _ ->
            ok
    end,
    %% 重置每日段位奖励
    case data_3v3:get_tier_info(NewRole3v3#role_3v3.old_tier) of
        #tier_info{daily_reward = NewDailyHonor} -> ok;
        _ -> NewDailyHonor = 0
    end,
    IsTodayPack = utime:is_today(NewRole3v3#role_3v3.pack_time),
    LastRole3v3 = if
        IsTodayPack -> NewRole3v3;
        true -> NewRole3v3#role_3v3{daily_honor = NewDailyHonor}
    end,
    LastRole3v3.

%% 根据星数计算段位
%% @return {Tier, Star}
calc_tier_by_star(Tier, Star) ->
    KeyList = data_3v3:get_tier_and_star_info(),
    do_calc_tier_by_star(KeyList, {Tier, Star}).

do_calc_tier_by_star([], {Tier, Star}) -> {Tier, Star};
do_calc_tier_by_star([{TmpTier, TmpStar}|T], {Tier, Star}) ->
    case Star >= TmpStar of
        true -> do_calc_tier_by_star(T, {TmpTier, Star});
        false -> {Tier, Star}
    end.

%% 重连
reconnect(Player, LogType) when LogType == ?NORMAL_LOGIN orelse LogType == ?RE_LOGIN ->
    #player_status{
        id = RoleID, server_name = ServerName, server_num = ServerNum, server_id = ServerId,
        sid = RoleSid, figure = #figure{lv = RoleLv}, scene = SceneID
        } = Player,
    Is3v3Scene = lib_3v3_api:is_3v3_scene(SceneID),
    if
        RoleLv < ?KF_3V3_LV_LIMIT -> {next, Player};
        true ->
            clusters_node:apply_cast(mod_3v3_center, enter_pk_room, [[ServerName, ServerNum, ServerId, RoleID, RoleSid, Is3v3Scene]]),
            {next, Player}
    end;
reconnect(Player, _LogType) ->
    {next, Player}.

%% 玩家下线
logout(#player_status{
        server_name = ServerName, server_num = ServerNum, server_id = ServerId, id = RoleID, sid = RoleSid,
        figure = #figure{lv = RoleLv}, scene = SceneID, role_3v3 = Role3v3
    }) ->
    Is3v3Scene = lib_3v3_api:is_3v3_scene(SceneID),
    if
        RoleLv < ?KF_3V3_LV_LIMIT -> skip;
        true -> mod_3v3_local:logout([ServerName, ServerNum, ServerId, RoleID, RoleSid, ?PK_3V3_OFFLINE, Is3v3Scene])
        % Is3v3Scene -> leave_pk_room([Platform, ServerNum, RoleID, ?PK_3V3_OFFLINE, ServerId, Is3v3Scene]);
        % true ->
        %     %% 将本服跟跨服的玩家数据删除
        %     mod_3v3_local:leave_team([Platform, ServerNum, ServerId, RoleID, RoleSid])
    end,
    % replace_role_3v3(RoleID, Role3v3#role_3v3{daily_time = utime:unixtime()}).
    replace_role_3v3(RoleID, Role3v3).

replace_role_3v3(RoleID, Role3v3) ->
    %% 保存跨服3v3 数据
    case Role3v3 of
        #role_3v3{
            old_tier = OldTier, old_star = OldStar, tier = Tier, star = Star,
            continued_win = ContinuedWin, daily_win = DailyWin, daily_pk = DailyPK,
            daily_honor = DailyHonor, pack_time = PackTime, pack_reward = PackReward,
            daily_time = DailyTime, season_pk = SeasonPk
        } ->
            PackRewardBin = util:term_to_bitstring(PackReward),
            SQL = io_lib:format(?SQL_REPLACE_3V3_ROLE, [RoleID, OldTier, OldStar,
                Tier, Star, ContinuedWin, DailyWin, DailyPK, DailyHonor, PackRewardBin,
                PackTime, DailyTime, SeasonPk]),
            db:execute(SQL);
        _ -> skip
    end.

%% 跨服3v3 - 离开战场
leave_pk_room([ServerName, ServerNum, RoleID, Type, ServerId, Is3v3Scene]) ->
    clusters_node:apply_cast(mod_3v3_center, leave_pk_room, [[ServerName, ServerNum, RoleID, Type, ServerId, Is3v3Scene]]).

% %% 跨服3v3 - 重登进入战场
% enter_pk_room(#player_status{
%         platform = Platform, server_num = ServerNum, id = RoleID, sid = RoleSid,
%         figure = #figure{lv = RoleLv}
%     }) ->
%     if
%         RoleLv < ?KF_3V3_LV_LIMIT ->
%             skip;
%         true ->
%             clusters_node:apply_cast(mod_3v3_center, enter_pk_room, [[Platform, ServerNum, RoleID, RoleSid]])
%     end,
%     ok.

%%zero_time(#player_status{id = RoleID, role_3v3 = Role3v3} = Status) ->
%%    #role_3v3{tier = Tier, star = Star} = Role3v3,
%%    DayOfWeek = utime:day_of_week(utime:unixtime() + 10),
%%    if
%%        DayOfWeek == 7 -> %% 是周一的话，今日段位是继承后的段位
%%            case data_3v3:get_inherit_tier(Tier) of
%%                false -> %% 没有配置
%%                    NTier = Tier, NStar = Star;
%%                NTier ->
%%                    #tier_info{star = NStar} = data_3v3:get_tier_info(NTier)
%%            end,
%%            lib_log_api:log_3v3(RoleID, 2, Tier, Star, NTier, NStar, 0, 0), %% 3v3段位继承日志
%%            NRole3v3 = #role_3v3{old_tier = Tier, old_star = Star, tier = NTier, star = NStar};
%%        true ->
%%            NRole3v3 = #role_3v3{old_tier = Tier, old_star = Star, tier = Tier, star = Star}
%%    end,
%%    case NRole3v3 of
%%        Role3v3 -> skip;
%%        _ ->
%%            replace_role_3v3(RoleID, NRole3v3)
%%    end,
%%    NStatus = Status#player_status{role_3v3 = NRole3v3},
%%    pp_3v3:handle(65000, NStatus, []),
%%    NStatus.

%% 获取玩家参与数据
%% @return : {ok, UniteRoleData} | {false, ResID, TeamID}
%% @desc : 注意，这个方法只能在mod_3v3_local进程中使用
get_unite_role_data([_Platform, _ServerNum, RoleID]) ->
    % case ets:match_object(?ETS_ROLE_DATA, #kf_3v3_role_data{
    %         platform = Platform, server_num = ServerNum, role_id = RoleID, _ = '_'})
    % of
    %     [#kf_3v3_role_data{} = UniteRoleData] -> %% 参与过跨服3v3
    %         Ret = {ok, UniteRoleData};
    %     _ -> %% 不曾参与过跨服3v3
    %         Ret = {false, ?ERRCODE(err650_kf_3v3_not_joined)}
    % end,
    % Ret;
    get_unite_role_data(RoleID);
get_unite_role_data(RoleID) ->
    case ets:lookup(?ETS_ROLE_DATA, RoleID) of
        [#kf_3v3_role_data{} = UniteRoleData] -> %% 参与过跨服3v3
            Ret = {ok, UniteRoleData};
        _ -> %% 不曾参与过跨服3v3
            Ret = {false, ?ERRCODE(err650_kf_3v3_not_joined)}
    end,
    Ret.

%% 找到玩家的队伍数据
%% @desc : 注意这方法只能在mod_3v3_center进程中使用
get_unite_team_data(TeamID) when is_integer(TeamID) andalso TeamID > 0 ->
    case ets:lookup(?ETS_TEAM_DATA, TeamID) of
        [#kf_3v3_team_data{} = TeamData] ->
            {ok, TeamData};
        _ ->
            {false, ?ERRCODE(err650_kf_3v3_not_joined)}
    end;
get_unite_team_data(_) ->
    {false, ?ERRCODE(err650_kf_3v3_not_joined)}.

%% 转换#role_data{}
to_role_data(Status, [PowerLimit, LvLimit, Password, IsAuto]) ->
    #player_status{
        server_name = ServerName, server_num = ServerNum, server_id = ServerId, id = RoleID, sid = RoleSid,
        figure = Figure, hightest_combat_power = Power, combat_power = PowerView, role_3v3 = Role3v3,
        scene = SceneId, scene_pool_id = ScenePoolId, copy_id = CopyId, x = X, y = Y
    } = Status,
    % FashionID = lib_role_fashion:get_fash(Status),
    % TWeapon = lib_role_train:get_sub_train_grade(?TWEAPON, RoleTrains),
    % TFly = lib_role_train:get_sub_train_grade(?TFLY, RoleTrains),
    case Role3v3 of
        #role_3v3{tier = Tier, star = Star, continued_win = ContinuedWin, season_pk = SeasonPk} -> ok;
        _ -> Tier = 0, Star = 0, ContinuedWin = 0, SeasonPk = 0
    end,
    Node = clusters_node:get_node(),
    #role_data{
        node = Node, server_name = ServerName, server_num = ServerNum, server_id = ServerId,
        role_id = RoleID, sid = RoleSid, figure = Figure, power = Power, power_view = PowerView,
        % nickname = Nickname, sex = Sex, lv = RoleLv, vip = VipLv,
        % fashion_id = FashionID, train_weapon = TWeapon, train_fly = TFly,
        power_limit = PowerLimit, lv_limit = LvLimit, password = Password,
        is_auto = IsAuto, tier = Tier, star = Star, continued_win = ContinuedWin,
        old_scene_info = {SceneId, ScenePoolId, CopyId, X, Y}, season_pk = SeasonPk
    }.

%% 打包队伍信息
pack_team_info([]) ->
    [?SUCCESS, 0, 0, 0, 0, 0, 0, 0, []];
pack_team_info(TeamData) ->
    #kf_3v3_team_data{
        team_id = TeamID, captain_id = CaptainID, is_auto = IsAuto,
        power_limit = PowerLimit, lv_limit = LvLimit, password = Password,
        member_data = MemberData, average_power = AveragePower
    } = TeamData,
    Data = pack_member_data(MemberData, CaptainID, []),
    [?SUCCESS, TeamID, PowerLimit, LvLimit, Password, IsAuto, CaptainID, AveragePower, Data].

pack_team_info(Type, []) ->
    [Type, 0, 0, 0, 0, 0, 0, 0, []].

%% 打包队友信息
pack_member_data([], _, MemberData) ->
    MemberData;
pack_member_data([Member | Rest], CaptainID, MemberData) ->
    #kf_3v3_role_data{
        server_name = ServerName, server_num = ServerNum, server_id = ServerId, role_id = RoleID,
        figure = #figure{name = Nickname, career = Career, sex = Sex, turn = Turn}, power_view = PowerView,
        % nickname = Nickname, sex = Sex,
        % fashion_id = FashionID, train_weapon = TWeapon, train_fly = TFly,
        is_ready = IsReady
    } = Member,
    if
        CaptainID == RoleID ->
            IsCaptain = 1;
        true ->
            IsCaptain = 0
    end,
    FashionID = 0, TWeapon = 0, TFly = 0,
    Data = {
        ServerName, ServerNum, ServerId, RoleID, Nickname, Career, Sex, Turn, PowerView, FashionID,
        TWeapon, TFly, IsCaptain, IsReady
    },
    pack_member_data(Rest, CaptainID, [Data | MemberData]).

%% 打包队伍列表
pack_team_list(ResID, [], _) ->
    [ResID, []];
pack_team_list(ResID, TeamList, _ServerId) ->
    F = fun(#kf_3v3_team_data{
            team_id = TeamID, server_name = ServerName, server_num = ServerNum,
            server_id = _TServerId, captain_id = CaptainID, captain_name = Nickname,
            member_num = MemberNum, power_limit = PowerLimit, lv_limit = LvLimit,
            password = Password, is_auto = IsAuto, member_data = MemberData,
            is_pk = IsPk, average_power = AveragePower
        }, List) ->
        ErrUpdateTeamList = ?ERRCODE(err650_kf_3v3_update_teamlist),
        ErrUpdateTeam = ?ERRCODE(err650_kf_3v3_update_team),
        ErrDeleteTeam = ?ERRCODE(err650_kf_3v3_delete_team),
        if
            %% 战斗中的不处理
            IsPk == 1 -> List;
            %% 筛选本服创建的队伍
            (
                (ResID == ErrUpdateTeamList orelse ResID == ErrUpdateTeam)
%%                    andalso TServerId == ServerId
                ) orelse ResID == ErrDeleteTeam ->
                if
                    Password > 0 -> IsPassword = 1;
                    true -> IsPassword = 0
                end,
                case lists:keytake(CaptainID, #kf_3v3_role_data.role_id, MemberData) of
                    false -> CareerList = [];
                    {value, #kf_3v3_role_data{figure = #figure{career = Career}}, RestMemberData} ->
                        RestCareerList = [TmpCareer||#kf_3v3_role_data{figure = #figure{career = TmpCareer}}<-RestMemberData],
                        CareerList = [Career|RestCareerList]
                end,
                case lists:keyfind(CaptainID, #kf_3v3_role_data.role_id, MemberData) of
                    #kf_3v3_role_data{power_view = PowerView, figure = #figure{lv = RoleLv}} ->
                        [{TeamID, ServerName, ServerNum, CaptainID, Nickname, RoleLv, PowerView, AveragePower,
                            MemberNum, PowerLimit, LvLimit, IsPassword, IsAuto, CareerList} | List];
                    _ ->
                        List
                end;
            true -> List
        end
    end,
    [ResID, lists:foldl(F, [], TeamList)].

%% 打包队伍信息
pack_team_data(#kf_3v3_team_data{
        team_id = TeamID, server_name = ServerName,
        server_num = ServerNum, captain_id = CaptainID, captain_name = Nickname,
        member_num = MemberNum, power_limit = PowerLimit, lv_limit = LvLimit,
        password = Password, is_auto = IsAuto, member_data = MemberData
    }) ->
    if
        Password > 0 -> IsPassword = 1;
        true -> IsPassword = 0
    end,
    case lists:keyfind(CaptainID, #kf_3v3_role_data.role_id, MemberData) of
        #kf_3v3_role_data{power_view = PowerView, figure = #figure{lv = RoleLv}} ->
            [?SUCCESS, TeamID, ServerName, ServerNum, CaptainID, Nickname,
                RoleLv, PowerView, MemberNum, PowerLimit, LvLimit, IsPassword, IsAuto];
        _ ->
            [?SUCCESS, 0, "", 0, 0, "", 0, 0, 0, 0, 0, 0, 0]
    end;
pack_team_data(_) ->
    [?SUCCESS, 0, "", 0, 0, "", 0, 0, 0, 0, 0, 0, 0].

%% 是否在队伍中
%% @desc : 注意，这个方法只允许mod_3v3_local进程使用
is_in_team(RoleID) ->
    case ets:lookup(?ETS_ROLE_DATA, RoleID) of
        [#kf_3v3_role_data{team_id = TeamID}] when TeamID > 0 ->
            Ret = {false, ?ERRCODE(err650_kf_3v3_in_team)};
        [#kf_3v3_role_data{} = UniteRoleData] ->
            Ret = {ok, UniteRoleData};
        _ -> %% 不曾参与过跨服3v3
            Ret = {ok, #kf_3v3_role_data{}}
    end,
    Ret.

%% 将房间内所有玩家踢出场景
kick_out_room(RoleID, OldSceneInfo) ->
    % Pid = misc:get_player_process(RoleID),
    % case misc:is_process_alive(Pid) of
    %     true ->
    %         MFA = {lib_3v3_local, cast_kick_out_room, []},
    %         gen_server:cast(Pid, {apply_cast_save, MFA});
    %     _ -> skip
    % end.
    lib_player:apply_cast(RoleID, ?APPLY_CAST_STATUS, lib_3v3_local, cast_kick_out_room, [OldSceneInfo]),
    ok.

%% 将房间内所有玩家踢出场景
cast_kick_out_room(#player_status{scene = SceneID} = Status, OldSceneInfo) ->
    case lib_3v3_api:is_3v3_scene(SceneID) of
        true ->
            KeyValueList = [{group, 0}, {change_scene_hp_lim, 0}],
            case OldSceneInfo of
                {OldScene, OldScenePooldId, OldCopyId, OldX, OldY} ->
                    NStatus = lib_scene:change_scene(Status, OldScene, OldScenePooldId, OldCopyId, OldX, OldY, KeyValueList);
                _ ->
                    NewSceneId = ?MAIN_CITY_SCENE,
                    {X, Y} = lib_scene:get_main_city_x_y(),
                    NStatus = lib_scene:change_scene(Status, NewSceneId, 0, 0, X, Y, KeyValueList)
            end,
            {ok, NStatus};
        false ->
            {ok, Status}
    end.

change_status(MemberData, RoleStatus) ->
    F = fun(#kf_3v3_role_data{node = Node, role_id = RoleID}) ->
        Pid = misc:get_player_process(RoleID),
        case is_pid(Pid) andalso Node == node() of
            true ->
                % MFA = {?MODULE, cast_change_status, [RoleStatus]},
                % gen_server:cast(Pid, {apply_cast_save, MFA});
                lib_player:apply_cast(Pid, ?APPLY_CAST_STATUS, ?MODULE, cast_change_status, [RoleStatus]);
            _ -> skip
        end
    end,
    lists:foreach(F, MemberData).

cast_change_status(Status, RoleStatus) ->
    if
        RoleStatus == free ->
            lib_player_event:remove_listener(?EVENT_DISCONNECT, ?MODULE, handle_player_disconnect),
            KeyValueList = [{action_free, ?ERRCODE(err650_in_kf_3v3_act)}, {group, 0}];
        true ->
            lib_player_event:add_listener(?EVENT_DISCONNECT, ?MODULE, handle_player_disconnect),
            KeyValueList = [{action_lock, RoleStatus}]
    end,
    mod_server_cast:set_data_sub(KeyValueList, Status).

%% 清理所有玩家状态(开始结束通知)
clear_role_status(MemberData) ->
    F = fun(#kf_3v3_role_data{node = Node, role_id = RoleID}) ->
        Pid = misc:get_player_process(RoleID),
        case is_pid(Pid) andalso Node == node() of
            true ->
                {ok, BinData} = pt_650:write(65017, [?SUCCESS]),
                lib_server_send:send_to_uid(RoleID, BinData);
            _ ->
                skip
        end
    end,
    lists:foreach(F, MemberData).

%% 推送队伍信息
send_team_data([], _) ->
    ok;
send_team_data([#kf_3v3_role_data{node = Node} | Rest], Data) when node() /= Node ->
    send_team_data(Rest, Data);
send_team_data([#kf_3v3_role_data{role_id = RoleId} | Rest], Data) ->
    {ok, Bin} = pt_650:write(65010, Data),
    lib_server_send:send_to_uid(RoleId, Bin),
    send_team_data(Rest, Data).

%% 推送队伍列表
send_team_list([], _) ->
    ok;
send_team_list([#attention_list{sid = RoleSid} | Rest], Data) ->
    {ok, Bin} = pt_650:write(65011, Data),
    lib_server_send:send_to_sid(RoleSid, Bin),
    send_team_list(Rest, Data).

%% 发送双方的战力对比
send_power_contrast([RoleID, Data]) ->
    {ok, Bin} = pt_650:write(65029, [Data]),
    lib_server_send:send_to_uid(RoleID, Bin).

%% 发送战场信息
send_battle_info([RoleSid, Data]) ->
    {ok, Bin} = pt_650:write(65030, Data),
    lib_server_send:send_to_sid(RoleSid, Bin).

%% 获取荣誉排行榜
send_page_rank([RoleID, Page, RankID, RankList]) ->
    % Pid = misc:get_player_process(RoleID),
    % case is_pid(Pid) andalso misc:is_process_alive(Pid) of
    %     true ->
    %         MFA = {lib_3v3_local, cast_send_page_rank, [[Page, RankID, RankList]]},
    %         gen_server:cast(Pid, {apply_cast_save, MFA});
    %     _ -> skip
    % end.
    lib_player:apply_cast(RoleID, ?APPLY_CAST_STATUS, lib_3v3_local, cast_send_page_rank,
        [[Page, RankID, RankList]]),
    ok.

cast_send_page_rank(#player_status{sid = RoleSid, role_3v3 = Role3v3} = Status,
    [Page, RankID, RankList]) ->
    #role_3v3{old_tier = OldTier, old_star = OldStar, daily_honor = DailyHonor} = Role3v3,
    % case data_3v3:get_tier_info(OldTier) of
    %     #tier_info{daily_reward = DailyHonor} -> ok;
    %     _ -> DailyHonor = 0
    % end,
    % IsToday = utime:is_today(PackTime),
    % if
    %     IsToday -> NRole3v3 = Role3v3;
    %     true ->
    %         NRole3v3 = Role3v3#role_3v3{daily_honor = DailyHonor}
    % end,
    NRole3v3 = Role3v3,
    FormatRankList = [{
        ServerName,
        ServerNum,
        ServerId,
        RoleId,
        RoleName,
        Career,
        Sex,
        GradeNum,
        StartNum,
        Power} || #kf_3v3_rank_data{
            server_name = ServerName,
            server_num = ServerNum,
            server_id = ServerId,
            role_id = RoleId,
            nickname = RoleName,
            career = Career,
            sex = Sex,
            tier = GradeNum,
            star = StartNum,
            power = Power
        } <- RankList],
    {ok, Bin} = pt_650:write(65039, [Page, FormatRankList, OldTier, OldStar, RankID, DailyHonor]),
    lib_server_send:send_to_sid(RoleSid, Bin),
    Status#player_status{role_3v3 = NRole3v3}.

%% 推送战斗结算 && 发送单次战斗结算
%% @desc : 在线直接到背包，不在线则发邮件
send_pk_result([RoleID, Tier, Star, Honor, ContinuedWin, Data]) ->
    Pid = misc:get_player_process(RoleID),
    case is_pid(Pid) andalso misc:is_process_alive(Pid) of
        true ->
            % MFA = {lib_3v3_local, cast_send_pk_result, [[Tier, Star, Honor, ContinuedWin, Data]]},
            % gen_server:cast(Pid, {apply_cast_save, MFA});
            lib_player:apply_cast(RoleID, ?APPLY_CAST_STATUS, lib_3v3_local, cast_send_pk_result,
                [[Tier, Star, Honor, ContinuedWin, Data]]);
        _ ->
            if
                ContinuedWin > 0 -> Title = utext:get(6500003), Content = utext:get(6500004);
                true -> Title = utext:get(6500005), Content = utext:get(6500006)
            end,
            lib_mail_api:send_sys_mail([RoleID], ?MOD_KF_3V3, Title, Content, [{?TYPE_CURRENCY, ?GOODS_ID_3V3_HONOR, Honor}]),
            SQL = io_lib:format("update role_3v3 set tier = ~w, star = ~w where
                role_id = ~w", [Tier, Star, RoleID]),
            db:execute(SQL)
    end.

cast_send_pk_result(#player_status{id = RoleID, sid = RoleSid, role_3v3 = Role3v3} = Status,
    [Tier, Star, Honor, ContinuedWin, Data]) ->
    #role_3v3{tier = OldTier, star = OldStar, daily_win = DailyWin, daily_pk = DailyPK, season_pk = SeasonPk} = Role3v3,
    if
        ContinuedWin > 0 ->
            Result = 1, Type = 1,
            NRole3v3 = Role3v3#role_3v3{tier = Tier, star = Star, continued_win = ContinuedWin,
                daily_win = DailyWin + 1, daily_pk = DailyPK + 1, season_pk = SeasonPk + 1};
        true ->
            Result = 2, Type = 1,
            NRole3v3 = Role3v3#role_3v3{tier = Tier, star = Star, continued_win = 0,
                daily_pk = DailyPK + 1, season_pk = SeasonPk + 1}
    end,
    replace_role_3v3(RoleID, NRole3v3),
    {ok, Bin} = pt_650:write(65037, Data ++ [Star, ContinuedWin, Honor]),
    lib_server_send:send_to_sid(RoleSid, Bin),
    lib_log_api:log_3v3(RoleID, Type, OldTier, OldStar, Tier, Star, Result, Honor), %% 战斗日志
    mod_hi_point:success_end(RoleID, ?MOD_KF_3V3, 0),
    % NStatus = lib_goods_api:send_reward([{honor, Honor}], kf_3v3, Status#player_status{role_3v3 = NRole3v3}),
    Produce = #produce{type = kf_3v3, reward = [{?TYPE_CURRENCY, ?GOODS_ID_3V3_HONOR, Honor}]},
    {ok, NStatus} = lib_goods_api:send_reward_with_mail(Status#player_status{role_3v3 = NRole3v3}, Produce, ?MOD_KF_3V3),
    KeyValueList = [{group, 0}, {change_scene_hp_lim, 1}],
    mod_server_cast:set_data_sub(KeyValueList, NStatus). %% 战斗结束，将玩家状态直接复原

%% 发送周榜奖励
send_rank_rewards([RoleID, RankID]) ->
    case data_3v3:get_rank_rewards(RankID) of
        0 -> skip;
        Rewards -> lib_mail_api:send_sys_mail([RoleID], ?MOD_KF_3V3, utext:get(6500001), utext:get(6500002, [RankID]), Rewards)
    end.

%% 接受队伍消息
send_msg_to_team([RoleID, Bin]) ->
    lib_server_send:send_to_uid(RoleID, Bin).

handle_player_disconnect(Player, _) ->
    % logout(Player),
    {ok, Player}.

get_tier_respond(RoleId, Tier, Star) ->
    Pid = misc:get_player_process(RoleId),
    case is_pid(Pid) andalso misc:is_process_alive(Pid) of
        true ->
            lib_player:apply_cast(RoleId, ?APPLY_CAST_STATUS, ?MODULE, setup_player_tier, [Tier, Star]);
        _ ->
            case db:get_row(io_lib:format("SELECT `tier`, `star` FROM `role_3v3` WHERE `role_id`=~p", [RoleId])) of
                [Tier, Star] ->
                    ok;
                _ ->
                    SQL = io_lib:format("update role_3v3 set tier = ~w, star = ~w, old_tier = ~w, old_star = ~w where role_id = ~w", [Tier, Star, Tier, Star, RoleId]),
                    db:execute(SQL)
            end
    end.

setup_player_tier(Player, Tier, Star) ->
    #player_status{role_3v3 = Role3v3, id = RoleId} = Player,
    case Role3v3 of
        #role_3v3{tier = Tier, star = Star} ->
            ok;
        _ ->
            NRole3v3 = Role3v3#role_3v3{tier = Tier, star = Star, old_star = Star, old_tier = Tier},
            replace_role_3v3(RoleId, NRole3v3),
            Player#player_status{role_3v3 = NRole3v3}
    end.

repair_tier(Player) ->
    case utime:unixtime() - 1528808400 of
        S when S < 0 ->
            Node = clusters_node:get_node(),
            clusters_node:apply_cast(mod_3v3_rank, get_my_tier, [Node, Player#player_status.id]);
        _ ->
            ok
    end.

fix_bug() ->
    StartTime = utime:unixtime({{2018,7,1},{0,0,0}}),
    SQL = io_lib:format("SELECT `role_id`, `new_tier`, `new_star`, `time` FROM `log_3v3` WHERE `type`=2 AND `time` >= ~p", [StartTime]),
    All = db:get_all(SQL),
    List = lists:foldl(fun
                           ([RoleId, Tier, Star, Time], Acc) ->
                               case lists:keyfind(RoleId, 1, Acc) of
                                   {RoleId, Tier0, Star0, Time0, _} ->
                                       if
                                           Time < Time0 orelse (Time == Time0 andalso (Tier bsl 16 + Star) > (Tier0 bsl 16 + Star0)) ->
                                               lists:keystore(RoleId, 1, Acc, {RoleId, Tier, Star, Time, 1});
                                           true ->
                                               lists:keystore(RoleId, 1, Acc, {RoleId, Tier0, Star0, Time0, 1})
                                       end;
                                   _ ->
                                       [{RoleId, Tier, Star, Time, 0}|Acc]
                               end
                       end, [], All),
    SlimList = [{RoleId, Tier, Star} || {RoleId, Tier, Star, _Time, 1} <- List],
    spawn(fun () ->
        [begin
             Pid = misc:get_player_process(RoleId),
             case is_pid(Pid) andalso misc:is_process_alive(Pid) of
                 true ->
                     lib_player:apply_cast(Pid, ?APPLY_CAST_STATUS, ?MODULE, setup_player_tier, [Tier, Star]);
                 _ ->
                     SQL2 = io_lib:format("update role_3v3 set tier = ~w, star = ~w where role_id = ~w", [Tier, Star, RoleId]),
                     db:execute(SQL2)
             end,
	     timer:sleep(100)
         end || {RoleId, Tier, Star} <- SlimList]
          end),
    ok.
