%% ----------------------------------
%% desc     :社团午间采集逻辑模块
%% module   :lib_guild_collect.erl
%% author   :hh
%% time     :20/03/01
%% ----------------------------------


-module(lib_guild_collect).

-export([
    act_start/1
    ,act_end/1
    ,act_start_logic/1

    ,create_guild_mon/5
    ,collect_mon/2
    ,notice_collect_act/2
    ,check_collect/2
    ,create_invade_mon/8
    ,update_support_data/4
    % ,update_guild_support_info/1
    ,refresh_support_hurt_data/6
    ,refresh_support_mon_data/3
    ,interval_refresh_mon/1
    ,guild_mon_collected/2
    ,attack_mon/3
    ,mon_die/4

    ,send_help_reward/1
    ,send_invade_call_reward/1
    ,finish_collect_support/2
    ,check_coordiate/3
    ,collect_goods/4
    ,collect_assist_count_increment/1
    ,change_scene_callback/4
    ]).

-export([
    login/1
    ,role_update_enter_time/1
    ,role_update_collect_time/4
    ,role_finish_collect_support/5
    ,update_role_enter_count/2
    ,born_handle/3
    ,hp_change_handle/3
    ]).

% -compile([export_all]).

-include("guild_collect.hrl").
-include("scene.hrl").
-include("server_kv.hrl").
-include("rec_event.hrl").
-include("def_event.hrl").
-include("def_module.hrl").
-include("server.hrl").
-include("counter.hrl").
-include("common.hrl").
-include("battle.hrl").
-include("guild.hrl").
-include ("def_goods.hrl").
-include ("predefine.hrl").
-include ("def_id_create.hrl").
-include ("figure.hrl").
-include ("errcode.hrl").

-define(GUILD_COLLECT_MIDNIGHT, 4064).
-define(INIT_WEIGHT, 50).
-define(CIRCLE_LIMIT, 3).
-define(INIT_ARG,   580).

login(RoleId) ->
    RoleGuildCollect =
     case db:get_row(?SELECT_COLLECT_INFO, [RoleId]) of
        [LastCollectTime, LastEnterTime, CollectCount|_] ->
            #role_guild_collect{
                last_collect_time = LastCollectTime,
                last_enter_time = LastEnterTime,
                collect_count = CollectCount
            };
        _ ->
            #role_guild_collect{}
    end,
    case lib_activitycalen_api:check_ac_start(?MOD_GUILD_COLLECT) of
        false ->
            CountList = [{{?MOD_GUILD_COLLECT, 0, ?GUILD_COLLECT_3}, 0}, {{?MOD_GUILD_COLLECT, 0, ?GUILD_COLLECT_4}, 0}],
            lib_daily:set_count(RoleId, CountList);
        _    ->
            skip
    end,
    RoleGuildCollect.

change_scene_callback(Player, {_OldSceneId, _, _, _, _}, OldSceneData, NewSceneInfo) ->
    #player_status{id = RoleId, guild_collect = #role_guild_collect{last_enter_time = LastEnterTime} = RoleGuildCollect} = Player,
    #ets_scene{type = OldSceneType} = OldSceneData,
    #ets_scene{type = NewSceneType} = NewSceneInfo,
    case lib_activitycalen_api:check_ac_start(?MOD_GUILD_COLLECT) of
        true ->
            if OldSceneType == ?SCENE_TYPE_GUILD andalso NewSceneType =/= ?SCENE_TYPE_GUILD ->
                    %% 从副本场景切出
                    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]),
                    {ok, Player};
                OldSceneType =/= ?SCENE_TYPE_GUILD andalso NewSceneType == ?SCENE_TYPE_GUILD ->
                    %% 从副本场景切入
                    NewRoleGuildCollect = do_update_enter_time(RoleGuildCollect),
                    NewPlayer = Player#player_status{guild_collect = NewRoleGuildCollect},
                    {ok, NewPlayer};
                true -> {ok, Player}
            end;
        _A -> {ok, Player}
    end.

