%%%-------------------------------------------------------------------
%%% @author zmh
%%% @doc
%%%
%%% @end
%%%-------------------------------------------------------------------
-module(lib_guild_badge).
-compile(export_all).
%% API
-export([
    check_badge_own/2
    ,check_role_badge_own/2
    ,add_guild_badge/2
    ,do_add_guild_badge/2
    ,get_badge/1
    ,get_badge_attr/1
    % ,fix_badge/2
    ,update_status_guild/2
    ,check/1
    ,gm/0
]).
-include("server.hrl").
-include("guild.hrl").
-include("predefine.hrl").
-include("common.hrl").
-include("errcode.hrl").
-include("def_event.hrl").
-include("def_module.hrl").
-include("rec_event.hrl").
-include("common_rank.hrl").
-include("guild_tribe.hrl").
-include("camp_war.hrl").

%%20200520 版本修改
%% 只剩 社团战力和社团活跃榜单的徽章
%% 每小时更替一次
%% 失去加成效果


gm()->
    gen_server:cast(mod_common_rank, {'gm_daily_timer'}).

% handle_event(Status, #event_callback{type_id = ?EVENT_FOUR_CLOCK}) when is_record(Status, player_status) ->
%     #player_status{
%         guild = StatusGuild
%     } = Status,
%     #status_guild{badges=Badges}=StatusGuild,
%     Now = utime:unixtime(),
%     NBadges = fix_badge(Now,Badges,[]),
%     NStatusGuild = StatusGuild#status_guild{badges=NBadges},
%     NStatus0 = Status#player_status{guild=NStatusGuild},
%     NStatus =
%         case utime:day_of_week()=:= ?WEEKDAY_BADGE of
%             true->
%                 IsPre = check_badge_own(Badges,?GBADGE_ATTR),
%                 IsAft = check_badge_own(NBadges,?GBADGE_ATTR),
%                 case IsPre == IsAft of
%                     true->
%                         NStatus0;
%                     _->
%                         NStatus1  = lib_player:count_player_attribute(NStatus0,?MOD_GUILD),
%                         lib_player:send_attribute_change_notify(NStatus1, ?NOTIFY_ATTR),
%                         NStatus1
%                 end;
%             _->
%                 NStatus0
%         end,
%     {ok, NStatus};
handle_event(Status, _Event) ->
    {ok, Status}.

handle_event(_Event) ->
    ok.

get_badge_attr(_Status)->
    [].
    % #player_status{guild=StatusGuild}=Status,
    % #status_guild{badges=Badges}=StatusGuild,
    % case check_badge_own(Badges,?GBADGE_ATTR) of
    %     {true,Bid} ->
    %         case data_guild:get_badge(Bid) of
    %             #base_badge{effect=Attrs}->
    %                 Attrs;
    %             _->
    %                 []
    %         end;
    %     _->
    %         []
    % end.

update_status_guild(_OStatus,Status)->
   %  #player_status{
   %      guild = StatusGuild
   %  } = Status,
   %  #status_guild{badges=Badges}=StatusGuild,

   % #player_status{
   %      guild = OStatusGuild
   %  } = OStatus,
   %  #status_guild{badges=OBadges}=OStatusGuild,

   %  IsPre = check_badge_own(OBadges,?GBADGE_ATTR),
   %  IsAft = check_badge_own(Badges,?GBADGE_ATTR),
   %  case IsPre == IsAft of
   %      true->
   %          Status;
   %      _->
   %          NStatus  = lib_player:count_player_attribute(Status,?MOD_GUILD),
   %          lib_player:send_attribute_change_notify(NStatus, ?NOTIFY_ATTR),
   %          NStatus
   %  end.
   Status.

get_badge(Status)->
    #player_status{guild=StatusGuild}=Status,
    #status_guild{badges=Badges}=StatusGuild,
    Badges.


trigger_badge_event(Ranks,Type)->
    trigger_guild_badge(Ranks,data_guild:get_type_badge(Type)).

trigger_guild_badge([],_)->
    ok;
trigger_guild_badge(_,[])->
    ok;
