%% ---------------------------------------------------------------------------
%% @doc 跨服帮战管理进程
%% @author zhaoyu
%% @since  2018-08-28
%% ---------------------------------------------------------------------------
-module(cross_guild_war_mgr).

-behaviour(gen_server).


-include("guild_war.hrl").
-include("cross_guild_war.hrl").
-include("common.hrl").
-include("errcode.hrl").
-include("predefine.hrl").
-include("def_module.hrl").
-include("czone.hrl").
-include("guild.hrl").
-include("def_fun.hrl").
-include("camp_war.hrl").
-include("figure.hrl").

-export([start_link/0]).
-export ([init/1, handle_call/3, handle_cast/2, handle_info/2, code_change/3, terminate/2]).

-export([
        cast/1
        ,enter_sign/1
        ,enter_support/1
        ,enter_battle/2
        ,enter_over/1
        ,gm_stop/0
        ,update_join_guild/3        %%单个上报
        ,update_join_guild/1        %%批量上报
        ,return_support_local/1     %% 游戏服执行应援返还
        ,notice_cancel_mail_local/0 %% 给玩家发送邮件通知不能参与本次跨服帮战活动
        ,split_server_helper/2
        ,add_svrs/1
        ,recalc_zone/1
        % ,sync_switch_state/3
        ,zone_schedule_check_center/1

        ,pack_own_city_log/2
]).

%% 启动进程
start_link() ->
    gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).

cast(Msg) ->
    gen_server:cast(?MODULE, Msg).

add_svrs(CBMap)->
    gen_server:cast(?MODULE, {add_svrs,CBMap}).

recalc_zone(CBMap)->
    gen_server:cast(?MODULE,{recalc_zone,CBMap}).

%%进入报名期
enter_sign(Process)->
    gen_server:cast(?MODULE, {enter_sign,Process}).

enter_support(Process)->
    gen_server:cast(?MODULE, {enter_support,Process}).

%%开启战场
enter_battle(Process,ETime)->
    gen_server:cast(?MODULE, {enter_battle,Process,ETime}).

%%战斗结束
enter_over(Process)->
    gen_server:cast(?MODULE,{enter_over,Process}).

gm_stop()->
    gen_server:cast(?MODULE,{gm_stop}).

%%跨服团战结果上报
%%同时告诉各服战报
update_join_guild(ZoneId,FactId,SortedGuilds)->
    gen_server:cast(?MODULE,{update_join_guild,ZoneId,FactId,SortedGuilds}),
    %sync_notice_war_result(SortedGuilds),
    ok.

%%按照分区统一上报参与社团
update_join_guild(ZoneGuilds)->
    gen_server:cast(?MODULE,{update_join_guild,ZoneGuilds}),
    %sync_notice_war_result(SortedGuilds),
    ok.