role_update_enter_time(Player) ->
    #player_status{id = RoleId, guild_collect = RoleGuildCollect} = Player,
    lib_daily:increment(RoleId, ?MOD_GUILD_COLLECT, ?GUILD_COLLECT_1),
    NewRoleGuildCollect = do_update_enter_time(RoleGuildCollect),
    db_update_role_collect_info(RoleId, NewRoleGuildCollect),
    NewPlayer = Player#player_status{guild_collect = NewRoleGuildCollect},
    {ok, NewPlayer}.

role_update_collect_time(Player, StartTime, _EndTime, Goods) ->
    #player_status{id = RoleId, guild_collect = RoleGuildCollect, guild = StatusGuild} = Player,
    case RoleGuildCollect of
        #role_guild_collect{last_collect_time = LastCollectTime, collect_count = CollectCount} ->
            ok;
        _ ->
            LastCollectTime = 0, CollectCount = 0
    end,
    lib_daily:increment(RoleId, ?MOD_GUILD_COLLECT, ?GUILD_COLLECT_2),
    %% 更新本场采集次数
    if LastCollectTime == 0 ->
            NewCollectCount = 1;
        true ->
            if LastCollectTime >= StartTime ->
                    NewCollectCount = CollectCount + 1;
                true ->
                    NewCollectCount = 1
            end
    end,
    NewRoleGuildCollect = do_update_collect_time(RoleGuildCollect),
    NewRoleGuildCollect1 = NewRoleGuildCollect#role_guild_collect{collect_count = NewCollectCount},
    NewPlayer = Player#player_status{guild_collect = NewRoleGuildCollect1},
    db_update_role_collect_info(RoleId, NewRoleGuildCollect1),
    pp_guild_collect:handle(40803, NewPlayer, []),
    %% LOG
    case StatusGuild of
        #status_guild{id = GuildId} -> ok;
        _   -> GuildId = 0
    end,
    Now = utime:unixtime(),
    [CfgMaxCollectCount|_] = data_guild_collect:get_kv(collet_time),
    [CfgMaxDailyCount|_] = data_guild_collect:get_kv(join_time_day),
    TodayCollectCount = lib_daily:get_count(RoleId, ?MOD_GUILD_COLLECT, ?GUILD_COLLECT_2),
    RestCount = max(0, CfgMaxDailyCount - TodayCollectCount),
    RestRoundCount = max(0, CfgMaxCollectCount - NewCollectCount),
    lib_log_api:log_guild_collect([RoleId, GuildId, RestRoundCount, RestCount, util:term_to_bitstring(Goods), Now]),
    {ok, NewPlayer}.