trigger_guild_badge([H|T],Badges)->
    #common_rank_guild{guild_id=GuildID,rank=Rank}=H,
    Bid = filter_rank_badge(Badges,Rank),
    case Bid>0 of
        true->
            add_guild_badge(GuildID,Bid),
            trigger_guild_badge(T,Badges);
        _->
            trigger_guild_badge(T,Badges)
    end.

trigger_camp_war_badge_event(Ranks, Type)->
    Ranks1 = before_trigger_camp_war_badge(Ranks),
    trigger_camp_war_badge(Ranks1, data_guild:get_type_badge(Type)).

before_trigger_camp_war_badge(GuildRank) ->
    GuildRank1   = lists:filter(fun(#camp_war_guild{hurt = Hurt}) -> Hurt =/= 0 end, GuildRank),
    SortedGuilds = lists:reverse(lists:keysort(#camp_war_guild.hurt, GuildRank1)),
    F = fun(#camp_war_guild{guild_id = GuildId}, {TRank, TList}) ->
        {
            TRank + 1,
            [{GuildId, TRank + 1}|TList]
        }
    end,
    {_, AfterSortedList} = lists:foldl(F, {0, []}, SortedGuilds),
    AfterSortedList.

trigger_camp_war_badge([], _)->
    ok;
trigger_camp_war_badge(_, [])->
    ok;
trigger_camp_war_badge([H|T], Badges) ->
    {GuildId, Rank} = H,
    Bid = filter_rank_badge(Badges, Rank),
    case Bid > 0 of
        true->
            add_guild_badge(GuildId, Bid),
            trigger_camp_war_badge(T, Badges);
        _->
            trigger_camp_war_badge(T,Badges)
    end.

filter_rank_badge([],_Rank)->
    0;
filter_rank_badge([H|T],Rank)->
    case data_guild:get_badge(H) of
        #base_badge{condition = [{rank,Need}|_]} when Rank=<Need->
            H;
        _->
            filter_rank_badge(T,Rank)
    end.


%%给社团发徽章
add_guild_badge(GuildID,Bid)->
    mod_guild:cast_to_guild({add_guild_badge,GuildID,Bid}).


do_add_guild_badge(GuildID,Bid)->
    Guild = lib_guild_data:get_guild_by_id(GuildID),
    case is_record(Guild, guild) of
        true->
            #guild{badges=Badges}=Guild,
            NBadges = update_guild_badge(Bid,Badges),
            sync_guild_member(GuildID,NBadges),
            NewGuild = Guild#guild{badges=NBadges},
            lib_guild_data:db_guild_update_badge(GuildID,NBadges),
            lib_guild_data:update_guild(NewGuild);
        _->
            ok
    end.

sync_guild_member(GuildID,Badges)->
    GuildMemberMap = lib_guild_data:get_guild_member_map(GuildID),
    maps:fold(fun
        (_, GMember,_) ->
            if
                is_record(GMember, guild_member) ->
                    if
                        GMember#guild_member.online_flag =:= ?ONLINE_ON ->
                            lib_player:apply_cast(GMember#guild_member.id, ?APPLY_CAST_STATUS, lib_guild, update_guild_badge, [GuildID,Badges]);
                        true ->
                            skip
                    end,
                    ok;
                true ->
                    ok
            end
    end,[],GuildMemberMap).

%%20200520更正
%%每小时更替 每次都要先清理上轮同类 再追加新的
%%没有时间实效
update_guild_badge(Bid,Badges)->
    #base_badge{type=Type}=data_guild:get_badge(Bid),
    Badges0 = [B||B<-Badges,B#guild_badge.type /= Type],
    NRec = #guild_badge{id=Bid,type=Type,stime=0,etime=0},
    NBadges = lists:keystore(Type,#guild_badge.type,Badges0,NRec),
    NBadges.


    % #base_badge{type=Type,cool=Cool}=data_guild:get_badge(Bid),
    % Now = utime:unixtime(),
    % case Cool>0 of
    %     true->
    %         Stime = Now,
    %         Etime = utime:logic_week_start()+86400*7*Cool;
    %     _->
    %         Stime = 0,
    %         Etime = 0
    % end,
    % Badges0 = fix_badge(Now,Badges,[]),
    % NRec = case lists:keyfind(Type,#guild_badge.type,Badges0) of
    %     #guild_badge{id=Oid}=Rec when Oid>Bid-> %%已有 更高级 未失效
    %         Rec;
    %     #guild_badge{id=Bid}=Rec -> %%已有 更高级 未失效 时间更新
    %         Rec#guild_badge{stime=Stime,etime=Etime};
    %     _->
    %         #guild_badge{id=Bid,type=Type,stime=Stime,etime=Etime}
    % end,
    % NBadges = lists:keystore(Type,#guild_badge.type,Badges0,NRec),
    % NBadges.

fix_badge(Now,Guild)->
    #guild{badges=Badges}=Guild,
    NBadges = fix_badge(Now,Badges,[]),
    Guild#guild{badges=NBadges}.

fix_badge(_Now,[],Badges)->
    Badges;
fix_badge(Now,[H|T],Badges)->
    #guild_badge{etime=Etime}=H,
    case Etime>0 of
        true when Now>=Etime->
            fix_badge(Now,T,Badges);
        _->
            fix_badge(Now,T,[H|Badges])
    end.

%%分红
badge_ability_for_cash(Badges)->
    case check_badge_own(Badges, ?GBADGE_CASH) of
        {true,Bid}  ->
            case data_guild:get_badge(Bid) of
                #base_badge{effect=Effect}->
                    Effect;
                _->
                    0
            end;
        _ ->
            0
    end.
%%贡献
badge_ability_for_contribute(Badges) ->
    case check_badge_own(Badges, ?GBADGE_CONTRIBUTE) of
        {true,Bid}  ->
            case data_guild:get_badge(Bid) of
                #base_badge{effect=Effect}->
                    Effect;
                _->
                    0
            end;
        _ ->
            0
    end.

%%名望
badge_ability_for_repution(Badges) ->
    case check_badge_own(Badges, ?GBADGE_REPUTATION) of
        {true,Bid}  ->
            case data_guild:get_badge(Bid) of
                #base_badge{effect=Effect}->
                    Effect;
                _->
                    0
            end;
        false ->
            0
    end.
%%伤害
badge_ability_for_boss(Badges) ->
    case check_badge_own(Badges, ?GBADGE_BOSS) of
         {true,Bid}  ->
            case data_guild:get_badge(Bid) of
                #base_badge{effect=Effect}->
                    Effect;
                _->
                    0
            end;
        false ->
            0
    end.


%% 判断玩家是否持有某徽章
check_role_badge_own(Status,Type) ->
    #player_status{guild=StatusGuild} = Status,
    #status_guild{badges=Badges}=StatusGuild,
    check_badge_own(Badges,Type).

check_badge_own(Badges,Type)->
    Now = utime:unixtime(),
    case lists:keyfind(Type, #guild_badge.type, Badges) of
        #guild_badge{id=Bid,etime=Etime} when Etime=<0 ->
            {true,Bid};
        #guild_badge{id=Bid,etime=Etime} when Etime>=Now ->
            {true,Bid};
        _->
            false
    end.

%%事件激活徽章
trigger_badge(Guild,Type)->
    Allbadges  = data_guild:get_all_badge(),
    NeedCheckList = filter_need_check(Allbadges,Type,[]),
    Actives = check_active_badges(Guild,NeedCheckList),
    Badges = split_badge(Actives,[]),
    case length(Actives)>0 of
        true->
            NGuild = do_active_badge(Badges,Guild),
            #guild{id=GuildID,badges=NewBadges}=NGuild,
            lib_guild_data:db_guild_update_badge(GuildID,NewBadges),
            sync_guild_member(GuildID,NewBadges);
        _->
            NGuild = Guild
    end,
    NGuild.

split_badge([],Badges)->
    Badges;
split_badge([H|T],Badges)->
    case data_guild:get_badge(H) of
        #base_badge{type=Type}->
            case lists:keyfind(Type,1,Badges) of
                {_,V} when V>=H->
                    split_badge(T,Badges);
                _->
                    split_badge(T,lists:keystore(Type,1,Badges,{Type,H}))
            end;
        _->
            split_badge(T,Badges)
    end.


check_active_badges(Guild,NeedCheckList)->
    check_active_badges(Guild,NeedCheckList,[]).
check_active_badges(_Guild,[],Actives) ->
    Actives;
check_active_badges(Guild,[H|T],Actives) ->
    NActives =
        case check({check_condition,{Guild,H}}) of
            true ->
                [H | Actives];
            _ ->
                Actives
        end,
    check_active_badges(Guild,T, NActives).


% %% 检查社团参与人数
% check({{guild_party, Num},Guild}) ->
%     #guild{fire_num=FNum}=Guild,
%     case FNum >= Num of
%         false ->
%             {false, ?ERRCODE(err400_conditions_not_met)};
%         _ ->
%             true
%     end;

%% 检查社团帮战获胜次数
check({{guild_war_win, Num}, Guild}) ->
    #guild{war_win=WNum}=Guild,
    case WNum>=Num of
        false ->
            {false, ?ERRCODE(err400_conditions_not_met)};
        _ ->
            true
    end;

% %% 检查社团周助战
% check({{guild_assist, Num}, Guild}) ->
%     #guild{assist=ANum}=Guild,
%     case ANum>=Num of
%         false ->
%             {false, ?ERRCODE(err400_conditions_not_met)};
%         _ ->
%             true
%     end;

% %% 检查社团等级
% check({{guild_level,Lv}, Guild}) ->
%     #guild{lv=GLv}=Guild,
%     case GLv>=Lv of
%         false ->
%             {false, ?ERRCODE(err400_conditions_not_met)};
%         _ ->
%             true
%     end;

%% 检查是否满足激活徽章
check({check_condition,{Guild,Bid}}) ->
    #base_badge{
        condition = Condition
    } = data_guild:get_badge(Bid),
    NewCondition = [
        {Cond, Guild} || Cond <- Condition
    ],
    check_list(NewCondition).

check_list([]) -> true;
check_list([H|L]) ->
    case check(H) of
        {false, Reason} ->
            {false, Reason};
        true ->
            check_list(L)
    end.

do_active_badge([],Guild)->
    Guild;
do_active_badge([{_,H}|T],Guild)->
    #guild{badges=Badges}=Guild,
    NBadges = update_guild_badge(H,Badges),
    do_active_badge(T,Guild#guild{badges=NBadges}).

filter_need_check([],_,Checks)->
    Checks;
filter_need_check([H|T],Type,Checks)->
    #base_badge{condition=Condition}=data_guild:get_badge(H),
    case lists:keymember(Type,1,Condition) of
        true ->
            filter_need_check(T,Type,[H|Checks]);
        false ->
            filter_need_check(T,Type,Checks)
    end.


%%重新发放 晚宴 助战  社团战徽章
% recheck_badge(Now,Guild)->
%     OpenDay = util:get_open_day(),
%     Day = utime:logic_day_of_week(),
%     case OpenDay>=?OPENDAY_BADGE andalso Day == ?WEEKDAY_BADGE of
%         true->
%             NGuild0    = fix_badge(Now,Guild),
%             Allbadges  = data_guild:get_all_badge(),
%             NeedCheckList0 = filter_need_check(Allbadges,guild_party,[]),
%             NeedCheckList1 = filter_need_check(Allbadges,guild_assist,[]),
%             NeedCheckList2 = filter_need_check(Allbadges,guild_war_win,[]),
%             NeedCheckList  = NeedCheckList0++NeedCheckList1++NeedCheckList2,
%             Actives = check_active_badges(NGuild0,NeedCheckList),
%             Badges = split_badge(Actives,[]),
%             case length(Actives)>0 of
%                 true->
%                     NGuild1 = do_active_badge(Badges,NGuild0),
%                     #guild{id=GuildID,badges=NewBadges}=NGuild1,
%                     lib_guild_data:db_guild_update_badge(GuildID,NewBadges),
%                     sync_guild_member(GuildID,NewBadges);
%                 _->
%                     NGuild1 = NGuild0
%             end,
%             NGuild = reset_badge_data(NGuild1#guild{last_renew=utime:logic_week_start()+86400*7}),
%             NGuild;
%         _->
%             Guild
%     end.

% reset_badge_data(Guild)->
%     #guild{id=GuildID,last_renew=Now,war_win=WarWin}=Guild,
%     lib_guild_data:db_guild_update_badge_need(GuildID,0,0,WarWin,Now),
%     Guild#guild{fire_num=0,assist=0}.