init([]) ->
    erlang:process_flag(trap_exit, true),
    %% 城池占领信息
    EtsArgsC = [
        {keypos, #cgw_zone_city_info.zone_id}, named_table, public, set
    ],
    ets:new(?CGW_CITY_ETS, EtsArgsC),

    %% 城池占领日志
    EtsArgsL = [
        {keypos, #cgw_zone_city_log.zone_id}, named_table, public, set
    ],
    ets:new(?CGW_CITY_LOG_ETS, EtsArgsL),

    %% 帮派与战场pid()对应关系信息ets
    EtsArgsG = [
        {keypos, #cgw_guild_battlefield_info.guild_id}, named_table, public, set
    ],
    ets:new(?CGW_GUILD_BATTLEFIELD_PID, EtsArgsG),

    EtsArgsJ = [
        {keypos, #cgw_server_info.zone_id}, named_table, public, set
    ],
    ets:new(?CGW_CAN_JOIN_ETS, EtsArgsJ),

    cross_guild_war_db:load_city_info(),
    ZoneMap = czone:get_svr_zone_map(),
    FactMap = czone:get_faction_map(svr_faction_map),

    ZoneGuildList = cross_guild_war_db:load_guild_info(FactMap),
    [begin
        put_zone_guild_help_info(Zone#cgw_zone_guild_info{guild_list = []}),
        put_zone_guild_info(Zone) end || Zone <- ZoneGuildList],


    ZoneGuildHelpList = cross_guild_war_db:load_guild_help_info(FactMap),
    [put_zone_guild_help_info(Zone) || Zone <- ZoneGuildHelpList],

    [LZoneMap,LFactMap] = cross_guild_war_db:load_last_zones(),
    State = #cgw_mgr_state{ser2zone=ZoneMap,ser2fact=FactMap,last_ser2zone=LZoneMap,last_ser2fact=LFactMap},
    cross_guild_war_db:load_cgw_log(),
    {ok, State}.

handle_call(Msg, From, State) ->
    case catch do_handle_call(Msg, From, State) of
        {'EXIT', Error} ->
            ?ERR("handle_call error: ~p~nMsg=~p~n", [Error, Msg]),
            {reply, error, State};
        Return  ->
            Return
    end.

handle_cast(Msg, State) ->
    case catch do_handle_cast(Msg, State) of
        {'EXIT', Error} ->
            ?ERR("handle_cast error: ~p~nMsg=~p~n", [Error, Msg]),
            {noreply, State};
        Return  ->
            Return
    end.

handle_info(Info, State) ->
    case catch do_handle_info(Info, State) of
        {'EXIT', Error} ->
            ?ERR("handle_info error: ~p~nInfo=~p~n", [Error, Info]),
            {noreply, State};
        Return  ->
            Return
    end.

terminate(_Reason, State)->
    #cgw_mgr_state{process=Process}=State,
    case lists:member(Process,[?CGW_ST_SIGN,?CGW_ST_SUPPORT]) of
        true->
            ZoneList = get_zone_guild_info(),
            cross_guild_war_db:save_guild_info(ZoneList),
            ZoneHelpList = get_zone_guild_help_info(),
            cross_guild_war_db:save_guild_help_info(ZoneHelpList);
        _->
            skip
    end,
    ok.

code_change(_OldVsn, State, _Extra) ->
    {ok, State}.

do_handle_call(_Msg, _From, State) ->
    {reply, ok, State}.


%%进入报名期 准备好数据
%%也让各服清理数据
do_handle_cast({enter_sign,Process},State)->

    FactMap = czone:get_faction_map(svr_faction_map),
    NewState = zone_init(State),

    % #cgw_mgr_state{ser2fact=FactMap,ser2zone=ZoneMap}=State,
    % ServerInfoList = ets:tab2list(?CGW_CAN_JOIN_ETS),
    % sync_switch_state(ServerInfoList,maps:to_list(FactMap),maps:to_list(ZoneMap)),
    {noreply,NewState#cgw_mgr_state{process=Process,ser2fact=FactMap}};
%%进入应援
do_handle_cast({enter_support,Process},State)->
    split_guild_helper(),
    mail_all_helper(),
    {noreply,State#cgw_mgr_state{process=Process}};

%%进入战斗
do_handle_cast({enter_battle,Process,ETime},State)->
    %% 城池占领情况
    ets:delete_all_objects(?CGW_CITY_ETS),
    cross_guild_war_db:del_city_info(),
    NewState = battle_init(State#cgw_mgr_state{end_time=ETime}),
    ZoneList = get_zone_guild_info(),
    offline_hosting_cgwar:check_zone_hosting(ZoneList),
    {noreply,NewState#cgw_mgr_state{process=Process}};

%%结束战斗
do_handle_cast({enter_over,Process},State)->
    NewState = act_end(State),
    {noreply,NewState#cgw_mgr_state{process=Process}};

%% 应援帮派
do_handle_cast({support, SupportRole, ServerId, GuildId, Sid, Pid}, State)  ->
    case zone_schedule_check_center(ServerId) of
        false->
            ErrCode = ?ERRCODE(err601_no_server_zone);
        _->
            #cgw_mgr_state{ser2zone=ZoneMap}=State,
            ErrCode = case maps:get(ServerId,ZoneMap,0) of
                ZoneId when ZoneId>0 ->
                    support_guild_do(ZoneId, GuildId, SupportRole, Pid);
                _ ->
                    ?ERRCODE(err601_no_server_zone)
            end
    end,
    {ok, BinData} = pt_601:write(60104, [ErrCode, GuildId]),
    lib_server_send:send_to_sid(Sid, BinData),
    {noreply, State};

%% 帮战参赛信息-报名阶段和活动进行中
do_handle_cast({send_zone_guilds_info, RoleId, ServerId, _GuildId, Sid,LastSign}, State) ->
    #cgw_mgr_state{ser2zone=ZoneMap,ser2fact=FactMap,process=Process}=State,
    ProData = case maps:get(ServerId,ZoneMap,0) of
        ZoneId when ZoneId>0->
            FactId = maps:get(ServerId,FactMap,0),
            IsSignUp = check_sign(Process,RoleId, ZoneId, FactId),
            GuildList = case get_zone_guild_info(ZoneId) of
                #cgw_zone_guild_info{guild_list = GuildL} -> GuildL;
                _ -> []
            end,
            DataList = pack_zone_guilds(GuildList),
            [IsSignUp,LastSign, DataList];
        _ ->
            [0,LastSign,[]]
    end,
    {ok, BinData} = pt_601:write(60102, ProData),
    lib_server_send:send_to_sid(Sid, BinData),
    {noreply, State};

%% 上次活动中城池占领信息
do_handle_cast({send_city_info, ServerId, Sid, AwardLog}, State) ->
    #cgw_mgr_state{last_ser2zone=ZoneMap,last_ser2fact=FactMap}=State,
    DataList = case maps:get(ServerId,ZoneMap,0) of
        ZoneId when ZoneId>0 ->
            pack_city_info(ZoneId, ServerId, FactMap,  AwardLog);
        _ ->
            []
    end,
    {ok, BinData} = pt_601:write(60101, [DataList]),
    lib_server_send:send_to_sid(Sid, BinData),
    {noreply, State};

%%取消报名
do_handle_cast({sign_up, OpTy, Sid, RoleInfo, GuildInfo},State) when OpTy=<0->
    #cgw_role_info{role_id=RoleId,server_id = ServerId} = RoleInfo,
    case zone_schedule_check_center(ServerId) of
        false->
            ErrCode = ?ERRCODE(err601_no_server_zone),
            IsHelp = 0;
        _->
            #cgw_mgr_state{ser2zone=ZoneMap,ser2fact=FactMap}=State,
            {ErrCode,IsHelp} =
                    case maps:get(ServerId,ZoneMap,0) of
                        ZoneId when ZoneId>0->
                            FactId = maps:get(ServerId,FactMap,0),
                            sign_up_cancel(ZoneId,FactId,RoleInfo,GuildInfo);
                        _ ->
                            {?ERRCODE(err601_no_server_zone),0}
                    end
    end,
    case ErrCode == ?SUCCESS of
        true->
            clusters_center:apply_cast(ServerId, {lib_player, apply_cast, [RoleId, ?APPLY_CAST_SAVE,cross_guild_war_api, mark_sign_cancle, []]});
        _->
            skip
    end,
    {ok, BinData} = pt_601:write(60106, [ErrCode,OpTy,IsHelp]),
    lib_server_send:send_to_sid(Sid, BinData),
    {noreply, State};
%% 报名
do_handle_cast({sign_up, OpTy, Sid, RoleInfo, GuildInfo},State) ->
    #cgw_role_info{server_id = ServerId} = RoleInfo,
    case zone_schedule_check_center(ServerId) of
        false->
            ErrCode = ?ERRCODE(err601_no_server_zone),
            IsHelp = 0;
        _->
            #cgw_mgr_state{ser2zone=ZoneMap,ser2fact=FactMap}=State,
            {ErrCode,IsHelp} =
                    case maps:get(ServerId,ZoneMap,0) of
                        ZoneId when ZoneId>0->
                            FactId = maps:get(ServerId,FactMap,0),
                            sign_up_do(ZoneId,FactId,RoleInfo,GuildInfo);
                        _ ->
                            {?ERRCODE(err601_no_server_zone),0}
                    end
    end,
    {ok, BinData} = pt_601:write(60106, [ErrCode,OpTy,IsHelp]),
    lib_server_send:send_to_sid(Sid, BinData),
    {noreply, State};

%% gm_stop跨服公会战。需要关闭所有的cross_guild_war_battle进程.
do_handle_cast({gm_stop}, State) ->
    BattlefieldList = ets:tab2list(?CGW_GUILD_BATTLEFIELD_PID),
    BattlefieldPids = [
        Pid || #cgw_guild_battlefield_info{pid = Pid} <- BattlefieldList
    ],
    Pids = lists:usort(BattlefieldPids),
    [cross_guild_war_battle:info(Pid, {time_is_over}) || Pid <- Pids],
    {noreply, State};

%% 处理返回来的战场结果
do_handle_cast({battlefield_result, ZoneId, _Pid, BattleResult}, State) ->
    #cgw_mgr_state{battle_result = Result} = State,
    NewZoneInfo = #cgw_zone_city_info{
        zone_id = ZoneId,
        city_info = BattleResult
    },
    NewResult = lists:keystore(ZoneId, #cgw_zone_city_info.zone_id, Result,NewZoneInfo),
    NewState = State#cgw_mgr_state{battle_result = NewResult},
    choose_king(BattleResult),
    {noreply, NewState};

%%上报各阵营 自己测试用
do_handle_cast({update_join_guild,ZoneId,_FacId,Guilds},State)->
    case lists:member(State#cgw_mgr_state.process,[?CGW_ST_IDLE,?CGW_ST_OVER]) of
        true->
            batch_update_join_one(ZoneId,Guilds),
            {noreply,State};
        _->
            {noreply,State}
    end;

%%统一上报
do_handle_cast({update_join_guild,ZoneGuilds},State)->
    batch_update_join(ZoneGuilds),
    FactMap = czone:get_faction_map(svr_faction_map),
    NewState = zone_init(State),
    % #cgw_mgr_state{ser2fact=FactMap,ser2zone=ZoneMap}=State,
    % ServerInfoList = ets:tab2list(?CGW_CAN_JOIN_ETS),
    % sync_switch_state(ServerInfoList,maps:to_list(FactMap),maps:to_list(ZoneMap)),
    {noreply,NewState#cgw_mgr_state{process=?CGW_ST_SIGN,ser2fact=FactMap}};

do_handle_cast({update_join_guild,SerID,CanJoins},State)->
    #cgw_mgr_state{ser2zone=ZoneMap,ser2fact=FactMap}=State,
    ZoneId = maps:get(SerID,ZoneMap,0),
    FactId = maps:get(SerID,FactMap,0),
    NCanJoins = [A#cgw_guild_info{zone_id=ZoneId,fact_id=FactId}||A<-CanJoins],
    do_handle_cast({update_join_guild,ZoneId,FactId,NCanJoins},State);

%% 进入场景
do_handle_cast({enter_scene, Sid, RoleInfo}, State) ->
    #cgw_role_info{server_id = ServerId} = RoleInfo,
    #cgw_mgr_state{ser2zone=ZoneMap,ser2fact=FactMap}=State,
    ErrCode = case maps:get(ServerId,ZoneMap,0) of
        ZoneId when ZoneId>0->
            case maps:get(ServerId,FactMap,0) of
                FactId when FactId>0->
                    enter_scene_do(ZoneId,FactId,RoleInfo);
                _->
                    ?ERRCODE(err601_no_server_zone) %?ERR601_NO_SERVER_ZONE
            end;
        _ ->
            ?ERRCODE(err601_no_server_zone) %?ERR601_NO_SERVER_ZONE
    end,
    {ok, BinData} = pt_601:write(60108, [ErrCode]),
    lib_server_send:send_to_sid(Sid, BinData),
    {noreply, State};
%% 离开场景
do_handle_cast({leave_scene, Sid, RoleId, ServerId}, State) ->
    GuildId = get_guild_id(RoleId,ServerId,State),
    ErrCode = case ets:lookup(?CGW_GUILD_BATTLEFIELD_PID, GuildId) of
        [#cgw_guild_battlefield_info{pid = Pid}] ->
            Msg = {leave_scene, RoleId},
            cross_guild_war_battle:cast(Pid, Msg),
            ?SUCCESS;
        _ ->
            MFA = {cross_guild_war_api, leave_scene_function, [RoleId]},
            clusters_center:apply_cast(ServerId, MFA),
            ?ERRCODE(err601_no_battle_pid)%?ERR601_NO_BATTLE_PID
    end,
    ErrCode == ?SUCCESS andalso begin
        {ok, BinData} = pt_601:write(60109, [ErrCode]),
        lib_server_send:send_to_sid(Sid, BinData)
    end,
    {noreply, State};
%% 战场信息
do_handle_cast({send_battlefield_info, Sid, RoleId, ServerId}, State) ->
    GuildId = get_guild_id(RoleId,ServerId,State),
    case ets:lookup(?CGW_GUILD_BATTLEFIELD_PID, GuildId) of
        [#cgw_guild_battlefield_info{pid = Pid}] ->
            Msg = {send_battlefield_info, Sid},
            cross_guild_war_battle:cast(Pid, Msg);
        _ ->
            ok
    end,
    {noreply, State};

%% 报名榜 社团
do_handle_cast({send_room_sign_up_info, ServerId, OpTy, Sid}, State) when OpTy=<0 ->
    #cgw_mgr_state{ser2zone=ZoneMap,ser2fact=FactMap}=State,
    ProData =case maps:get(ServerId,ZoneMap,0) of
        ZoneId when ZoneId>0->
            FactId = maps:get(ServerId,FactMap,0),
            GuildList = case get_zone_guild_info(ZoneId) of
                #cgw_zone_guild_info{guild_list = GuildL} -> GuildL;
                _ -> []
            end,
            DataList = pack_room_sign_up_roles(GuildList,FactId),
            [OpTy, DataList];
        _ ->
            [OpTy, []]
    end,
    {ok, BinData} = pt_601:write(60105, ProData),
    lib_server_send:send_to_sid(Sid, BinData),
    {noreply, State};
%% 报名榜 外援 外援用阵营构建了一个虚拟社团
do_handle_cast({send_room_sign_up_info, ServerId, OpTy, Sid}, State)->
    #cgw_mgr_state{ser2zone=ZoneMap,ser2fact=FactMap}=State,
    ProData =case maps:get(ServerId,ZoneMap,0) of
        ZoneId when ZoneId>0->
            FactId = maps:get(ServerId,FactMap,0),
            GuildList = case get_zone_guild_help_info(ZoneId) of
                #cgw_zone_guild_info{guild_list = GuildL} -> GuildL;
                _ -> []
            end,
            DataList = pack_room_sign_up_roles(GuildList,FactId),
            [OpTy, DataList];
        _ ->
            [OpTy, []]
    end,
    {ok, BinData} = pt_601:write(60105, ProData),
    lib_server_send:send_to_sid(Sid, BinData),
    {noreply, State};

%% 发出号令
do_handle_cast({send_guild_direction, Sid, RoleId, ServerId, CityId}, State) ->
    GuildId = get_guild_id(RoleId,ServerId,State),
    #cgw_mgr_state{ser2fact=FactMap}=State,
    FactId = maps:get(ServerId,FactMap,0),
    case ets:lookup(?CGW_GUILD_BATTLEFIELD_PID, GuildId) of
        [#cgw_guild_battlefield_info{pid = Pid}] ->
            Msg = {send_guild_direction, Sid, FactId, CityId},
            cross_guild_war_battle:cast(Pid, Msg);
        _ ->
            ok
    end,
    {noreply, State};

%% 应援列表
do_handle_cast({send_support_list, ServerId, Sid, SupportNum, LessFreeTimes, RoleId},State) ->
    #cgw_mgr_state{ser2zone=ZoneMap}=State,
    case maps:get(ServerId,ZoneMap,0) of
        ZoneId when ZoneId>0 ->
            send_support_list(ZoneId, Sid, SupportNum, LessFreeTimes, RoleId);
        _ ->
            ok
    end,
    {noreply, State};

%% 领取占领城池奖励
do_handle_cast({get_city_award, ServerId, CityId, _GuildId, Sid, Pid}, State) ->
    #cgw_mgr_state{last_ser2zone=ZoneMap,last_ser2fact=FactMap}=State,
    ErrCode = case maps:get(ServerId,ZoneMap,0) of
        ZoneId when ZoneId>0 ->
            get_city_award(ZoneId, CityId, ServerId, Pid, FactMap);
        _ ->
            ?ERRCODE(err601_donot_own_city)%?ERR601_DONOT_OWN_CITY
    end,
    case ErrCode of
        ok ->
            ok;
        _ ->
            {ok, BinData} = pt_601:write(60107, [CityId, ErrCode]),
            lib_server_send:send_to_sid(Sid, BinData)
    end,
    {noreply, State};

do_handle_cast({get_cgw_log, ServerId, Sid},State)->
    #cgw_mgr_state{last_ser2zone=ZoneMap}=State,
    ZoneId = maps:get(ServerId,ZoneMap,0),
    case ets:lookup(?CGW_CITY_LOG_ETS, ZoneId) of
        [#cgw_zone_city_log{times_citys=Citys}|_] ->
            CitysL   = pack_city_log(Citys,[]),
            {ok,Bin} = pt_601:write(60115,[CitysL]),
            lib_server_send:send_to_sid(Sid, Bin);
        _ ->
            skip
    end,
    {noreply,State};

do_handle_cast({sync_to_cgw_mgr,Process,TimeOut},State)->
    case Process of
        ?CGW_ST_SUPPORT when TimeOut>300->
            split_guild_helper(),
            mail_all_helper();
        _->
            ok
    end,

    % case lists:member(Process,[?CGW_ST_SIGN,?CGW_ST_SUPPORT]) of
    %     true->
    %         #cgw_mgr_state{ser2fact=FactMap,ser2zone=ZoneMap}=State,
    %         ServerInfoList = ets:tab2list(?CGW_CAN_JOIN_ETS),
    %         sync_switch_state(ServerInfoList,maps:to_list(FactMap),maps:to_list(ZoneMap));
    %     _->
    %         skip
    % end,

    {noreply,State#cgw_mgr_state{process=Process}};

do_handle_cast({add_svrs,CBMap},State)->
    #cgw_mgr_state{ser2zone=ZoneMap,ser2fact=FactMap}=State,
    #{add_servers := AddServers}=CBMap,
    [NZoneMap,NFactMap] = do_add_svrs(AddServers,ZoneMap,FactMap),
    NState = State#cgw_mgr_state{ser2zone=NZoneMap,ser2fact=NFactMap},
    {noreply,NState};


do_handle_cast({recalc_zone,CBMap},State)->
     #{svr_zone_map := ZoneMap} = CBMap,
     NState = State#cgw_mgr_state{ser2zone=ZoneMap},
     {noreply,NState};

do_handle_cast({faction_rename, RoleId, ServerId, FactId, FactionName},State)->
    #cgw_mgr_state{ser2zone = ZoneMap}=State,
    ZoneId =  maps:get(ServerId,ZoneMap,0),
    IsTrue = lists:member(FactId, ?FACTION_LIST),
    FactionNameBin = util:make_sure_binary(FactionName),
    ErrCode =
    if
        IsTrue ->
            case czone:get_faction_name(ZoneId, all) of
                FactionNameList when is_list(FactionNameList) ->
                    IsSameName = lists:any(fun({_, NameBin}) -> NameBin == FactionNameBin end, FactionNameList),
                    ?IF(IsSameName, ?ERRCODE(err601_faction_name_same), ?SUCCESS);
                _ ->
                    ?FAIL
            end;
        true ->
            ?FAIL
    end,
    ErrCode == ?SUCCESS andalso czone:set_faction_name(ZoneId, FactId, FactionName),
    clusters_center:apply_cast(ServerId, {lib_player, apply_cast, [RoleId, ?APPLY_CAST_SAVE,
        cross_guild_war_api, rename_callback, [ErrCode, FactId, FactionName]]}),
    {noreply,State};

do_handle_cast({recover_cgw_log, Time},State)->
    #cgw_mgr_state{ser2fact=Facts} = State,
    Result = ets:tab2list(?CGW_CITY_ETS),
    update_cgw_log(Result, Facts, Time),
    {noreply,State};

do_handle_cast(_Msg, State) ->
    {noreply, State}.


do_handle_info({'EXIT', _Pid, Reason}, State) ->
    ErrorInfo = Reason,
    ?ERR("cross_guild_war_mgr_error:~p~n", [ErrorInfo]),
    {noreply, State};

do_handle_info(_Msg, State) ->
    {noreply, State}.

%%
%% @doc 进行分区相关初始化
zone_init(State) ->
    del_zone_guild_info(),
    del_zone_guild_help_info(),
    NewState = init_zone_guild_info(State),
    NewState.

%% ---------------------------------------------------------------------------
%% @doc 确定各个分区可以参战的帮派。
init_zone_guild_info(State) ->
    ServerInfoList = ets:tab2list(?CGW_CAN_JOIN_ETS),
    init_zone_guild_info(State, ServerInfoList).
init_zone_guild_info(State, []) ->
    State;
init_zone_guild_info(State, [ServerInfo | T]) ->
    #cgw_server_info{zone_id=ZoneId, guild_list = GuildList0} = ServerInfo,

    GuildList = filter_ready_rezone(GuildList0),

    case length(GuildList0) /= length(GuildList) of
        true->
            NServerInfo = ServerInfo#cgw_server_info{zone_id=ZoneId,guild_list=GuildList},
            ets:insert(?CGW_CAN_JOIN_ETS, NServerInfo);
        _->
            skip
    end,

    NewGuildList = [
        GInfo#cgw_guild_info{zone_id = ZoneId} || GInfo <- GuildList
    ],
    NewZoneGuildInfo = #cgw_zone_guild_info{
        zone_id = ZoneId, guild_list = NewGuildList
    },
    put_zone_guild_info(NewZoneGuildInfo),
    put_zone_guild_help_info(#cgw_zone_guild_info{zone_id = ZoneId, guild_list = []}),
    init_zone_guild_info(State, T).


% %%同步开关状态
% sync_switch_state(ServerInfoList,Facts,Zones)->
%     sync_switch_state(ServerInfoList,Facts,Zones,[]).
% sync_switch_state([],_,_,_)->
%     ok;
% sync_switch_state([H|T],Facts,Zones,FinishFacts)->
%     #cgw_server_info{zone_id=ZoneId,guild_list = GuildList} = H,
%     CanJoins = [
%         FactId || #cgw_guild_info{fact_id=FactId} <- GuildList
%     ],
%     NFinishFacts = do_sync_switch_state(CanJoins,ZoneId,Facts,Zones,FinishFacts),
%     sync_switch_state(T,Facts,Zones,NFinishFacts).

% do_sync_switch_state([],_,_,_,FinishFacts)->
%     FinishFacts;
% do_sync_switch_state([H|T],ZoneId,Facts,Zones,FinishFacts)->
%     case lists:member(H,FinishFacts) of
%         true->%%不要重复通知
%             do_sync_switch_state(T,ZoneId,Facts,Zones,FinishFacts);
%         _->
%             Servers = filter_server(H,ZoneId,Facts,Zones),
%             [ begin
%                 MFA = {cross_guild_war_local, sync_switch_state, [1]},
%                 clusters_center:apply_cast(ServerId, MFA)
%              end || ServerId<-Servers ],

%             do_sync_switch_state(T,ZoneId,Facts,Zones,[H|FinishFacts])
%     end.

% filter_server(FactId,ZoneId,Facts,Zones)->
%     Servers0  = [Sid||{Sid,Z}<-Zones,Z=:=ZoneId],
%     Servers   = [Sid||{Sid,F}<-Facts,F=:=FactId,lists:member(Sid,Servers0)],
%     Servers.

%% ---------------------------------------------------------------------------
%% @doc 创建战场并且确保所有数据已经重置
battle_init(State) ->
    %% 帮派与战场pid()对应关系信息ets
    ets:delete_all_objects(?CGW_GUILD_BATTLEFIELD_PID),

    ZoneList = get_zone_guild_info(),
    %% 按分区Id排序
    ZoneInfoList = lists:keysort(#cgw_zone_guild_info.zone_id, ZoneList),
    %% 给不同的房间开启战场
    #cgw_mgr_state{end_time = EndTime} = State,
    start_battlefield(ZoneInfoList, EndTime),
    State.

%%分配支援者
split_guild_helper()->
    ZonehelpList = get_zone_guild_help_info(),
    split_guild_helper(ZonehelpList).

split_guild_helper([])->
    ok;
split_guild_helper([H|T])->
    #cgw_zone_guild_info{zone_id=ZoneId,guild_list=GuildList}=H,
    split_guild_fact_helper(ZoneId,GuildList),
    split_guild_helper(T).

split_guild_fact_helper(_,[])->
    ok;
split_guild_fact_helper(ZoneId,[H|T])->
    #cgw_guild_info{sign_ups=Helpers,fact_id=FactId}=H,
    case get_zone_guild_info(ZoneId) of
        #cgw_zone_guild_info{guild_list = GuildL} ->
            NGuildsList = split_guild_room_helper(GuildL,FactId,Helpers),
            put_zone_guild_info(#cgw_zone_guild_info{zone_id=ZoneId,guild_list = NGuildsList});
        _ ->
            []
    end,
    split_guild_fact_helper(ZoneId,T).


split_guild_room_helper(GuildL,_FactId,[])->
    GuildL;
split_guild_room_helper(GuildL,FactId,Helpers)->
    {PreHelpers,_LastHelpers} = ulists:split(10,Helpers),
    NGuildL = add_guild_helper(GuildL,FactId,PreHelpers,[]),
    NGuildL.


add_guild_helper([],_FactId,_,GuildL)->
    GuildL;
add_guild_helper([H|T],FactId,Helpers,GuildL)->
    #cgw_guild_info{guild_id=_GuildId,fact_id=Fact}=H,
    case Fact =:= FactId of
        true->
            add_guild_helper(T,FactId,Helpers,[H#cgw_guild_info{help_ups=Helpers}|GuildL]);
        _->
            add_guild_helper(T,FactId,Helpers,[H|GuildL])
    end.



%% ---------------------------------------------------------------------------
%% @doc 给不同的房间开启战场
-spec start_battlefield(ZoneInfoList, EndTime) -> ok when
    ZoneInfoList    :: [#cgw_zone_guild_info{}],
    EndTime         :: integer().
%% ---------------------------------------------------------------------------
start_battlefield([], _EndTime) ->
    ok;
start_battlefield([ZoneInfo | T], EndTime) ->
    #cgw_zone_guild_info{zone_id = ZoneId, guild_list = GuildList} = ZoneInfo,
    cross_guild_war_battle:start_link(ZoneId, GuildList, EndTime),
    start_battlefield(T, EndTime).


%% ---------------------------------------------------------------------------
%% @doc 跨服帮战活动结束
-spec act_end(Data) -> NewData when
    Data        :: #cgw_mgr_state{},
    NewData     :: #cgw_mgr_state{}.
%% ---------------------------------------------------------------------------
act_end(State) ->
    %% 分区信息保存为上一次分区信息
    #cgw_mgr_state{ser2zone=Zones,ser2fact=Facts,battle_result = Result}=State,
    cross_guild_war_db:del_zones_and_save_last_zones(Zones,Facts),

    ets:insert(?CGW_CITY_ETS, Result),
    cross_guild_war_db:save_city_info(Result),

    %% 帮派与战场pid()对应关系信息ets
    ets:delete_all_objects(?CGW_GUILD_BATTLEFIELD_PID),

    %% 各个分区帮派报名和援助信息
    %% 进程字典中的帮派报名和援助信息保存到下次活动开启，只清理数据库中的数据。
    %% del_zone_guild_info(),
    cross_guild_war_db:del_guild_info(),

    %% 活动结束清除玩家应援和领取奖励记录
    clusters_center:apply_to_all_node(cross_guild_war_api, del_role_cgw, []),

    update_cgw_log(Result, Facts),

    del_zone_guild_help_info(),
    cross_guild_war_db:del_guild_help_info(),

    ets:delete_all_objects(?CGW_CAN_JOIN_ETS),

    State#cgw_mgr_state{last_ser2zone=Zones,last_ser2fact=Facts,battle_result = []}.


%% ---------------------------------------------------------------------------
%% @doc 获取各个分区帮派报名和援助信息
-spec get_zone_guild_info() -> ZoneList when
    ZoneList      :: [#cgw_zone_guild_info{}].
%% ---------------------------------------------------------------------------
get_zone_guild_info() ->
    [Zone || {{zone_guild_info, _ZoneId}, Zone} <- erlang:get()].


get_zone_guild_help_info() ->
    [Zone || {{zone_guild_help_info, _ZoneId}, Zone} <- erlang:get()].

%% ---------------------------------------------------------------------------
%% @doc 获取各个分区帮派报名和援助信息
-spec get_zone_guild_info(ZoneId) -> Return when
    ZoneId      :: integer(),
    Return      :: #cgw_zone_guild_info{} | undefined.
%% ---------------------------------------------------------------------------
get_zone_guild_info(ZoneId) ->
    erlang:get({zone_guild_info, ZoneId}).

%% ---------------------------------------------------------------------------
%% @doc 保存各个分区帮派报名和援助信息
-spec put_zone_guild_info(ZoneGuildInfo) -> Return when
    ZoneGuildInfo   :: #cgw_zone_guild_info{},
    Return          :: #cgw_zone_guild_info{} | undefined.
%% ---------------------------------------------------------------------------
put_zone_guild_info(ZoneGuildInfo) ->
    #cgw_zone_guild_info{zone_id = ZoneId} = ZoneGuildInfo,
    erlang:put({zone_guild_info, ZoneId}, ZoneGuildInfo).

%% @doc 获取各个分区外援信息
get_zone_guild_help_info(ZoneId)->
    erlang:get({zone_guild_help_info, ZoneId}).

put_zone_guild_help_info(ZoneGuildInfo) ->
    #cgw_zone_guild_info{zone_id = ZoneId} = ZoneGuildInfo,
    erlang:put({zone_guild_help_info, ZoneId}, ZoneGuildInfo).


%% ---------------------------------------------------------------------------
%% @doc 清空各个分区帮派报名和援助信息
-spec del_zone_guild_info() -> ok.
%% ---------------------------------------------------------------------------
del_zone_guild_info() ->
    [erlang:erase(Key) || {Key = {zone_guild_info, _ZoneId}, _Zone} <- erlang:get()],
    ok.
%% @doc 清空各个分区外援信息
del_zone_guild_help_info()->
    [erlang:erase(Key) || {Key = {zone_guild_help_info, _ZoneId}, _Zone} <- erlang:get()],
    ok.


% %% ---------------------------------------------------------------------------
% %% @doc 清空分区帮派报名和援助信息
% -spec del_zone_guild_info(ZoneId) -> ok when
%     ZoneId  :: integer().
% %% ---------------------------------------------------------------------------
% del_zone_guild_info(ZoneId) ->
%     erlang:erase({zone_guild_info, ZoneId}),
%     ok.

%%取消逻辑
sign_up_cancel(ZoneId,FactId,RoleInfo,GuildInfo)->
    #cgw_role_info{role_id = RoleId} = RoleInfo,
    case GuildInfo of
        #cgw_guild_info{guild_id = GuildId} when GuildId>0->
            case get_zone_guild_info(ZoneId) of
                Zone = #cgw_zone_guild_info{guild_list = GuildList} ->
                    case lists:keytake(GuildId, #cgw_guild_info.guild_id, GuildList) of
                        {value, Guild = #cgw_guild_info{sign_ups = SignUps}, LessGs} ->
                            case lists:keytake(RoleId, #cgw_role_info.role_id, SignUps) of
                                {value,_,SignUps2}->
                                    Guild2 = Guild#cgw_guild_info{sign_ups = SignUps2},
                                    Guild3 = update_guild_info(GuildInfo, Guild2),
                                    NewGuildList = [Guild3 | LessGs],
                                    NewZone = Zone#cgw_zone_guild_info{
                                        guild_list = NewGuildList
                                    },
                                    put_zone_guild_info(NewZone),
                                    {?SUCCESS,0};
                                true ->
                                    sign_up_help_cancel(ZoneId,FactId,RoleInfo)
                            end;
                        _ ->
                            sign_up_help_cancel(ZoneId,FactId,RoleInfo)
                    end;
                _ ->
                    sign_up_help_cancel(ZoneId,FactId,RoleInfo)
            end;
        _->
           sign_up_help_cancel(ZoneId,FactId,RoleInfo)
    end.


%% ---------------------------------------------------------------------------
%% @doc 报名逻辑
sign_up_do(ZoneId,FactId,RoleInfo,GuildInfo) ->
    #cgw_role_info{role_id = RoleId} = RoleInfo,
    case  GuildInfo of
        #cgw_guild_info{guild_id = GuildId} when GuildId>0->
            case get_zone_guild_info(ZoneId) of
                Zone = #cgw_zone_guild_info{guild_list = GuildList} ->
                    case lists:keytake(GuildId, #cgw_guild_info.guild_id, GuildList) of
                        {value, Guild = #cgw_guild_info{sign_ups = SignUps}, LessGs} ->
                            case lists:keymember(RoleId, #cgw_role_info.role_id, SignUps) of
                                false ->
                                    SignUps2 = lists:keysort(#cgw_role_info.power, [RoleInfo | SignUps]),
                                    Len = length(SignUps2),
                                    Max = data_cross_guild_war:get_config(sign_up_max),
                                    {SignUps3, DeleteRole} = case Len > Max of
                                        true ->
                                            [DeleteR | Tail] = SignUps2,
                                            {Tail, DeleteR};
                                        false ->
                                            {SignUps2, false}
                                    end,
                                    Guild2 = Guild#cgw_guild_info{sign_ups = SignUps3},
                                    Guild3 = update_guild_info(GuildInfo, Guild2),
                                    NewGuildList = [Guild3 | LessGs],
                                    NewZone = Zone#cgw_zone_guild_info{
                                        guild_list = NewGuildList
                                    },
                                    put_zone_guild_info(NewZone),
                                    case DeleteRole of
                                        RoleInfo -> %% 战力不足
                                            {?ERRCODE(err601_power_lower),0};
                                        DRole = #cgw_role_info{} -> %% 挤走了别人
                                            send_consolation(0,DRole),
                                            {?SUCCESS,0};
                                        false -> %% 人数没达到上限
                                            {?SUCCESS,0}
                                    end;
                                true ->
                                    {?ERRCODE(err601_have_sign_up),0}
                            end;
                        _ ->
                            sign_up_help(ZoneId,FactId,RoleInfo#cgw_role_info{position=?POS_NORMAL})
                    end;
                _ ->
                    {?ERRCODE(err601_no_zone_data),0}
            end;
        _->
            sign_up_help(ZoneId,FactId,RoleInfo#cgw_role_info{position=?POS_NORMAL})
    end.

%%取消援助
sign_up_help_cancel(ZoneId,FactId,RoleInfo)->
    GuildInfo = #cgw_guild_info{guild_id=FactId},
    #cgw_role_info{role_id = RoleId} = RoleInfo,
    case get_zone_guild_help_info(ZoneId) of
        Zone = #cgw_zone_guild_info{guild_list = GuildList} ->
            case lists:keytake(FactId, #cgw_guild_info.guild_id, GuildList) of
                {value, Guild = #cgw_guild_info{sign_ups = SignUps}, LessGs} ->
                    case lists:keytake(RoleId, #cgw_role_info.role_id, SignUps) of
                        {value,_,SignUps2} ->
                            Guild2 = Guild#cgw_guild_info{sign_ups = SignUps2},
                            Guild3 = update_guild_info(GuildInfo, Guild2),
                            NewGuildList = [Guild3 | LessGs],
                            NewZone = Zone#cgw_zone_guild_info{
                                guild_list = NewGuildList
                            },
                            put_zone_guild_help_info(NewZone),
                            {?SUCCESS,1};
                        true ->
                            {?ERRCODE(err601_have_sign_up),0}
                    end;
                 _ ->
                    {?ERRCODE(err601_no_zone_data),1}
            end;
        _->
            {?ERRCODE(err601_no_zone_data),0}
    end.

%%援助的都已普通身份参加
sign_up_help(ZoneId,FactId,RoleInfo) when FactId>0->
    GuildInfo = #cgw_guild_info{guild_id=FactId},
    #cgw_role_info{server_id=ServerId,role_id = RoleId} = RoleInfo,
    case get_zone_guild_help_info(ZoneId) of
        Zone = #cgw_zone_guild_info{guild_list = GuildList} ->
            case lists:keytake(FactId, #cgw_guild_info.guild_id, GuildList) of
                {value, Guild = #cgw_guild_info{sign_ups = SignUps}, LessGs} ->
                    case lists:keymember(RoleId, #cgw_role_info.role_id, SignUps) of
                        false ->
                            SignUps2 = lists:keysort(#cgw_role_info.power, [RoleInfo | SignUps]),
                            Len = length(SignUps2),
                            Max = data_cross_guild_war:get_config(sign_up_help_max),
                            {SignUps3, DeleteRole} = case Len > Max of
                                true ->
                                    [DeleteR | Tail] = SignUps2,
                                    {Tail, DeleteR};
                                false ->
                                    {SignUps2, false}
                            end,
                            Guild2 = Guild#cgw_guild_info{sign_ups = SignUps3},
                            Guild3 = update_guild_info(GuildInfo, Guild2),
                            NewGuildList = [Guild3 | LessGs],
                            NewZone = Zone#cgw_zone_guild_info{
                                guild_list = NewGuildList
                            },
                            put_zone_guild_help_info(NewZone),
                            case DeleteRole of
                                RoleInfo -> %% 战力不足
                                    {?ERRCODE(err601_power_lower),0};
                                DRole = #cgw_role_info{} -> %% 挤走了别人
                                    send_consolation(1,DRole),
                                    {?SUCCESS,1};
                                false -> %% 人数没达到上限
                                    {?SUCCESS,1}
                            end;
                        true ->
                            {?ERRCODE(err601_have_sign_up),0}
                    end;
                 _ ->
                    NewGuildList = [#cgw_guild_info{guild_id=FactId,fact_id = FactId, server_id = ServerId, zone_id = ZoneId,sign_ups = [RoleInfo]}|GuildList],
                    NewZone = #cgw_zone_guild_info{zone_id=ZoneId,guild_list = NewGuildList},
                    put_zone_guild_help_info(NewZone),
                    {?SUCCESS,1}
            end;
        _->
            {?ERRCODE(err601_no_zone_data),0}
    end;
sign_up_help(_,_,_)->
    {?ERRCODE(err601_no_zone_data),0}.


update_guild_info(NewGuild, Guild) ->
    #cgw_guild_info{
        guild_name = GuildName, guild_power = GuildPower
        ,chief_id = ChiefId, chief_name = ChiefName, chief_power = ChiefPower
    } = NewGuild,
    Guild#cgw_guild_info{
        guild_name = GuildName, guild_power = GuildPower
        ,chief_id = ChiefId, chief_name = ChiefName, chief_power = ChiefPower
    }.



%%发送落选邮件
send_consolation(Help,DelRole) ->
    #cgw_role_info{role_id = RoleId, server_id = ServerId} = DelRole,
    Args = [[RoleId], utext:get(6010009), utext:get(6010010), []],
    Mfa = {lib_mail_api, send_sys_mail, Args},
    clusters_center:apply_cast(ServerId, Mfa),
    {ok,Bin} = pt_601:write(60117,[Help]),
    Mfa1 = {lib_server_send, send_to_uid, [RoleId,Bin]},
    clusters_center:apply_cast(ServerId, Mfa1),
    ok.


%% ---------------------------------------------------------------------------
%% @doc 进入场景逻辑
enter_scene_do(ZoneId, FactId, RoleInfo) ->
    #cgw_role_info{role_id = RoleId} = RoleInfo,
    case have_signed_up(RoleId, ZoneId, FactId) of
        {true,GuildId} ->
            case ets:lookup(?CGW_GUILD_BATTLEFIELD_PID, GuildId) of
                [#cgw_guild_battlefield_info{pid = Pid}] ->
                    Msg = {enter_scene, RoleInfo, GuildId},
                    cross_guild_war_battle:cast(Pid, Msg),
                    ?SUCCESS;
                _ ->
                    ?ERRCODE(err601_no_battle_pid)
            end;
        {false, Reason} ->
            Reason
    end.


%%获取代表社团ID
get_guild_id(RoleId,ServerId,State)->
    #cgw_mgr_state{ser2zone=ZoneMap,ser2fact=FactMap}=State,
    GuildId = case maps:get(ServerId,ZoneMap,0) of
        ZoneId when ZoneId>0->
            case maps:get(ServerId,FactMap,0) of
                FactId when FactId>0->
                    case have_signed_up(RoleId, ZoneId, FactId) of
                        {true,V}->
                            V;
                        _->
                            0
                    end;
                _->
                    0
            end;
        _ ->
            0
    end,
    GuildId.

%% ---------------------------------------------------------------------------
%% @doc 是否已报名
check_sign(Process,RoleId, ZoneId, FactId) when Process =:= ?CGW_ST_PK->
    case have_signed_up(RoleId, ZoneId, FactId) of
        {false, _Reason} ->
            0;
        {true, _} ->
            1
    end;
check_sign(_Process,RoleId, ZoneId, FactId)->
    case have_signed_up(RoleId, ZoneId, FactId) of
        {false, _Reason} ->
            case get_zone_guild_help_info(ZoneId) of
                #cgw_zone_guild_info{guild_list = GuildList}->
                    case lists:keyfind(FactId,#cgw_guild_info.guild_id,GuildList) of
                        #cgw_guild_info{sign_ups=SignUps}->
                            case lists:keymember(RoleId, #cgw_role_info.role_id, SignUps) of
                                false ->
                                    0;
                                true ->
                                    1
                            end;
                        _->
                            0
                    end;
                _->
                    0
            end;
        _->
            1
    end.

have_signed_up(RoleId, ZoneId, FactId) ->
    case get_zone_guild_info(ZoneId) of
        #cgw_zone_guild_info{guild_list = GuildList} ->
            have_signed_up(RoleId,ZoneId,FactId,GuildList);
        _->
            {false, ?ERRCODE(err601_no_zone_data)}
    end.
have_signed_up(_RoleId,_ZoneId,_FactId,[])->
    {false, ?ERRCODE(err601_not_in_sign_up_list)};
have_signed_up(RoleId,ZoneId,FactId,[H|T])->
    #cgw_guild_info{guild_id=GuildId,fact_id=CurF,sign_ups=SignUps,help_ups=HelpUps} = H,
    case FactId =:= CurF of
        true->
            AllSigns = SignUps++HelpUps,
            case lists:keymember(RoleId, #cgw_role_info.role_id, AllSigns) of
                false ->
                    have_signed_up(RoleId,ZoneId,FactId,T);
                true ->
                    {true,GuildId}
            end;
        _->
            have_signed_up(RoleId,ZoneId,FactId,T)
    end.


%% @doc 打包分区参赛帮派信息
pack_zone_guilds(GuildList) ->
    pack_zone_guilds(GuildList, []).


pack_zone_guilds([], DataList) ->
    DataList;
pack_zone_guilds([Guild | T], DataList) ->
    #cgw_guild_info{
        server_id = ServerId, guild_id = GuildId,fact_id=FactId
        ,guild_name = Name, guild_power = Power,server_num = ServerNum
        ,chief_name=ChiefName
    } = Guild,
    Data = {ServerId, ServerNum,FactId,GuildId, Name, Power,ChiefName},
    pack_zone_guilds(T, [Data|DataList]).



%% ---------------------------------------------------------------------------
%% @doc 打包报名榜
pack_room_sign_up_roles(GuildList,FactId) ->
    NewGuildList = [Guild || Guild = #cgw_guild_info{fact_id = FactId2}<- GuildList, FactId =:= FactId2],
    case NewGuildList of
        [#cgw_guild_info{sign_ups = SignUps} | _] ->
            pack_sign_up_roles(SignUps, []);
        _ ->
            []
    end.

pack_sign_up_roles([], DataList) ->
    DataList;
pack_sign_up_roles([Role | T], DataList) ->
    #cgw_role_info{
        name = Name, power = Power, lev = Lev, vip = Vip, position = Position,sex=Sex,sup_vip=SVip
    } = Role,
    NewDataList = [{Name, Power, Sex, Lev, Vip,SVip,Position} | DataList],
    pack_sign_up_roles(T, NewDataList).



%% ---------------------------------------------------------------------------
%% @doc 应援帮派逻辑
support_guild_do(ZoneId, GuildId, SupportRole, Pid) ->
    case get_zone_guild_info(ZoneId) of
        Zone = #cgw_zone_guild_info{guild_list = GuildList} ->
            case lists:keytake(GuildId, #cgw_guild_info.guild_id, GuildList) of
                {value, Guild, LessGs} ->
                    case support_guild_done(SupportRole, Pid, Guild) of
                        Guild2 = #cgw_guild_info{} ->
                            NewGuildList = [Guild2 | LessGs],
                            NewZone = Zone#cgw_zone_guild_info{
                                guild_list = NewGuildList
                            },
                            put_zone_guild_info(NewZone),
                            ?SUCCESS;
                        Reason ->
                            Reason
                    end;
                _ ->
                    ?ERRCODE(err601_the_guild_is_no_exist)
            end;
        _ ->
            ?ERRCODE(err601_no_zone_data)
    end.

support_guild_done(SupportRole, RolePid, Guild) ->
    Request = {
        apply_call, ?APPLY_CALL_SAVE, cross_guild_war_api, support_guild_callback, []
    },
    %% 扣角色应援消耗，只等待2s，超时算失败
    try gen_server:call(RolePid, Request, 2000) of
        {false, Reason} -> %% 消耗不足
            Reason;
       {ok,{Name,RTimes,SerId,SerNum,CostList}} ->
            #cgw_guild_info{supports = Supports, support_num = SNum} = Guild,
            #cgw_support{role_id = RoleId} = SupportRole,
            NewSupports =
            case lists:keytake(RoleId, #cgw_support.role_id, Supports) of
                {value, SupportR = #cgw_support{num = Num}, LessSR} ->
                    NewSupportR = SupportR#cgw_support{num = Num + 1},
                    [NewSupportR | LessSR];
                _ ->
                    [SupportRole | Supports]
            end,
            cross_guild_war_api:log_cross_guild_war_support(RoleId,Name,RTimes,SerId,SerNum,CostList,Guild),
            Guild#cgw_guild_info{
                supports = NewSupports, support_num = SNum + 1
            }
    catch _A:_B -> %% 超时之类的
        ?FAIL
    end.



%% ---------------------------------------------------------------------------
%% @doc 领取占领城池奖励
get_city_award(ZoneId, CityId, MSerId, Pid, FactMap) ->
    case ets:lookup(?CGW_CITY_ETS, ZoneId) of
        [#cgw_zone_city_info{city_info = Cities}] ->
            KeyPos = #cgw_city_owner_info.city_id,
            case lists:keyfind(CityId, KeyPos, Cities) of
                #cgw_city_owner_info{server_id=CSerId} ->
                    MFactId = maps:get(MSerId,FactMap,0),
                    CFactId = maps:get(CSerId,FactMap,0),
                    case CFactId of
                        MFactId when MFactId > 0 ->
                            lib_player:apply_cast(
                                Pid, ?APPLY_CAST_SAVE, cross_guild_war_api
                                ,get_city_award_callback, [CityId]
                            ),
                            ok;
                        _->
                             ?ERRCODE(err601_donot_own_city)
                    end;
                _ ->
                    ?ERRCODE(err601_donot_own_city)
            end;
        _ ->
            ?ERRCODE(err601_donot_own_city)
    end.



%% ---------------------------------------------------------------------------
%% @doc 应援列表
send_support_list(ZoneId, Sid, SupportNum, LessFreeTimes, RoleId) ->
    case get_zone_guild_info(ZoneId) of
        #cgw_zone_guild_info{guild_list = GuildList} ->
            {DataList, MyTotalSupNum} = pack_support_list(RoleId,GuildList,[],0),
            SupportNum2 = case SupportNum of
                0 -> MyTotalSupNum;
                _ -> SupportNum
            end,
            ProData = [LessFreeTimes, SupportNum2, DataList],
            {ok, BinData} = pt_601:write(60103, ProData),
            lib_server_send:send_to_sid(Sid, BinData);
        _ ->
            ok
    end,
    ok.

pack_support_list(_RoleId, [], DataList, MyTotalSupNum) ->
    {DataList, MyTotalSupNum};
pack_support_list(RoleId, [Guild | T], DataList, MyTotalSupNum) ->
    #cgw_guild_info{
        server_id = ServerId, guild_name = GuildName,guild_power=GPower
        ,chief_name = ChiefName, support_num = SNum, supports = SupportList
        ,guild_id = GuildId, server_num = ServerNum,fact_id=FactId,chief_power=CPower
    } = Guild,
    MySupportNum = case lists:keyfind(RoleId, #cgw_support.role_id, SupportList) of
        #cgw_support{num = Num} -> Num;
        _ -> 0
    end,
    Data = {
        ServerId, ServerNum,FactId, GuildId, GuildName,GPower,ChiefName
        ,CPower,SNum, MySupportNum
    },
    NewDataList = [Data | DataList],
    NewMyTotalSupNum = MyTotalSupNum + MySupportNum,
    pack_support_list(RoleId, T, NewDataList, NewMyTotalSupNum).




%% ---------------------------------------------------------------------------
%% @doc 打包上次活动中城池占领信息
pack_city_info(ZoneId, ServerId, FactMap, AwardLog) ->
    case ets:lookup(?CGW_CITY_ETS, ZoneId) of
        [#cgw_zone_city_info{city_info = Cities}] ->
            CityList = pack_city_list(Cities, ServerId, FactMap, AwardLog, []),
            CityList;
        _ ->
            []
    end.

pack_city_list([], _MServerId, _FactMap, _AwardLog, DataList) ->
    DataList;
pack_city_list([City | T], MServerId, FactMap, AwardLog, DataList) ->
    #cgw_city_owner_info{
        city_id = CityId, server_id = ServerId
        ,guild_id = GuildId, guild_name = GuildName, guild_power = GuildPower
        ,chief_id = ChiefId, chief_name = ChiefName, chief_power = ChiefPower
        ,server_num = ServerNum
    } = City,
    MFact = maps:get(MServerId,FactMap,0),
    CFact = maps:get(ServerId,FactMap,0),
    IsAward = case CFact of
        MFact when MFact>0 ->
            case lists:member(CityId, AwardLog) of
                true ->
                    1;
                false ->
                    0
            end;
        _ ->
            2
    end,
    CityInfo = {
        CityId, ServerId, CFact, ServerNum, GuildId, GuildName, GuildPower
        ,ChiefId, ChiefName, ChiefPower, IsAward
    },
    NewDataList = [CityInfo | DataList],
    pack_city_list(T, MServerId, FactMap, AwardLog, NewDataList).



% %% ---------------------------------------------------------------------------
% %% @doc 合服处理
% -spec merge_server_do(ServerIdList) -> ok when
%     ServerIdList :: [ServerId :: integer()].
% %% ---------------------------------------------------------------------------
% merge_server_do([]) ->
%     ok;
% merge_server_do([ServerId | T]) ->
%     case ets:lookup(?CGW_ZONES_ETS, ServerId) of
%         [Zone = #cgw_zone_info{} | _] -> %% 有游戏服合服的分区需要取消帮战比赛
%             zone_cancel_act(Zone);
%         _ -> %% 不在分区中
%             ok
%     end,
%     merge_server_do(T).


% %% ---------------------------------------------------------------------------
% %% @doc 分区取消跨服帮战活动
% -spec zone_cancel_act(Zone) -> ok when
%     Zone        :: #cgw_zone_info{}.
% %% ---------------------------------------------------------------------------
% zone_cancel_act(Zone) ->
%     %% 删除分区信息
%     #cgw_zone_info{zone_id = ZoneId} = Zone,
%     ets:delete(?CGW_ZONES_ETS, ZoneId),
%     cross_guild_war_db:del_zone(ZoneId),

%     %% 根据分区详细数据进行应援返还
%     ServerSupportList = case get_zone_guild_info(ZoneId) of
%         #cgw_zone_guild_info{guild_list = GuildList} ->
%             SupportList = server_support_list(GuildList, []),
%             SupportList;
%         _ ->
%             []
%     end,
%     [
%         clusters_center:apply_cast(
%             ServerId, {?MODULE, return_support_local, [SerSupportList]}
%         ) || {ServerId, SerSupportList} <- ServerSupportList
%     ],

%     %% 清除分区详细数据
%     del_zone_guild_info(ZoneId),
%     cross_guild_war_db:del_guild_info(ZoneId),
%     ok.

% server_support_list([], SupportList) ->
%     SupportList;
% server_support_list([Guild | T], SupportList) ->
%     #cgw_guild_info{
%         supports = Supports, guild_id = GuildId, guild_name = GuildName
%         ,own_cities = Cities, server_id = ServerId
%     } = Guild,
%     Settlement = #support_settlement{
%         guild_id = GuildId, guild_name = GuildName, cities = Cities
%     },
%     %% 确保每个服都有数据，以便每个服发通知邮件
%     SupportList2 = case lists:keyfind(ServerId, 1, SupportList) of
%         false -> [{ServerId, []} | SupportList];
%         _ -> SupportList
%     end,
%     NewSupportList = guild_support_list(Settlement, Supports, SupportList2),
%     server_support_list(T, NewSupportList).

% %% 每个帮派的应援按ServerId分开
% guild_support_list(_Settlement, [], SupportList) ->
%     SupportList;
% guild_support_list(Settlement, [Support | T], SupportList) ->
%     #cgw_support{server_id = ServerId, role_id = RoleId, num = Num} = Support,
%     RoleSettlement = Settlement#support_settlement{role_id = RoleId, num = Num},
%     NewSupportList = case lists:keytake(ServerId, 1, SupportList) of
%         {value, {ServerId, ServerSuList}, LessList} ->
%             NewServerSuList = [RoleSettlement | ServerSuList],
%             [{ServerId, NewServerSuList} | LessList];
%         _ ->
%             [{ServerId, [RoleSettlement]} | SupportList]
%     end,
%     guild_support_list(Settlement, T, NewSupportList).

%%给入选外援发邮件
mail_all_helper()->
    ZoneList = get_zone_guild_info(),
    mail_all_helper(ZoneList,[]).

mail_all_helper([],[])->
    ok;
mail_all_helper([],Helpers)->
    SerHelpers = split_server_helper(Helpers,[]),
    do_mail_helper(SerHelpers);
mail_all_helper([H|T],Helpers)->
    #cgw_zone_guild_info{guild_list = GuildList}=H,
    Helpers1 = lists:foldl(fun(CgwG,Acc)->
        case CgwG of
            #cgw_guild_info{help_ups=Helpers0}->
                Acc++Helpers0;
            _->
                Acc
        end
    end,[],GuildList),
    mail_all_helper(T,Helpers1++Helpers).

split_server_helper([],SerHelpers)->
    SerHelpers;
split_server_helper([H|T],SerHelpers)->
    #cgw_role_info{role_id=Rid,server_id=ServerId} = H,
    NSerHelpers = case lists:keytake(ServerId, 1, SerHelpers) of
        {value, {ServerId, Helpers}, LessList} ->
            NHelpers = [Rid | Helpers],
            [{ServerId, NHelpers} | LessList];
        _ ->
            [{ServerId, [Rid]} | SerHelpers]
    end,
    split_server_helper(T,NSerHelpers).

do_mail_helper([])->
    ok;
do_mail_helper([{ServerId,Helpers}|T])->
    Args = [Helpers, utext:get(6010011), utext:get(6010012), []],
    Mfa = {lib_mail_api, send_sys_mail, Args},
    clusters_center:apply_cast(ServerId, Mfa),
    do_mail_helper(T).


%% ---------------------------------------------------------------------------
%% @doc 游戏服执行应援返还
-spec return_support_local(SupportList) -> ok when
    SupportList :: [#support_settlement{}].
%% ---------------------------------------------------------------------------
return_support_local(SupportList) ->
    erlang:spawn(fun() -> return_support_local_do(SupportList, 1) end),
    ?ERR("return_support_local", []),
    ok.

return_support_local_do([], _DoTimes) ->
    %% 退还所有应援之后，发送合服取消跨服帮战的全服邮件。
    %% 只给符合等级要求并且最近n天有上线的玩家发。
    Title = utext:get(6010003),
    Content = utext:get(6010004),
    ModuleLev = data_module:get_module_open_lv(601, 0),
    lib_mail_api:send_sys_mail_to_active(Title, Content, [], ModuleLev, 5),
    ok;
return_support_local_do([Support | T], DoTimes) ->
    #support_settlement{role_id = RoleId, num = Num} = Support,
    Title = utext:get(6010005),
    Content = utext:get(6010006),
    SideAward = data_cross_guild_war:get_config(surroundfield_encourage_rewards),
    Award = cross_guild_war_battle:n_times_award(SideAward, Num),
    lib_mail_api:send_sys_mail([RoleId], Title, Content, Award),
    case DoTimes rem 20 of
        0 -> timer:sleep(500);
        _ -> ok
    end,
    return_support_local_do(T, DoTimes + 1).


% %%把团战结果发回原服
% sync_notice_war_result([])->
%     ok;
% sync_notice_war_result([H|T])->
%     #cgw_guild_info{
%         guild_id = GuildId,
%         server_id = SerID
%     }=H,
%     clusters_center:apply_cast(SerID, cross_guild_war_local, sync_cgwar_room, [GuildId]),
%     sync_notice_war_result(T).

update_cgw_log(Result, Ser2Fast)->
    update_cgw_log(Result, Ser2Fast, utime:unixtime()).

update_cgw_log([],_,_)->
    ok;
update_cgw_log([H|T],Ser2Fast, Time)->
    #cgw_zone_city_info{zone_id = ZoneId, city_info = BattleResults}=H,
    FastInfo = collect_hold_city(Ser2Fast, BattleResults, []),
    F = fun({FacId, CityList}, CityInfo) ->
            CityNum = length(CityList),
            case ets:lookup(?ETS_FAC_LOG_RET, {ZoneId, FacId}) of
                [{_, ZoneFactionRanks}|_] ->
                    SortFun = fun(Guild1, Guild2) ->
                        Guild1#camp_war_guild.hurt > Guild2#camp_war_guild.hurt
                              end,
                    SortGuilds = lists:sort(SortFun, ZoneFactionRanks),
                    SubList = lists:sublist(SortGuilds, CityNum),
                    NCityInfo = change_city_info(CityList, SubList, CityInfo),
                    NCityInfo;
                _ -> CityInfo
            end
        end,
    BattleResults2 = lists:foldl(F, BattleResults, FastInfo),
    NewZone = case ets:lookup(?CGW_CITY_LOG_ETS, ZoneId) of
        [#cgw_zone_city_log{times_citys=Citys}|_] ->
            NewCitys0 = [#times_citys{time=Time,city_info=BattleResults2}|Citys],
            NewCitys1 = lists:keysort(#times_citys.time,NewCitys0),
            NewCitys2 = lists:reverse(NewCitys1),
            {NewCitys,DelCiTys} = ulists:split(3,NewCitys2),
            cross_guild_war_db:del_city_log(ZoneId,DelCiTys),
            cross_guild_war_db:save_city_log(ZoneId,Time,BattleResults2),
            #cgw_zone_city_log{zone_id=ZoneId,times_citys=NewCitys};
        _ ->
            NewCitys = [#times_citys{time=Time,city_info=BattleResults2}],
            cross_guild_war_db:save_city_log(ZoneId,Time,BattleResults2),
            #cgw_zone_city_log{zone_id=ZoneId,times_citys=NewCitys}
    end,
    ets:insert(?CGW_CITY_LOG_ETS,[NewZone]),
    update_cgw_log(T,Ser2Fast,Time).


pack_city_log([],CitysL)->
    CitysL;
pack_city_log([H|T],CitysL)->
    #times_citys{time=Time,city_info=Citys}=H,
    OwnersL = pack_own_city_log(Citys,[]),
    pack_city_log(T,[{Time,OwnersL}|CitysL]).


pack_own_city_log([],OwnersL)->
    OwnersL;
pack_own_city_log([H|T],OwnersL)->
    #cgw_city_owner_info{
        city_id = CityId
        ,server_num = SNum
        ,guild_name = GName
        ,chief_name = CName
        ,chief_info = ChiefInfo
    }=H,
    if
        is_record(ChiefInfo, rec_picture) ->
            pack_own_city_log(T,[{CityId,SNum,GName,CName,ChiefInfo}|OwnersL]);
        true ->
            pack_own_city_log(T,OwnersL)
    end.


do_add_svrs([],ZoneMap,FactMap)->
    [ZoneMap,FactMap];
do_add_svrs([{SerId,ZoneId,FactId}|T],ZoneMap,FactMap)->
    NZoneMap = maps:put(SerId,ZoneId,ZoneMap),
    NFactMap = maps:put(SerId,FactId,FactMap),
    do_add_svrs(T,NZoneMap,NFactMap).


%% 跨服分区开放及倒计时检查 - 跨服中心节点使用
%% -> {true, ZoneId}  开放
%%    false           禁止或倒计时阶段
zone_schedule_check_center(ServerId) ->
    case czone:get_scheduled_time(ServerId) of
        {_NoticeState, undefined, _, _} ->
            false;
        {false, ZoneId, _ScheduleTime, _NextStage} ->
            {true, ZoneId};
        {_NoticeState, ZoneId, 0, _NextStage}->
            {true, ZoneId};
        {true, _ZoneId, _ScheduledTime, _NextStage} ->
            false;
        _ ->
            false
    end.

%%过滤准备分区的服
filter_ready_rezone(GuildList)->
    filter_ready_rezone(GuildList,[],[]).

filter_ready_rezone([],GuildList,_)->
    GuildList;
filter_ready_rezone([H|T],GuildList,Filters)->
    #cgw_guild_info{server_id=ServerId}=H,
    case zone_schedule_check_center(ServerId) of
        false->
            case lists:member(ServerId,Filters) of
                true->%%不重复通知
                    filter_ready_rezone(T,GuildList,Filters);
                _->
                    clusters_center:apply_cast(ServerId, {?MODULE, notice_cancel_mail_local, []}),
                    filter_ready_rezone(T,GuildList,[ServerId|Filters])
            end;
        _->
            filter_ready_rezone(T,[H|GuildList],Filters)
    end.

%%发发取消邮件
notice_cancel_mail_local() ->
    Title = utext:get(6010013),
    Content = utext:get(6010014),
    ModuleLev = data_module:get_module_open_lv(601, 0),
    lib_mail_api:send_sys_mail_to_active(Title, Content, [], ModuleLev, 5).


%%选出霸主
choose_king(BattleResult)->
    Main = data_cross_guild_war:get_config(main_city),
    choose_king(Main,BattleResult).
choose_king(_Main,[])->
    ok;
choose_king(Main,[H|T])->
    #cgw_city_owner_info{
        city_id = City,
        server_id = SerId,
        chief_id = ChiefId
    }=H,
    case City =:= Main of
        true->
            clusters_center:apply_cast(SerId,{cross_guild_war_api,appoint_king,[ChiefId]});
        _->
            clusters_center:apply_cast(SerId,{cross_guild_war_api,quasi_appoint_king,[ChiefId]})
    end,
    choose_king(Main,T).


%%批量上报
batch_update_join([])->
    ok;
batch_update_join([{Zone,Guilds}|T])->
    batch_update_join_one(Zone,Guilds),
    batch_update_join(T).

batch_update_join_one(Zone,Guilds)->
    ServerInfo = #cgw_server_info{zone_id=Zone,guild_list=Guilds},
    ets:insert(?CGW_CAN_JOIN_ETS, ServerInfo).

%% 统计各阵营占领了多少城区
collect_hold_city(_Ser2Fast, [], FastInfo) ->
    FastInfo;
collect_hold_city(Ser2Fast, [H|T], FastInfo) ->
    #cgw_city_owner_info{
        city_id = City,
        server_id = SerId
    }=H,
    Fid = maps:get(SerId, Ser2Fast, 0),
    case lists:keyfind(Fid, 1, FastInfo) of
        {Fid, CityList} ->
            NFastInfo = lists:keystore(Fid, 1, FastInfo, {Fid, [City|CityList]}),
            collect_hold_city(Ser2Fast, T, NFastInfo);
        _ ->
            collect_hold_city(Ser2Fast, T, [{Fid, [City]}|FastInfo])
    end.

%% 修改城池占领信息
change_city_info([], _, CityInfo) ->
    CityInfo;
change_city_info([CityId|CityList], [], CityInfo) ->
    Info = lists:keyfind(CityId, #cgw_city_owner_info.city_id, CityInfo),
    NCityInfo = lists:delete(Info, CityInfo),
    change_city_info(CityList, [], NCityInfo);
change_city_info([CityId|CityList] = Cities, [Guild|GuildList], CityInfo) ->
    MainCity = data_cross_guild_war:get_config(main_city),
    case lists:member(MainCity, Cities) of
        true ->
            NCityInfo = modify_city_info(MainCity, Guild, CityInfo),
            change_city_info(lists:delete(MainCity, Cities), GuildList, NCityInfo);
        _ ->
            NCityInfo = modify_city_info(CityId, Guild, CityInfo),
            change_city_info(CityList, GuildList, NCityInfo)
    end.

modify_city_info(CityId, Guild, CityInfo) ->
    case lists:keyfind(CityId, #cgw_city_owner_info.city_id, CityInfo) of
        #cgw_city_owner_info{zone_id = ZoneId} ->
            #camp_war_guild{
                server_num = SerNum,
                server_id = SerId,
                chief_info = ChiefInfo,
                guild_id = GuildId,
                guild_name = GuildName,
                guild_power = GuildPower}
                = Guild,
            #rec_picture{id = ChiefId, name = ChiefName, power = Power} = ChiefInfo,
            CgwInfo = #cgw_city_owner_info{
                zone_id = ZoneId,
                city_id = CityId,
                server_num = SerNum,
                server_id = SerId,
                guild_name = GuildName,
                guild_id = GuildId,
                chief_name = ChiefName,
                chief_id = ChiefId,
                chief_power = Power,
                guild_power = GuildPower,
                chief_info = ChiefInfo},
            lists:keystore(CityId, #cgw_city_owner_info.city_id, CityInfo, CgwInfo);
        _ ->
            CityInfo
    end.