do_update_enter_time(GuildCollect = #role_guild_collect{}) ->
    GuildCollect#role_guild_collect{last_enter_time = utime:unixtime()};
do_update_enter_time(_) ->
    #role_guild_collect{last_enter_time = utime:unixtime()}.

do_update_collect_time(GuildCollect = #role_guild_collect{}) ->
    GuildCollect#role_guild_collect{last_collect_time = utime:unixtime()};
do_update_collect_time(_) ->
    #role_guild_collect{last_collect_time = utime:unixtime()}.

db_update_role_collect_info(RoleId, GuildCollect) ->
    #role_guild_collect{
        last_collect_time = CollectTime,
        last_enter_time = EnterTime,
        collect_count = CollectCount
    } = GuildCollect,
    db:execute(?REPLACE_COLLECT_INFO, [RoleId, CollectTime, EnterTime, CollectCount]),
    ok.

check_collect(Player, _MondId) ->
    #player_status{id = RoleId, scene = Scene} = Player,
    GuildScene = data_guild:get(guild_scene),
    GuildScene1 = data_guild:get(guild_scene_night),
    if GuildScene =/= Scene orelse GuildScene1 =/= Scene ->
            true;
        true ->
            [{_, JoinCount}, {_, CollectCount}|_] = lib_daily:get_count(RoleId, [{?MOD_GUILD_COLLECT, ?DEFAULT_SUB_MODULE, ?GUILD_COLLECT_1}, {?MOD_GUILD_COLLECT, ?DEFAULT_SUB_MODULE, ?GUILD_COLLECT_2}]),
            [JoinMax|_] = data_guild_collect:get_kv(join_time_day),
            [CollectMax|_] = data_guild_collect:get_kv(collet_time),
            if JoinCount >= JoinMax ->
                    {false, 37}; %% 社团采集每日参与活动次数已达上限
                CollectCount >= CollectMax ->
                    {false, 38}; %% 社团采集每次活动的封印次数已达上限
                true ->
                    true
            end
    end.

update_role_enter_count(Player, NewCount) ->
    #player_status{id = RoleId, guild_collect = RoleGuildCollect} = Player,
    lib_daily:increment(RoleId, ?MOD_GUILD_COLLECT, ?GUILD_COLLECT_1),
    if NewCount =/= 0 ->
            Now = utime:unixtime(),
            NewRoleGuildCollect = RoleGuildCollect#role_guild_collect{
                last_enter_time = Now
            },
            % NewRoleGuildCollect = do_update_enter_time(RoleGuildCollect),
            db_update_role_collect_info(RoleId, NewRoleGuildCollect);
        true ->
            NewRoleGuildCollect = RoleGuildCollect
    end,
    {ok, Player#player_status{guild_collect = NewRoleGuildCollect}}.

%% --------------------------------------------------

act_start(ActSub) ->
    guild_collect_mgr:act_start(ActSub).

act_end(ActSub) ->
    guild_collect_mgr:act_end(ActSub).

act_start_logic(State) ->
    #guild_collect_state{ref = Ref, guild_list = GuildList, guild_scene = GuildScene, index = Index} = State,
    [MonId|_] = data_guild_collect:get_kv(mon_id),
    case data_mon:get(MonId) of
        #mon{type = Type} -> ok;
        _ -> Type = 0
    end,
    % GuildScene = lib_guild_api:get_guild_scene(),
    {GuildMonData, NewIndex} = lists:foldl(fun(GuildId, {Acc, TmpIndex}) ->
        {GuildMonXy, TmpIndex1} = create_guild_mon(MonId, Type, GuildScene, GuildId, TmpIndex),
        {ok, BinData} = pt_408:write(40806, [length(GuildMonXy)]),
        lib_server_send:send_to_guild(GuildId, BinData),
        {[{GuildId, GuildMonXy}|Acc], TmpIndex1}
     end, {[], Index}, GuildList),
    [RefreshTime|_] = data_guild_collect:get_kv(refresh_mon_time),
    NewRef = util:send_after(Ref, RefreshTime*1000, self(), {'interval_refresh_mon'}),
    NewState = State#guild_collect_state{wave = 1, index = NewIndex, ref = NewRef, guild_mon_data = GuildMonData},
    NewState.

create_guild_mon(MonId, MonType, GuildScene, GuildId, Index) ->
    [MonNum|_] = data_guild_collect:get_kv(mon_num),
    [ScenePoints|_] = data_guild_collect:get_kv(scene_point),
    AreaNum  = length(ScenePoints),
    TotalNum = MonNum,
    PerAreaNum = round(TotalNum/AreaNum),
    % ?ERR("~p ~p", [TotalNum, PerAreaNum]),
    MonCreated = [],
    do_create_guild_mon(MonId, MonType, GuildScene, GuildId, PerAreaNum, ScenePoints, MonCreated, Index).

do_create_guild_mon(_MonId, _MonType, _GuildScene, _GuildId, _PerAreaNum, [], MonCreated, Index) ->
    {MonCreated, Index};
do_create_guild_mon(MonId, MonType, GuildScene, GuildId, PerAreaNum, [{MidX, MidY}|Rest], MonCreated, Index) ->
    DotList = data_drop:get_dot_list(),
    AccessDotList = calc_access_dot_list(GuildScene, {MidX, MidY}, DotList, ?CIRCLE_LIMIT, ?INIT_ARG, ?INIT_WEIGHT, MonCreated, PerAreaNum, []),
    {NewMonCreated, NewIndex} = do_create_guild_mon_do(MonId, MonType, GuildScene, GuildId, AccessDotList, MonCreated, Index),
    do_create_guild_mon(MonId, MonType, GuildScene, GuildId, PerAreaNum, Rest, NewMonCreated, NewIndex).

%% 先剔除障碍点
%% 再算权重,算出可用点,重置权重
calc_access_dot_list(_, _, _, _, _, _, _, PerAreaNum, AccessDotList) when PerAreaNum =< 0 ->
    AccessDotList;
calc_access_dot_list(_, _, _DotList, CircleLimit, _InitArg, _InitWeight, _MonCreated, _, AccessDotList) when CircleLimit =< 0 ->
    AccessDotList;
calc_access_dot_list(GuildScene, {X, Y}, [], CircleLimit, Arg, Weight, MonCreated, PerAreaNum, AccessDotList) ->
    DotList = data_drop:get_dot_list(),
    calc_access_dot_list(GuildScene, {X, Y}, DotList, CircleLimit-1, Arg+100, Weight, MonCreated, PerAreaNum, AccessDotList);
calc_access_dot_list(GuildScene, {X, Y}, [{OX, OY}|DotList], CircleLimit, Arg, Weight, MonCreated, PerAreaNum, AccessDotList) ->
    RandX = X + round(Arg*OX),
    RandY = Y + round(Arg*OY),
    case check_coordiate(GuildScene, RandX, RandY) of
        true ->
            Rand = urand:rand(1, 100),
            % ?ERR("~p ~p", [Rand, Weight]),
            case lists:keymember({RandX, RandY}, 2, MonCreated) of
                false when Weight >= Rand -> %% 可用
                    calc_access_dot_list(GuildScene, {X, Y}, DotList, CircleLimit, Arg, ?INIT_WEIGHT, MonCreated, PerAreaNum-1, [{RandX, RandY}|AccessDotList]);
                _ ->
                    calc_access_dot_list(GuildScene, {X, Y}, DotList, CircleLimit, Arg, Weight+10, MonCreated, PerAreaNum, AccessDotList)
            end;
        _ ->
            calc_access_dot_list(GuildScene, {X, Y}, DotList, CircleLimit, Arg, Weight+10, MonCreated, PerAreaNum, AccessDotList)
    end.

%% 1 不可行走区域
%% 3 游泳区
check_coordiate(GuildScene, X, Y) ->
    {LogicX, LogicY} = lib_scene_calc:pixel_to_logic_coordinate(X, Y),
    not scene_landform:check_landform(GuildScene, LogicX, LogicY, 1) andalso
        not scene_landform:check_landform(GuildScene, LogicX, LogicY, 3).

do_create_guild_mon_do(_MonId, _MonType, _GuildScene, _GuildId, [], MonCreated, Index) ->
    {MonCreated, Index};
do_create_guild_mon_do(MonId, MonType, GuildScene, GuildId, [{OX, OY}|DotList], MonCreated, Index) ->
    CreateKey = {guild_collect, GuildId, Index},
    lib_mon:async_create_mon(MonId, GuildScene, ?GUILD_REM_POOL(GuildId), OX, OY, MonType, GuildId, 1, [{create_key, CreateKey}]),
    do_create_guild_mon_do(MonId, MonType, GuildScene, GuildId, DotList, [{Index, {OX, OY}}|MonCreated], Index+1).

hp_change_handle(State, MonAtter, [FromPid|_]) ->
    #ob_act{object = Minfo} = State,
    gen_server:cast(FromPid, {hp_change_handle, Minfo, MonAtter}),
    ok.

born_handle(init, Minfo, [CreateId, FromPid|_]) ->
    #scene_object{id = MonId, config_id = MonCfgId} = Minfo,
    %% 必须传递怪物唯一Id作为前端寻路标志
    gen_server:cast(FromPid, {mon_born_handle, CreateId, MonId, MonCfgId}).

collect_mon(CollectId, Minfo) ->
    #scene_object{
        config_id = ConfigId, scene = SceneId, scene_pool_id = ScenePool,
        copy_id = GuildId, x = X, y = Y, mon = #scene_mon{create_key = CreateKey}} = Minfo,
    case data_mon:get(ConfigId) of
        #mon{kind = ?MON_KIND_COLLECT} ->
            GuildScene = data_guild:get(guild_scene),
            GuildScene1 = data_guild:get(guild_scene_night),
            case GuildScene == SceneId orelse GuildScene1 == SceneId of
                true ->
                    case CreateKey of
                        {_, GuildId, _} ->
                            guild_collect_mgr:collect_mon(CollectId, ConfigId, CreateKey, X, Y, SceneId, ScenePool, GuildId),
                            lib_daily:increment(CollectId, ?MOD_GUILD_COLLECT, ?GUILD_COLLECT_3);
                        _ ->
                            skip
                    end;
                _ ->
                    skip
            end;
        _ ->
            skip
    end.

mon_die(Minfo, _AtterSign, AtterId, GuildId) ->
    GuildScene = data_guild:get(guild_scene),
    GuildScene1 = data_guild:get(guild_scene_night),
    #scene_object{scene = SceneId, mon = Mon} = Minfo,
    case Mon of
        #scene_mon{create_key = {?GUILD_COLLECT_INVADE_MON, _CreateId, _}}
         when GuildScene == SceneId orelse GuildScene1 == SceneId ->
            guild_collect_mgr:kill_mon(Minfo, AtterId, GuildId);
        _ ->
            skip
    end.

attack_mon(Atter, Minfo, Hurt) ->
    GuildScene = data_guild:get(guild_scene),
    GuildScene1 = data_guild:get(guild_scene_night),
    #scene_object{scene = SceneId, mon = Mon} = Minfo,
    #battle_return_atter{id = AtterId} = Atter,
    case Mon of
        #scene_mon{create_key = {?GUILD_COLLECT_INVADE_MON, CreateId, _}}
        when (GuildScene == SceneId orelse GuildScene1 == SceneId) andalso CreateId =/= AtterId ->
            guild_collect_mgr:attack_mon(Atter, Minfo, Hurt);
        _ ->
            skip
    end.


create_invade_mon(CollectId, SceneId, ScenePool, CopyId, X, Y, _ConfigMonId, Index) ->
    [Weight|_] = data_guild_collect:get_kv(weight), %% 入侵怪概率
    Rand = urand:rand(1, ?WEIGHT_MAX),
    if Weight >= Rand ->
            [InvadeId|_] = data_guild_collect:get_kv(invade_mon), %% 怪物id
            #figure{lv = RoleLv, guild_id = _GuildId} = lib_role:get_role_figure(CollectId),
            MonName = get_mon_name(CollectId, InvadeId),
            % SupportSid = mod_id_create:get_new_id(?SUPPORT_ID_CREATE),
            MonKey = {?GUILD_COLLECT_INVADE_MON, CollectId, Index},
            % update_guild_support_info([SupportSid, CollectId]),
            BornHandler = {born_handler, {?MODULE, born_handle, [CollectId, self()]}},
            HpHandler = {hp_change_handler, {?MODULE, hp_change_handle, [self()]}},
            Attrs = [{create_key, MonKey},{auto_lv, RoleLv},{mon_name, MonName}, HpHandler, BornHandler],
            case data_mon:get(InvadeId) of
                #mon{type = MonType} -> ok;
                _ -> MonType = 1
            end,
            lib_mon:async_create_mon(InvadeId, SceneId, ScenePool, X, Y, MonType, CopyId, 1, Attrs),
            {true, Index+1};
        true ->
            {false, Index}
    end.

update_support_data(SupportData, _CollectId, _Index, false) ->
    SupportData;
update_support_data(SupportData, CollectId, Index, _) ->
    Key = {CollectId, Index},
    HurtL = [],
    RoleSupport = {Key, HurtL},
    NewSupportData = lists:keystore(Key, 1, SupportData, RoleSupport),
    NewSupportData.

%%update_guild_support_info([SupportSid, CollectId]) ->
%%    #figure{guild_id = GuildId} = lib_role:get_role_figure(CollectId),
%%    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,
%%            GuildInstance  = create_guild_support_instance(SupportSid, CollectId),
%%            NewSupportMaps = maps:put(SupportSid, GuildInstance, SupportMaps),
%%            {OwnSidList, HelpSid} = maps:get(CollectId, RoleMaps, {[], 0}),
%%            NewOwnSidList  = [SupportSid|OwnSidList],
%%            NewRoleMaps    = maps:put(CollectId, {NewOwnSidList, HelpSid}, RoleMaps),
%%            NewGuildSupportInfo = GuildSupportInfo#guild_collect_support_info{
%%                support_maps = NewSupportMaps, role_maps = NewRoleMaps},
%%            ets:insert(?ETS_GUILD_COLLECT_ASSIST, NewGuildSupportInfo);
%%        _ ->
%%            GuildInstance    = create_guild_support_instance(SupportSid, CollectId),
%%            SupportMaps      = maps:put(SupportSid, GuildInstance, #{}),
%%            RoleMaps         = maps:put(CollectId, {[SupportSid], 0}, #{}),
%%            GuildSupportInfo = #guild_collect_support_info{
%%                guild_id = GuildId, support_maps = SupportMaps, role_maps = RoleMaps},
%%            ets:insert(?ETS_GUILD_COLLECT_ASSIST, GuildSupportInfo)
%%    end.

%%create_guild_support_instance(SupportSid, CollectId) ->
%%    [BossId|_] = data_guild_collect:get_kv(invade_mon),
%%    #support_instance{
%%        sid = SupportSid,
%%        req_role = CollectId,
%%        boss_id = BossId,
%%        create_time = utime:unixtime()
%%    }.

