%% ---------------------------------
%% desc     :社团午间采集
%% module   :guild_collect_mgr.erl
%% author   :hh
%% time     :20/02/26
%% ---------------------------------

-module(guild_collect_mgr).

-behaviour(gen_server).

-include("guild_collect.hrl").
-include("common.hrl").
-include("def_module.hrl").
-include("predefine.hrl").
-include("activitycalen.hrl").
-include("scene.hrl").
-include("def_fun.hrl").
-include("battle.hrl").
-include("guild_labor.hrl").
-include ("figure.hrl").
-include ("errcode.hrl").
-include ("guild.hrl").
-include ("server.hrl").

%% gen_server callbacks
-export([
        init/1,
        handle_call/3,
        handle_cast/2,
        handle_info/2,
        terminate/2,
        code_change/3
    ]).

%% API
-export([
    start_link/0
    ,gm_act/1
    ,act_start/1
    ,act_end/1
    ,daily_clear/0
    ,get_collect_info/1
    ,collect_mon/8
    ,attack_mon/3
    ,kill_mon/3
    ,create_guild/1
    ,disband_guild/1
    ,get_role_collect_count/4
    ,get_guild_scene_collect_mon/2
    ,get_support_mon_data/4
    ,get_guild_collect_support_data/2
    ,response_collect_support/6
    ,cancel_collect_support/3
    ,collect_act_is_open/0
    ,role_act_end_refresh_count/1
    ]).

-define(SERVER, ?MODULE).

-ifdef(DEV_SERVER).
-define(GUILD_INIT_TIME, 5000).
-define(GUILD_COLLECT_ACT_CHECK_TIME, 10000).
-else.
-define(GUILD_INIT_TIME, 30000).
-define(GUILD_COLLECT_ACT_CHECK_TIME, 35000).
-endif.

-define(GUILD_COLLECT_GM_TIME, 610000).

%%%-------------------------------------------------------------------
%%% API Functions
%%%-------------------------------------------------------------------
start_link() ->
    gen_server:start_link({local, ?SERVER}, ?MODULE, {}, []).

act_start(ActSub) ->
    act_start(ActSub, ?GUILD_COLLECT_ACT).

act_start(ActSub, StartType) ->
    gen_server:cast(?SERVER, {act_start, ActSub, StartType}).

act_end(ActSub) ->
    act_end(ActSub, ?GUILD_COLLECT_ACT).

act_end(ActSub, EndType) ->
    gen_server:cast(?SERVER, {act_end, ActSub, EndType}).

get_collect_info(Sid) ->
    gen_server:cast(?SERVER, {get_collect_info, Sid}).

collect_mon(CollectId, ConfigId, CreateKey, X, Y, SceneId, ScenePoolId, CopyId) ->
    gen_server:cast(?SERVER, {collect_mon, CollectId, ConfigId, CreateKey, X, Y, SceneId, ScenePoolId, CopyId}).

attack_mon(Atter, Minfo, Hurt) ->
    gen_server:cast(?SERVER, {attack_mon, Atter, Minfo, Hurt}).

kill_mon(Minfo, AtterId, GuildId) ->
    gen_server:cast(?SERVER, {kill_mon, Minfo, AtterId, GuildId}).

create_guild(GuildId) ->
    gen_server:cast(?SERVER, {create_guild, GuildId}).

disband_guild(GuildId) ->
    gen_server:cast(?SERVER, {disband_guild, GuildId}).

get_role_collect_count(Sid, DailyCount, CollectCount, LastCollectTime) ->
    gen_server:cast(?SERVER, {get_role_collect_count, Sid, DailyCount, CollectCount, LastCollectTime}).

get_guild_scene_collect_mon(Sid, GuildId) ->
    gen_server:cast(?SERVER, {get_guild_scene_collect_mon, Sid, GuildId}).

get_support_mon_data(Sid, GuildId, SupportSid, EnterRet) ->
    gen_server:cast(?SERVER, {get_support_mon_data, Sid, GuildId, SupportSid, EnterRet}).

%% 申请协助(废弃)
response_collect_support(Sid, RoleId, Pid, GuildId, SupportSid, IsGuildScene) ->
    gen_server:cast(?SERVER, {response_collect_support, Sid, RoleId, Pid, GuildId, SupportSid, IsGuildScene}).

%% 取消协助(废弃)
cancel_collect_support(Sid, RoleId, GuildId) ->
    gen_server:cast(?SERVER, {cancel_collect_support, Sid, RoleId, GuildId}).

daily_clear() ->
    gen_server:cast(?SERVER, {daily_clear}).

collect_act_is_open() ->
    gen_server:call(?SERVER, {collect_act_is_open}).


gm_act(Sign) ->
    if Sign == ?GUILD_COLLECT_CLOSED ->
            act_end(_ActSub = 1, ?GUILD_COLLECT_GM);
        Sign == ?GUILD_COLLECT_OPEN ->
            act_start(_ActSub = 1, ?GUILD_COLLECT_GM);
        true ->
            skip
    end.