refresh_support_hurt_data(CreateId, CreateIndex, AtterId, SupportId, Hurt, SupportData) ->
    if SupportId == CreateId ->
            case lists:keyfind({CreateId, CreateIndex}, 1, SupportData) of
                {_, HurtSupport} ->
                    NewHurtSupport =
                    case lists:keyfind(AtterId, 1, HurtSupport) of
                        {_, OldHurt} ->
                            lists:keystore(AtterId, 1, HurtSupport, {AtterId, round(OldHurt+Hurt)});
                        _ ->
                            lists:keystore(AtterId, 1, HurtSupport, {AtterId, round(Hurt)})
                    end,
                    lists:keystore({CreateId, CreateIndex}, 1, SupportData, {{CreateId, CreateIndex}, NewHurtSupport});
                _ ->
                    SupportData
            end;
        true ->
            SupportData
    end.

refresh_support_mon_data(State, CreateId, MonId) ->
    #guild_collect_state{support_mon_data = SupportMons} = State,
    NewSupportMons =
    case lists:keyfind(CreateId, 1, SupportMons) of
        {_, Mons} ->
            lists:keystore(CreateId, 1, SupportMons, {CreateId, lists:delete(MonId, Mons)});
        _ ->
            SupportMons
    end,
    State#guild_collect_state{support_mon_data = NewSupportMons}.

interval_refresh_mon(State) ->
    #guild_collect_state{
        wave = Wave, index = Index, ref = Ref, guild_list = GuildList,
        guild_mon_data = GuildMonData, guild_scene = GuildScene
    } = State,
    [RefreshTime|_] = data_guild_collect:get_kv(refresh_mon_time),
    [TotalWave|_] = data_guild_collect:get_kv(total_wave),
    if Wave >= TotalWave ->
            State;
        true ->
            NewWave = Wave + 1,
            GuildMonData1 = check_guild_increment(GuildList, GuildMonData),
            {NewGuildMonData, NewIndex} = update_new_guild_mon_data(GuildScene, Index, GuildMonData1),
            NewRef = util:send_after(Ref, RefreshTime*1000, self(), {'interval_refresh_mon'}),
            State#guild_collect_state{ref = NewRef, wave = NewWave, index = NewIndex, guild_mon_data = NewGuildMonData}
    end.

check_guild_increment(GuildList, GuildMonData) ->
    CreatedGuild = [GuildId || {GuildId, _} <- GuildMonData],
    NewCreateGuildIds = GuildList -- CreatedGuild,
    lists:foldl(fun(NewGuildId, Acc) ->
        [{NewGuildId, []}|Acc]
    end, GuildMonData, NewCreateGuildIds).