%% 获取社团采集协助信息(废弃)
get_guild_collect_support_data(RoleId, GuildId) ->
    case ets:lookup(?ETS_GUILD_COLLECT_ASSIST, GuildId) of
        [AssistRec = #guild_collect_support_info{}|_] -> ok;
        _ -> AssistRec = #guild_collect_support_info{}
    end,
    #guild_collect_support_info{role_maps = RoleMaps, support_maps = AssistMaps} = AssistRec,
    AssistList = pack_guild_collect_assist_list(AssistMaps),
    {_OwnSids, HelpSid} = maps:get(RoleId, RoleMaps, {0, 0}),
    [HelpSid, AssistList].

pack_guild_collect_assist_list(AssistMaps) ->
    [BossId|_] = data_guild_collect:get_kv(invade_mon),
    AssistList = lists:foldl(fun({AssistId, AssistInstance}, Acc) ->
        #support_instance{
            sid = AssistId,
            req_role = ReqRoleId,
            create_time = CreateTime
        } = AssistInstance,
        Figure = lib_role:get_role_figure(ReqRoleId),
        [{AssistId, 2, Figure, 0, BossId, CreateTime}|Acc]
    end, [], maps:to_list(AssistMaps)),
    AssistList.

%%%-------------------------------------------------------------------
%%% Callback Functions
%%%-------------------------------------------------------------------
init(_Args) ->
    Ref  = util:send_after(undefined, ?GUILD_INIT_TIME, self(), {'get_guild_after_init'}),
    Ref1 = util:send_after(undefined, ?GUILD_COLLECT_ACT_CHECK_TIME, self(), {'guild_collect_act_check'}),
    NewCollectStatus = maps:put(?GUILD_INIT_REF, Ref, #{}),
    NewCollectStatus1 = maps:put(?GUILD_COLLECT_ACT_REF, Ref1, NewCollectStatus),
    Season = get_collect_act_season(?MOD_GUILD_COLLECT, 0, 1, ?GUILD_COLLECT_ACT),
    %% 社团采集协助数据
    % ets:new(?ETS_GUILD_COLLECT_ASSIST,
    %    [{keypos, #guild_collect_support_info.guild_id}, named_table, public, set, {read_concurrency, true}]
    % ),
    {ok, #guild_collect_state{season = Season, collect_status = NewCollectStatus1}}.


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) ->
    ?ERR("~p terminate: ~n reason: ~p", [?MODULE, _Reason]),
    ok.

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

%%%-------------------------------------------------------------------
%%% Internal Functions
%%%-------------------------------------------------------------------

do_handle_call({collect_act_is_open}, _From, State) ->
    #guild_collect_state{status = Status} = State,
    Ret = if Status == ?GUILD_COLLECT_OPEN -> true;
        true -> false
    end,
    {reply, Ret, State};

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

do_handle_cast({act_start, ActSub, StartType}, State) ->
    #guild_collect_state{guild_list = GuildList, collect_status = Map} = State,
    NewState  = init_collect_act(ActSub, StartType, State),
    Season    = get_collect_act_season(?MOD_GUILD_COLLECT, 0, ActSub, StartType),
    #guild_collect_state{end_time = ETime, status = Status} = NewState1 = NewState#guild_collect_state{guild_list = GuildList, season = Season, collect_status = Map},
    % NewState2 = lib_guild_collect:act_start_logic(NewState1),
    lib_activitycalen_api:activity_end_clean_record(?MOD_GUILD_COLLECT, 5),
    lib_guild_collect:notice_collect_act(Status, Season),
    EndRef = if StartType == ?GUILD_COLLECT_GM ->
            Now = utime:unixtime(), LastTime = ETime - Now,
            erlang:send_after(LastTime*1000, self(), {act_end, ActSub, StartType});
        true -> undefined
    end,
    InitMonRef = erlang:send_after(?INIT_MON_DELAY, self(), {init_mon_delay}),
    NewCollectStatus = maps:put(StartType, EndRef, NewState1#guild_collect_state.collect_status),
    NewCollectStatus1 = maps:put(init_mon_delay, InitMonRef, NewCollectStatus),
    lib_chat:send_TV({all}, ?MOD_GUILD_COLLECT, 1, []),
    lib_chat:send_TV({all}, ?MOD_GUILD_COLLECT, 5, []),
    GuildScene = lib_guild_api:get_guild_scene(),
    {noreply, NewState1#guild_collect_state{collect_status = NewCollectStatus1, guild_scene = GuildScene}};

do_handle_cast({act_end, ActSub, EndType}, State) ->
    % ?INFO_TTY("act end ~p", [EndType]),
    #guild_collect_state{guild_list = GuildList, collect_status = CollectStatus, season = Season, ref = Ref, guild_scene = GuildScene} = State,
    NewSeason = ?IF(EndType == ?GUILD_COLLECT_ACT, Season+1, get_collect_act_season(?MOD_GUILD_COLLECT, 0, ActSub, EndType)),
    lib_guild_collect:notice_collect_act(?GUILD_COLLECT_CLOSED, Season),
    %% 处理协助数据
    guild_support_collect:collect_act_end(GuildList),
    % SceneId = data_guild:get(guild_scene),
    GuildPoolList = calc_guild_pool(GuildList),
    act_end_clear_scene(GuildScene, GuildPoolList),
    act_end_guild_seal(GuildScene, GuildPoolList),
    % ?ERR("~p ~p ~p", [GuildScene, GuildList, GuildPoolList]),
    EndType == ?GUILD_COLLECT_GM andalso begin
        OldRef = maps:get(EndType, CollectStatus, undefined),
        util:cancel_timer(OldRef)
    end,
    NewCollectStatus = maps:put(?GUILD_INVADE_MON_HURT, [], CollectStatus),
    util:cancel_timer(Ref),
    lib_activitycalen_api:activity_end_clean_record(?MOD_GUILD_COLLECT, 5),
    NewState = State#guild_collect_state{
        status = ?GUILD_COLLECT_CLOSED, start_time = 0, end_time = 0,
        season = NewSeason,
        guild_scene = 0,
        collect_status = NewCollectStatus,
        wave = 0,
        ref = undefined,
        guild_mon_data = [],
        support_mon_data = []},
    % ets:delete_all_objects(?ETS_GUILD_COLLECT_ASSIST),
    {noreply, NewState};

do_handle_cast({get_collect_info, Sid}, State) ->
    #guild_collect_state{status = Status, season = Season, end_time = EndTime} = State,
    {ok, BinData} = pt_408:write(40801, [Status, EndTime, Season]),
    lib_server_send:send_to_sid(Sid, BinData),
    {noreply, State};


do_handle_cast({collect_mon, CollectId, ConfigId, CreateKey, X, Y, SceneId, ScenePoolId, CopyId}, State) ->
    #guild_collect_state{
        end_time = EndTime, index = Index,
        guild_mon_data= GuildMonData, support_hurt_data = SupportData,
        guild_scene = GuildScene} = State,
    Now = utime:unixtime(),
    NewState = if Now >= EndTime -> %% 已过了活动时间不生成了
            State;
        true ->
            NewGuildMonData = lib_guild_collect:guild_mon_collected(CreateKey, GuildMonData),
            {RandX, RandY} = get_invade_mon_xy(GuildScene, X, Y),
            %% 生成入侵怪
            {IsCall, NewIndex} =
             lib_guild_collect:create_invade_mon(CollectId, SceneId, ScenePoolId, CopyId, RandX, RandY, ConfigId, Index),
            IsCall andalso begin
                % lib_chat:send_TV({guild, GuildId}, ?MOD_GUILD_COLLECT, 2, [Name, CollectId]),
                %% 通知前端完成采集操作
                {ok, BinData} = pt_408:write(40805, []),
                lib_server_send:send_to_uid(CollectId, BinData)
            end,
            %% 处理协助相关的
            NewSupportData = lib_guild_collect:update_support_data(SupportData, CollectId, Index, IsCall),
            State#guild_collect_state{
                guild_mon_data = NewGuildMonData, support_hurt_data = NewSupportData, index = NewIndex}
    end,
    %% 成就
    lib_achievement_api:async_event(CollectId, lib_achievement_api, guild_collect_event, 1),
    %% 战团任务
    lib_role_legion:trigger_task(CollectId, ?MOD_GUILD_COLLECT, 0),
    lib_guild_labor:task_active(CollectId, ?GTASK_TYPE_COLLECT),
    %% 更新收集者数据
    % lib_player:apply_cast(CollectId, ?APPLY_CAST_SAVE, lib_guild_collect, role_update_collect_time, [StartTime, EndTime]),
    %% 日常活跃任务
    lib_activitycalen_api:role_success_end_activity(CollectId, ?MOD_GUILD_COLLECT, 0),
    {noreply, NewState};

do_handle_cast({attack_mon, Atter, Minfo, Hurt}, State) ->
    #guild_collect_state{collect_status = CollectStatus, support_hurt_data = SupportData} = State,
    #scene_object{id = MonId, mon = #scene_mon{create_key = {?GUILD_COLLECT_INVADE_MON, CreateId, CreateIndex}}} = Minfo,
    #battle_return_atter{id = AtterId, support_id = SupportId, guild_id = _GuildId} = Atter,
    HurtList = maps:get(?GUILD_INVADE_MON_HURT, CollectStatus, []),
    case lists:keyfind(MonId, 1, HurtList) of
        {_, HurtRoles} ->
            NewHurtRoles = case lists:member(AtterId, HurtRoles) of
                true -> HurtRoles;
                _    -> [AtterId|HurtRoles]
            end,
            NewHurtList = lists:keystore(MonId, 1, HurtList, {MonId, NewHurtRoles}),
            NewCollectStatus = maps:put(?GUILD_INVADE_MON_HURT, NewHurtList, CollectStatus);
        _ ->
            NewHurtList = lists:keystore(MonId, 1, HurtList, {MonId, [AtterId]}),
            NewCollectStatus = maps:put(?GUILD_INVADE_MON_HURT, NewHurtList, CollectStatus)
    end,
    NewSupportData = lib_guild_collect:refresh_support_hurt_data(CreateId, CreateIndex, AtterId, SupportId, Hurt, SupportData),
    NewState = State#guild_collect_state{
        collect_status = NewCollectStatus, support_hurt_data = NewSupportData
    },
    {noreply, NewState};

do_handle_cast({kill_mon, Minfo, AtterId, GuildId}, State) ->
    #guild_collect_state{collect_status = CollectStatus} = State,
    #scene_object{id = MonId, mon = #scene_mon{create_key = {?GUILD_COLLECT_INVADE_MON, CreateId, _Index}}} = Minfo,
    mod_guild_support:apply_cast(guild_support_collect, finish_support, [GuildId, CreateId, MonId]),
    case maps:get(?GUILD_INVADE_MON_HURT, CollectStatus, []) of
        HurtList = [_|_] ->
            case lists:keyfind(MonId, 1, HurtList) of
                {_, HurtRoles = [_|_]} ->
                    if AtterId =/= CreateId ->
                            NewHurtRoles = case lists:member(AtterId, HurtRoles) of
                                true -> HurtRoles;
                                _    -> [AtterId|HurtRoles]
                            end;
                        true ->
                            NewHurtRoles = HurtRoles
                    end,
                    [lib_guild_collect:send_help_reward(HurtRoleId)|| HurtRoleId <- NewHurtRoles],
                    NewHurtList = lists:keydelete(MonId, 1, HurtList);
                _ ->
                    NewHurtList = lists:keydelete(MonId, 1, HurtList)
            end,
            NewCollectStatus = maps:put(?GUILD_INVADE_MON_HURT, NewHurtList, CollectStatus),
            NewCollectStatus;
        _ ->
            NewCollectStatus = CollectStatus
    end,
%%    case ets:lookup(?ETS_GUILD_COLLECT_ASSIST, GuildId) of
%%        [GuildSupportInfo = #guild_collect_support_info{}|_] ->
%%            #guild_collect_support_info{support_maps = SupportMaps, role_maps = RoleMaps} = GuildSupportInfo,
%%            case maps:get(SupportSid, SupportMaps, false) of
%%                SupportInstance = #support_instance{} ->
%%                    lib_guild_collect:finish_collect_support(GuildId, SupportInstance),
%%                    NewSupportMaps = maps:remove(SupportSid, SupportMaps);
%%                _ ->
%%                    NewSupportMaps = SupportMaps
%%            end,
%%            {OwnSupportSids, _HelpSid} = maps:get(CreateId, RoleMaps, {[], 0}),
%%            NewOwnSupportSids = lists:delete(SupportSid, OwnSupportSids),
%%            NewRoleMaps = maps:put(CreateId, {NewOwnSupportSids, _HelpSid}, RoleMaps),
%%            NewGuildSupportInfo = GuildSupportInfo#guild_collect_support_info{support_maps = NewSupportMaps, role_maps = NewRoleMaps},
%%            ets:insert(?ETS_GUILD_COLLECT_ASSIST, NewGuildSupportInfo);
%%        _ ->
%%            skip
%%    end,
    NewState = State#guild_collect_state{collect_status = NewCollectStatus},
    NewState1 = lib_guild_collect:refresh_support_mon_data(NewState, CreateId, MonId),
    lib_guild_collect:send_invade_call_reward(CreateId),
    {noreply, NewState1};


do_handle_cast({create_guild, GuildId}, State) ->
    #guild_collect_state{guild_list = GuildList} = State,
    case lists:member(GuildId, GuildList) of
        false ->
            NewGuildList = [GuildId|GuildList],
            NewState = State#guild_collect_state{guild_list = NewGuildList};
        _ ->
            NewState = State
    end,
    {noreply, NewState};

do_handle_cast({disband_guild, GuildId}, State) ->
    #guild_collect_state{guild_list = GuildList, status = Status, guild_mon_data = GuildMonData, guild_scene = GuildScene} = State,
    NewGuildList = lists:delete(GuildId, GuildList),
    % GuildScene = data_guild:get(guild_scene),
    Status == ?GUILD_COLLECT_OPEN andalso GuildScene =/= 0 andalso lib_mon:clear_scene_mon(GuildScene, ?GUILD_REM_POOL(GuildId), GuildId, 1),
    NewGuildMonData = lists:keydelete(GuildId, 1, GuildMonData),
    NewState = State#guild_collect_state{guild_list = NewGuildList, guild_mon_data = NewGuildMonData},
    {noreply, NewState};

do_handle_cast({get_role_collect_count, Sid, DailyCount, CollectCount, LastCollectTime}, State) ->
    #guild_collect_state{start_time = StartTime, end_time = EndTime} = State,
    if LastCollectTime == 0 ->
            {ok, BinData} = pt_408:write(40803, [CollectCount, DailyCount]),
            lib_server_send:send_to_sid(Sid, BinData);
        true ->
            if LastCollectTime >= StartTime andalso LastCollectTime =< EndTime ->
                    {ok, BinData} = pt_408:write(40803, [CollectCount, DailyCount]),
                    lib_server_send:send_to_sid(Sid, BinData);
                true ->
                    {ok, BinData} = pt_408:write(40803, [0, DailyCount]),
                    lib_server_send:send_to_sid(Sid, BinData)
            end
    end,
    {noreply, State};

do_handle_cast({daily_clear}, State) ->
    {noreply, State#guild_collect_state{season = 1}};

do_handle_cast({get_guild_scene_collect_mon, Sid, GuildId}, State) ->
    #guild_collect_state{guild_mon_data = GuildMonData} = State,
    case lists:keyfind(GuildId, 1, GuildMonData) of
        {_, MonData} ->
            MonLen = length(MonData),
            lib_server_send:send_to_sid(Sid, pt_408, 40806, [MonLen]);
        _ ->
            lib_server_send:send_to_sid(Sid, pt_408, 40806, [0])
    end,
    {noreply, State};

do_handle_cast({mon_born_handle, CreateId, MonId, MonCfgId}, State) ->
    %% 发送协助
    lib_player:apply_cast(CreateId, ?APPLY_CAST_STATUS, lib_guild_support_mod, ask_for_support,
        [?MOD_GUILD_COLLECT, 0, {MonId, MonCfgId}]
    ),
    {noreply, State};
%%    #guild_collect_state{support_mon_data = SupportMons} = State,
%%    NewSupportMons =
%%    case lists:keyfind(CreateId, 1, SupportMons) of
%%        {_, Mons} ->
%%            lists:keystore(CreateId, 1, SupportMons, {CreateId, [MonId|Mons]});
%%        _ ->
%%            lists:keystore(CreateId, 1, SupportMons, {CreateId, [MonId]})
%%    end,
%%    #figure{guild_id = GuildId} = lib_role:get_role_figure(CreateId),
%%    case ets:lookup(?ETS_GUILD_COLLECT_ASSIST, GuildId) of
%%        [GuildSupportInfo = #guild_collect_support_info{support_maps = SupportMaps}|_] ->
%%            case maps:get(SupportSid, SupportMaps, false) of
%%                SupportInstance = #support_instance{} ->
%%                    NewSupportInstance = SupportInstance#support_instance{boss_id = MonId},
%%                    NewSupportMaps = maps:put(SupportSid, NewSupportInstance, SupportMaps),
%%                    NewGuildSupportInfo = GuildSupportInfo#guild_collect_support_info{support_maps = NewSupportMaps},
%%                    ets:insert(?ETS_GUILD_COLLECT_ASSIST, NewGuildSupportInfo);
%%                _ ->
%%                    skip
%%            end;
%%        _ -> skip
%%    end,
%%    NewState = State#guild_collect_state{support_mon_data = NewSupportMons},
%%    {noreply, NewState};

do_handle_cast({hp_change_handle, Minfo, MonAtter}, State) ->
    #guild_collect_state{support_hurt_data = SupportData} = State,
    #scene_object{mon = #scene_mon{mid = Mid, create_key = CreateKey}} = Minfo,
    #mon_atter{id = AtterId, name = AtterName, support_id = SupportId, hurt = Hurt} = MonAtter,
    {?GUILD_COLLECT_INVADE_MON, CollectId, Index} = CreateKey,
    if
        SupportId > 0 andalso CollectId == SupportId ->
            case lists:keyfind(SupportId, 1, SupportData) of
                {_, HurtList} ->
                    NewHurtList =
                    case lists:keyfind(AtterId, 1, HurtList) of
                        {_, OldHurt} ->
                            SuppporterHurt = [Mid, Index, AtterId, AtterName, round(OldHurt+Hurt)],
                            lists:keystore(AtterId, 1, HurtList, {AtterId, round(OldHurt+Hurt)});
                        _ ->
                            SuppporterHurt = [Mid, Index, AtterId, AtterName, round(Hurt)],
                            lists:keystore(AtterId, 1, HurtList, {AtterId, round(Hurt)})
                    end,
                    NewSupportData = lists:keystore(SupportId, 1, SupportData, {SupportId, NewHurtList});
                _ ->
                    SuppporterHurt = [Mid, Index, AtterId, AtterName, round(Hurt)],
                    NewHurtList = [{AtterId, round(Hurt)}],
                    NewSupportData = lists:keystore(SupportId, 1, SupportData, {SupportId, NewHurtList})
            end,
            send_to_suppporter(SupportId, SuppporterHurt);
        true ->
            NewSupportData = SupportData
    end,
    NewState = State#guild_collect_state{support_hurt_data = NewSupportData},
    {noreply, NewState};

do_handle_cast({get_support_mon_data, _Sid, _GuildId, _SupportSid, _EnterRet}, State) ->
%%    case ets:lookup(?ETS_GUILD_COLLECT_ASSIST, GuildId) of
%%        [#guild_collect_support_info{support_maps = SupportMaps}|_] ->
%%            #support_instance{boss_id = BossId} = maps:get(SupportSid, SupportMaps, #support_instance{}),
%%            lib_server_send:send_to_sid(Sid, pt_408, 40808, [EnterRet, BossId]);
%%        _A ->
%%            lib_server_send:send_to_sid(Sid, pt_408, 40808, [EnterRet, 0])
%%    end,
    {noreply, State};

do_handle_cast({response_collect_support, _Sid, _RoleId, _Pid, _GuildId, _SupportSid, _IsGuildScene}, State) ->
%%    case ets:lookup(?ETS_GUILD_COLLECT_ASSIST, GuildId) of
%%        [GuildSupportInfo|_] ->
%%            #guild_collect_support_info{role_maps = RoleMaps, support_maps = SupportMaps} = GuildSupportInfo,
%%            {OwnSupportSids, HelpSid} = maps:get(RoleId, RoleMaps, {[], 0}),
%%            if HelpSid =/= 0 ->
%%                    lib_server_send:send_to_sid(Sid, pt_408, 40809, [?ERRCODE(err400_is_supporting), SupportSid]);
%%                true ->
%%                    case maps:get(SupportSid, SupportMaps, false) of
%%                        SupportInstance = #support_instance{sid = SupportSid, res_roles = ResRoles} ->
%%                            #base_guild_support{support_limit = NumLimit} = data_guild:get_guild_support_cfg(2),
%%                            SupportNumLimit = length(ResRoles) >= NumLimit,
%%                            if
%%                                SupportNumLimit ->
%%                                    lib_server_send:send_to_sid(Sid, pt_408, 40809, [?ERRCODE(err400_support_role_num_max), SupportSid]),
%%                                    skip;
%%                                true ->
%%                                    case lists:member(RoleId, ResRoles) of
%%                                        true -> NewSupportMaps = SupportMaps;
%%                                        _    ->
%%                                            NewSupportMaps = maps:put(SupportSid, SupportInstance#support_instance{res_roles = [RoleId|ResRoles]}, SupportMaps)
%%                                    end,
%%                                    NewRoleMaps = maps:put(RoleId, {OwnSupportSids, SupportSid}, RoleMaps),
%%                                    NewGuildSupportInfo = GuildSupportInfo#guild_collect_support_info{
%%                                        role_maps = NewRoleMaps, support_maps = NewSupportMaps},
%%                                    ets:insert(?ETS_GUILD_COLLECT_ASSIST, NewGuildSupportInfo),
%%                                    lib_server_send:send_to_sid(Sid, pt_408, 40809, [?SUCCESS, SupportSid]),
%%                                    if
%%                                        not IsGuildScene ->
%%                                            gen_server:cast(Pid, {'SOCKET_EVENT', Sid, pt_400, pp_guild, 40044, <<>>});
%%                                        true ->
%%                                            skip
%%                                    end
%%                            end;
%%                        _ -> skip
%%                    end
%%            end;
%%        _ ->
%%            lib_server_send:send_to_sid(Sid, pt_408, 40809, [?ERRCODE(data_error), SupportSid])
%%    end,
    {noreply, State};

do_handle_cast({cancel_collect_support, _Sid, _RoleId, _GuildId}, State) ->
%%    case ets:lookup(?ETS_GUILD_COLLECT_ASSIST, GuildId) of
%%        [GuildSupportInfo|_] ->
%%            #guild_collect_support_info{role_maps = RoleMaps, support_maps = SupportMaps} = GuildSupportInfo,
%%            {OwnSupportSids, HelpSid} = maps:get(RoleId, RoleMaps, {[], 0}),
%%            NewRoleMaps = maps:put(RoleId, {OwnSupportSids, 0}, RoleMaps),
%%            case maps:get(HelpSid, SupportMaps, false) of
%%                SupportInstance = #support_instance{sid = HelpSid, res_roles = ResRoles} ->
%%                    NewResRoles = lists:delete(RoleId, ResRoles),
%%                    NewSupportMaps = maps:put(HelpSid, SupportInstance#support_instance{res_roles = NewResRoles}, SupportMaps);
%%                _ ->
%%                    NewSupportMaps = SupportMaps
%%            end,
%%            NewGuildSupportInfo = GuildSupportInfo#guild_collect_support_info{role_maps = NewRoleMaps, support_maps = NewSupportMaps},
%%            ets:insert(?ETS_GUILD_COLLECT_ASSIST, NewGuildSupportInfo),
%%            lib_server_send:send_to_sid(Sid, pt_408, 40810, [?SUCCESS]);
%%        _ ->
%%            lib_server_send:send_to_sid(Sid, pt_408, 40810, [?ERRCODE(data_error)])
%%    end,
    {noreply, State};

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

do_handle_info({'get_guild_after_init'}, State) ->
    #guild_collect_state{collect_status = CollectStatus} = State,
    OldRef = maps:get(?GUILD_INIT_REF, CollectStatus, undefined),
    util:cancel_timer(OldRef),
    lib_guild_api:get_all_guild_ids(self()),
    NewCollectStatus = maps:put(?GUILD_INIT_REF, undefined, CollectStatus),
    {noreply, State#guild_collect_state{collect_status = NewCollectStatus}};

do_handle_info({'guild_collect_act_check'}, State) ->
    #guild_collect_state{collect_status = CollectStatus} = State,
    OldRef = maps:get(?GUILD_COLLECT_ACT_REF, CollectStatus, undefined),
    util:cancel_timer(OldRef),
    NewCollectStatus = maps:put(?GUILD_COLLECT_ACT_REF, undefined, CollectStatus),
    case lib_activitycalen_api:get_first_enabled_ac_id(?MOD_GUILD_COLLECT, 0) of
        {ok, ActId} ->
            State1 = init_collect_act(ActId, State),
            Season = get_collect_act_season(?MOD_GUILD_COLLECT, 0, ActId, ?GUILD_COLLECT_ACT),
            State2 = State1#guild_collect_state{season = Season},
            {noreply, NewState0} = do_handle_cast({act_start, ActId, ?GUILD_COLLECT_ACT}, State2),
            NewState = NewState0#guild_collect_state{collect_status = NewCollectStatus};
        _ ->
            NewState = State#guild_collect_state{collect_status = NewCollectStatus}
    end,
    {noreply, NewState};

do_handle_info({'all_guild_ids', GuildIds}, State) ->
    % ?INFO_TTY("~p", [GuildIds]),
    NewState = State#guild_collect_state{guild_list = GuildIds},
    {noreply, NewState};

do_handle_info(Msg = {act_end, _ActSub, _StartType}, State) ->
    {noreply, NewState} = do_handle_cast(Msg, State),
    {noreply, NewState};

do_handle_info({'interval_refresh_mon'}, State) ->
    NewState = lib_guild_collect:interval_refresh_mon(State),
    {noreply, NewState};

do_handle_info({init_mon_delay}, State) ->
    NewState = lib_guild_collect:act_start_logic(State),
    {noreply, NewState};

do_handle_info({update_collector_data, Goods, RoleId}, State) ->
    #guild_collect_state{start_time = StartTime, end_time = EndTime} = State,
    %% 更新收集者数据
    lib_player:apply_cast(RoleId, ?APPLY_CAST_SAVE, lib_guild_collect, role_update_collect_time, [StartTime, EndTime, Goods]),
    {noreply, State};

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


init_collect_act(ActId, State) ->
    init_collect_act(ActId, ?GUILD_COLLECT_ACT, State).

init_collect_act(ActId, StartType, State) ->
    case data_activitycalen:get_ac(?MOD_GUILD_COLLECT, 0, ActId) of
        #base_ac{time_region = TimeRegion} ->
            Now = utime:unixtime(),
            case get_end_time(TimeRegion, Now) of
                [{StartTime, EndTime}|_] ->
                    State#guild_collect_state{
                        status = ?GUILD_COLLECT_OPEN,
                        start_time = StartTime,
                        end_time = EndTime};
                _ ->
                    LastTime = get_gm_last_time(TimeRegion),
                    if StartType == ?GUILD_COLLECT_GM ->
                            State#guild_collect_state{
                                status = ?GUILD_COLLECT_OPEN,
                                start_time = Now,
                                end_time = Now + LastTime};
                        true ->
                            State
                    end
            end;
        _ ->
            State
    end.

% lib_activitycalen_mod:get_ac_end_time
get_end_time(TimeRegion, Now) ->
    {{Year, Month, Day}, _} = utime:localtime(),
    case lists:filter(fun({{StartHour, StartMin}, {EndHour, EndMin}}) ->
        StartTimeX = utime:unixtime({{Year, Month, Day}, {StartHour, StartMin, 0}}),
        EndTimeX   = utime:unixtime({{Year, Month, Day}, {EndHour, EndMin, 0}}),
        Now >= StartTimeX andalso Now =< EndTimeX
     end, TimeRegion) of
        [{{SH, SM},{EH, EM}}|_] ->
            StartTime = utime:unixtime({{Year, Month, Day}, {SH, SM, 0}}),
            EndTime   = utime:unixtime({{Year, Month, Day}, {EH, EM, 0}}),
            [{StartTime, EndTime}];
        _ ->
            []
    end.

get_gm_last_time(TimeRegion) ->
    [{{SH, SM}, {EH, EM}}|_] = TimeRegion,
    {{Year, Month, Day}, _} = utime:localtime(),
    STime = utime:unixtime({{Year, Month, Day}, {SH, SM, 0}}),
    ETime = utime:unixtime({{Year, Month, Day}, {EH, EM, 0}}),
    round(ETime - STime).

%% 获取活动场次
get_collect_act_season(Module, ModuleSub, AcSub, Type) ->
    case data_activitycalen:get_ac(Module, ModuleSub, AcSub) of
        #base_ac{time_region = TimeRegion} when is_list(TimeRegion) andalso TimeRegion=/=[]->
            if Type == ?GUILD_COLLECT_ACT ->
                    NowTime = utime:unixtime(),
                    LocalTime = utime:unixtime_to_localtime(NowTime),
                    calc_act_season(LocalTime, NowTime, TimeRegion, 1);
                true ->
                    1
            end;
        _ ->
            1
    end.

calc_act_season(_LocTime, _Now, [], Season) ->
    Season;
calc_act_season(_LocTime, _Now, [{{_LastStartH, _LastStartM}, {_LastEndH, _LastEndM}}], Season) ->
    Season;
calc_act_season(LocTime, Now, [{{_LastStartH, _LastStartM}, {LastEndH, LastEndM}}|Rest], Season) ->
    {{Year, Month, Day}, _} = LocTime,
    End = utime:unixtime({{Year, Month, Day}, {LastEndH, LastEndM, 0}}),
    if Now =< End ->
            Season;
        true ->
            calc_act_season(LocTime, Now, Rest, Season+1)
    end.

send_to_suppporter(SupportId, SuppporterHurt) ->
    {ok, BinData} = pt_408:write(40807, SuppporterHurt),
    lib_server_send:send_to_uid(SupportId, BinData),
    ok.

get_invade_mon_xy(GuildScene, X, Y) ->
    case get_invade_mon_xy_do(GuildScene, X, Y, 5) of
        {RandX, RandY} ->
            {RandX, RandY};
        _ ->
            {X, Y}
    end.

get_invade_mon_xy_do(_GuildScene, _X, _Y, 0) -> false;
get_invade_mon_xy_do(GuildScene, X, Y, Index) ->
    RandY = urand:list_rand([-300,-200,-100,100,200,300]),
    RandX = urand:list_rand([-300,-200,-100,100,200,300]),
    TX = X + RandX,
    TY = Y + RandY,
    case lib_guild_collect:check_coordiate(GuildScene, TX, TY) of
        true ->
            {TX, TY};
        _ ->
            get_invade_mon_xy_do(GuildScene, X, Y, Index-1)
    end.

%% 获取社团所在分线
calc_guild_pool(GuildList) ->
    lists:foldl(fun(GuildIdX, Acc) -> 
        PoolId = ?GUILD_REM_POOL(GuildIdX),
        case lists:keyfind(PoolId, 1, Acc) of
            {_, GuildIds} ->
                case lists:member(GuildIdX, GuildIds) of
                    true -> Acc;
                    _    ->
                        NewGuildIds = [GuildIdX|GuildIds],
                        lists:keystore(PoolId, 1, Acc, {PoolId, NewGuildIds})
                end;
            _ ->
                lists:keystore(PoolId, 1, Acc, {PoolId, [GuildIdX]})
        end
    end, [], GuildList).


%% 活动结束清理怪物
act_end_clear_scene(0, _GuildPoolList) ->
    ok;
act_end_clear_scene(GuildScene, GuildPoolList) ->
    spawn(fun() -> 
        act_end_clear_scene_1(GuildScene, GuildPoolList)
    end).

act_end_clear_scene_1(_, []) -> ok;
act_end_clear_scene_1(GuildScene, [{PoolId, GuildIds}|Rest]) ->
    CopyIdLen = length(GuildIds),
    if CopyIdLen > 5 ->
            {SubList, RestList} = ulists:sublist(GuildIds, 5),
            lists:map(fun(GuildId) -> 
                lib_mon:clear_scene_mon(GuildScene, PoolId, GuildId, 1)
            end, SubList),
            timer:sleep(1000),
            act_end_clear_scene_1(GuildScene, [{PoolId, RestList}|Rest]);
        true ->
            lists:map(fun(GuildId) -> 
                lib_mon:clear_scene_mon(GuildScene, PoolId, GuildId, 1)
            end, GuildIds),
            act_end_clear_scene_1(GuildScene, Rest)
    end.

act_end_guild_seal(_, []) -> ok;
act_end_guild_seal(GuildScene, [{_PoolId, GuildIds}|Rest]) ->
    [mod_guild:apply_cast_guild_member(GuildId, 0, ?MODULE, role_act_end_refresh_count, []) || GuildId <- GuildIds],
    act_end_guild_seal(GuildScene, Rest).

%% 活动结束TA数据上报
role_act_end_refresh_count(Player) ->
    #player_status{id = RoleId, guild_collect = #role_guild_collect{last_enter_time = LastEnterTime} = RoleGuildCollect} = Player,
    EnterRec = lib_activitycalen_api:get_enter_activity_record(?MOD_GUILD_COLLECT, RoleId),
    CountList = [{?MOD_GUILD_COLLECT, 0, ?GUILD_COLLECT_3}, {?MOD_GUILD_COLLECT, 0, ?GUILD_COLLECT_4}],
    StayTime = utime:unixtime() - LastEnterTime,
    [{_, CollectCount}, {_, AssistCount}|_] = lib_daily:get_count(RoleId, CountList),
    ta_agent_fire:guild_seal(Player, [EnterRec, CollectCount, AssistCount, StayTime]),
    CountList1 = [{{?MOD_GUILD_COLLECT, 0, ?GUILD_COLLECT_3}, 0}, {{?MOD_GUILD_COLLECT, 0, ?GUILD_COLLECT_4}, 0}],
    lib_daily:set_count(RoleId, CountList1),
    {ok, Player#player_status{guild_collect = RoleGuildCollect#role_guild_collect{last_enter_time = 0}}}.