update_new_guild_mon_data(GuildScene, Index, GuildMonData) ->
    [TotalMonNum|_] = data_guild_collect:get_kv(mon_num),
    [ScenePoints|_] = data_guild_collect:get_kv(scene_point),
    lists:foldl(fun({GuildId, GuildMonXy}, {TmpGuildMonData, TmpIndex}) ->
        MonLen = length(GuildMonXy),
        if MonLen >= TotalMonNum ->
                {[{GuildId, GuildMonXy}|TmpGuildMonData], TmpIndex};
            true ->
                NeedRfresh   = TotalMonNum - MonLen,
                AreaFreshNum = calc_arena_need_fresh(NeedRfresh, ScenePoints),
                % ?ERR("~p", [AreaFreshNum]),
                {GuildData, TmpIndex1} = do_update_guild_mon_data(GuildId, GuildScene, GuildMonXy, TmpIndex, AreaFreshNum, ScenePoints),
                {[GuildData|TmpGuildMonData], TmpIndex1}
        end
     end, {[], Index}, GuildMonData).

calc_arena_need_fresh(NeedRfresh, ScenePoints) ->
    Area   = length(ScenePoints),
    PerNum = umath:floor(NeedRfresh/Area),
    Rest   = NeedRfresh - round(Area*PerNum),
    SpNum  = Rest + PerNum,
    [SpNum] ++ lists:duplicate(max(0, Area-1), PerNum).

do_update_guild_mon_data(GuildId, GuildScene, GuildMonXy, Index, AreaFreshNum, ScenePoints) ->
    % GuildMonXy1 = [ {X, Y} || {_, {X, Y}} <- GuildMonXy],
    % RestScenePoints = ConfigScenePoints -- GuildMonXy1,
    [MonId|_]  = data_guild_collect:get_kv(mon_id),
    case data_mon:get(MonId) of
        #mon{type = Type} -> ok;
        _ -> Type = 0
    end,
    {NewGuildMon, NewIndex} = lists:foldl(fun(FreshNum, {TempGuildMonXy, TempIndex}) ->
        do_create_guild_mon(MonId, Type, GuildScene, GuildId, FreshNum, ScenePoints, TempGuildMonXy, TempIndex)
    end, {GuildMonXy, Index},  AreaFreshNum),
    % MonId, MonType, GuildScene, GuildId, PerAreaNum, ScenePoints, MonCreated, Index
    % {NewRfreshMon, NewIndex} = do_create_guild_mon(MonId, Type, GuildScene, GuildId, NeedRfresh, ScenePoints, [], Index),
    % NewGuildMon = GuildMonXy ++ NewRfreshMon,
    MonLen = length(NewGuildMon),
    {ok, BinData} = pt_408:write(40806, [MonLen]),
    lib_server_send:send_to_guild(GuildId, BinData),
    {{GuildId, NewGuildMon}, NewIndex}.

guild_mon_collected(CreateKey, GuildMonData) ->
    {_, GuildId, Index} = CreateKey,
    case lists:keyfind(GuildId, 1, GuildMonData) of
        {_, Indexs} ->
            NewIndexs = lists:keydelete(Index, 1, Indexs),
            NewGuildMonData = lists:keystore(GuildId, 1, GuildMonData, {GuildId, NewIndexs}),
            MonLen = length(NewIndexs),
            {ok, BinData} = pt_408:write(40806, [MonLen]),
            lib_server_send:send_to_guild(GuildId, BinData),
            NewGuildMonData;
        _ ->
            GuildMonData
    end.

get_mon_name(CollectId, MonId) ->
    case data_mon:get(MonId) of
        #mon{name = Name} -> ok;
        _ -> Name = "boss"
    end,
    RoleName    = lib_role:get_role_name(CollectId),
    RoleNameL   = unicode:characters_to_list(RoleName),
    Name1       = unicode:characters_to_list("的"),
    Name2       = unicode:characters_to_list(Name),
    MonName     = RoleNameL ++ Name1 ++ Name2,
    MonName1    = unicode:characters_to_binary(MonName),
    MonName1.

send_help_reward(RoleId) ->
    RoleLv = lib_role:get_role_lv(RoleId),
    case data_guild_collect:get_help_rewards(RoleLv) of
        Rewards = [_|_] ->
            do_send_reward(guild_collect_help_rewards, Rewards, RoleId);
        _ ->
            skip
    end.

send_invade_call_reward(RoleId) ->
    RoleLv = lib_role:get_role_lv(RoleId),
    case data_guild_collect:get_rewards(RoleLv) of
        Rewards = [_|_] ->
            do_send_reward(guild_collect_invade_call_rewards, Rewards, RoleId);
        _ ->
            skip
    end.

%% 完成协助后
finish_collect_support(GuildId, SupportInstance) ->
    #support_instance{req_role = ReqRoleId, res_roles = ResRoles} = SupportInstance,
    mod_guild:apply_cast(lib_guild_tribe_mod, update_guild_assist, [GuildId]),
    Type = 1, SupportCfgId = 2,
    [BossId|_] = data_guild_collect:get_kv(invade_mon),
    GoodsTypeId = guild_thank:get_reward_cfg(Type, SupportCfgId),
    lists:map(fun(RoleId) ->
        Pid = misc:get_player_process(RoleId),
        case misc:is_process_alive(Pid) of
            true ->
                lib_player:apply_cast(RoleId, ?APPLY_CAST_SAVE, ?MODULE, role_finish_collect_support, [SupportCfgId, ReqRoleId, ResRoles, BossId]);
            _ ->
                ExtraData = [{?GOODS_OTHER_KEY_SUPPORT_ROLE_LIST, [{thank_cfgid, Type, SupportCfgId, BossId}, ResRoles]}],
                lib_mail_api:send_sys_mail([RoleId], ?MOD_GUILD, utext:get(13), utext:get(14), [{?TYPE_ATTR_GOODS, GoodsTypeId, 1, [{extra_data, ExtraData}]}])
        end
    end, [ReqRoleId] ++ ResRoles),
    ok.

role_finish_collect_support(Player, SupportCfgId, ReqRoleId, _ResRoles, BossId) ->
    #player_status{id = RoleId, sid = Sid, figure = #figure{guild_id = GuildId}} = Player,
    % Type = 1,
    Figure = lib_role:get_role_figure(ReqRoleId),
    %% 请求者 协助感谢奖励
    {ok, Player1} =
    if ReqRoleId == RoleId ->
            % guild_thank:send_thank_support_reward(Player, Type, SupportCfgId, ResRoles, BossId),
            {ok, Player};
        true ->
            {ok, BinData} = pt_400:write(40054, [?SUCCESS, SupportCfgId, Figure, BossId]),
            lib_server_send:send_to_sid(Sid, BinData),
            %% 日志
            lib_log_api:log_guild_support_reward(RoleId, GuildId, ReqRoleId, SupportCfgId, 1),
            {ok, NewPlayer} = lib_achievement_api:guild_collect_support_event(Player, 1),
            %% 协助者 社团声望
            {ok, NewPlayer1} = lib_guild_support_mod:add_reputation(NewPlayer, SupportCfgId, ReqRoleId),
            lib_achievement_api:support_event(NewPlayer1, 1)
    end,
    {ok, Player1}.

do_send_reward(RewardType, Rewards, RoleId) ->
    Pid = misc:get_player_process(RoleId),
    case is_pid(Pid) andalso misc:is_process_alive(Pid) of
        true ->
            lib_goods_api:send_reward_by_id(Rewards, RewardType, RoleId);
        _ ->
            if RewardType == guild_collect_help_rewards ->
                    Title = Content = <<"社团采集入侵怪击杀协助奖励"/utf8>>,
                    lib_mail_api:send_sys_mail([RoleId], ?MOD_GUILD_COLLECT, Title, Content, Rewards);
                RewardType == guild_collect_invade_call_rewards ->
                    Title = Content = <<"社团采集入侵怪召唤奖励"/utf8>>,
                    lib_mail_api:send_sys_mail([RoleId], ?MOD_GUILD_COLLECT, Title, Content, Rewards);
                true ->
                    skip
            end
    end.

notice_collect_act(Status, Season) ->
    % ?INFO_TTY("~p", [Status]),
    {ok, BinData} = pt_408:write(40804, [Status, Season]),
    lib_server_send:send_to_all(BinData).

collect_goods(Goods, Player, ProduceType, ProduceSubType) ->
    #player_status{scene = SceneId, id = RoleId} = Player,
    [MonId|_] = data_guild_collect:get_kv(mon_id),
    case lib_guild_api:check_in_guild_scene(SceneId) of
        true when ProduceType == mon_drop andalso ProduceSubType == MonId ->
            guild_collect_mgr ! {update_collector_data, Goods, RoleId};
        _ ->
            ok
    end.

collect_assist_count_increment(Helper) ->
    lib_daily:plus_count_offline(Helper, ?MOD_GUILD_COLLECT, ?GUILD_COLLECT_4, 1),
    ok.
