%%%--------------------------------------
%%% @Module  : lib_draw_record_mod_kf.hrl
%%% @Author  : lhy
%%% @Created : 2019-06-01
%%% @Description:  定制活动抽奖记录(跨服)
%%%--------------------------------------

-module(lib_draw_record_mod_kf).
-include("custom_act.hrl").
-include("figure.hrl").
-include("predefine.hrl").
-include("role.hrl").
-include("server.hrl").
-include("clusters_zone.hrl").
-include("def_module.hrl").
-include("common.hrl").
-include("custom_act_draw_record.hrl").

-export([
	      init/1
         ,make_record/2

	     ,refresh_draw_reward_record/2     %% 刷新活动记录
	     ,send_draw_reward_record/6        %% 发送记录 有特殊要求可根据活动类型进行特殊处理
         ,act_end/3                        %% 清除活动数据
         ,kf_act_end_local/2               %% 转到游戏服清除本服数据
]).

make_record(kf_draw_role, [Type, SubType, RoleId, ServerId, Platform, ServerNum, RoleName, GradeId, Time]) ->
    #kf_draw_role{
        type = Type,               %% 活动类型
	    sub_type = SubType,        %% 活动子类型
	    role_id = RoleId,          %% 玩家id
	    server_id = ServerId,      %% 服务器id
        platform = Platform,       %% 平台名字
        server_num = ServerNum,    %% 所在的服标示
        name = RoleName,           %% 名字
	    grade_id = GradeId,        %% 奖励档次id
	    time = Time                %% 时间
    }.

init(_) ->
    %% 跨服分区活动初始化
    F1 = fun(ZoneType, Maps) ->
    	MaxId = 1,
    	maps:put(ZoneType, MaxId, Maps)
    end,
    ZoneIdMaps = lists:foldl(F1, #{}, ?ZONE_TYPE_LIST),
    ZoneActList = lib_draw_record_api:get_kf_zone_act_list(),
    F2 = fun(ActType, TmpZoneMaps) ->
    	ZoneType = data_clusters_zone:get_zone_type(?MOD_AC_CUSTOM, ActType),
    	MaxId = maps:get(ZoneType, ZoneIdMaps, 1),
    	ZoneIds = lists:seq(1, MaxId),
        F3 = fun(ZoneId, Maps) ->
    	    KfDrawRecordMaps = do_init(ZoneType, ?MOD_AC_CUSTOM, ActType, ZoneId),
    	    maps:put({ZoneType, ZoneId}, KfDrawRecordMaps, Maps)
    	end,
    	lists:foldl(F3, TmpZoneMaps, ZoneIds)
    end,
    TmpZoneMaps = lists:foldl(F2, #{}, ZoneActList),
    %% 跨服全服活动初始化
    WholeActList = lib_draw_record_api:get_kf_whole_act_list(),
    F4 = fun(ActType, List) ->
        TmpList = db_kf_whole_draw_record_select(ActType),
        List ++ TmpList
    end,
    List = lists:foldl(F4, [], WholeActList),
    KfDrawRecordMaps = do_init_core(List),
    ZoneMaps = maps:put({0, 0}, KfDrawRecordMaps, TmpZoneMaps),
    #kf_draw_record_state{zone_max_id = ZoneIdMaps, zone_maps = ZoneMaps}.

do_init(_ZoneType, ?MOD_AC_CUSTOM, ActType, _ZoneId) ->
    ServerIds = [],
    F1 = fun(ServerId, List) ->
    	TmpList = db_kf_draw_record_select(ActType, ServerId),
    	TmpList ++ List
    end,
    List1 = lists:foldl(F1, [], ServerIds),
    do_init_core(List1).

do_init_core(List) ->
    TmpDrawRecordList = [make_record(kf_draw_role,
                         [Type, SubType, RoleId, ServerId, util:bitstring_to_term(Platform), ServerNum, util:bitstring_to_term(RoleName),
                          GradeId, Time]) || [Type, SubType, RoleId, ServerId, Platform, ServerNum, RoleName, GradeId, Time] <- List],
%    DrawRecordList = lists:keysort(#kf_draw_role.time, TmpDrawRecordList),
    DrawRecordList = record_sort(TmpDrawRecordList),
    F = fun(#kf_draw_role{type = Type, sub_type = SubType} = KfDrawRecord, AccMap) ->
        case maps:get({Type, SubType}, AccMap, false) of
            false ->
                TmpL = [];
            TmpL ->
                skip
        end,
        LengthLimit = lib_draw_record_api:get_upper_limit_length(Type, SubType),
        if
            length(TmpL) >= LengthLimit ->
                AccMap;
            true ->
                NewList = [KfDrawRecord | lists:reverse(TmpL)],
                maps:put({Type, SubType}, lists:reverse(NewList), AccMap)
        end
    end,
    lists:foldl(F, #{}, DrawRecordList).

record_sort(DrawRecordList) ->
    F = fun(A, B) ->
        A#kf_draw_role.time > B#kf_draw_role.time
    end,
    lists:sort(F, DrawRecordList).

%% 刷新记录
refresh_draw_reward_record(#kf_draw_role{type = Type, sub_type = SubType, server_id = ServerId} = KfDrawRecord, State) ->
    #kf_draw_record_state{zone_maps = ZoneMaps} = State,
    {ZoneType, ZoneId} = get_act_zone_info(Type, ServerId),
    KfDrawRecordMaps = maps:get({ZoneType, ZoneId}, ZoneMaps, #{}),
    TmpList = maps:get({Type, SubType}, KfDrawRecordMaps, []),
    NewList = lists:sublist([KfDrawRecord | TmpList], lib_draw_record_api:get_upper_limit_length(Type, SubType)),
    NewKfDrawRecordMaps = maps:put({Type, SubType}, NewList, KfDrawRecordMaps),
    NewZoneMaps = maps:put({ZoneType, ZoneId}, NewKfDrawRecordMaps, ZoneMaps),
    db_kf_draw_record_insert(KfDrawRecord),
    State#kf_draw_record_state{zone_maps = NewZoneMaps}.

%% 发送记录 有特殊要求可根据活动类型进行特殊处理
send_draw_reward_record(RoleId, Type, SubType, ServerId, PersonalRecords, State) ->
    #kf_draw_record_state{zone_maps = ZoneMaps} = State,
    {ZoneType, ZoneId} = get_act_zone_info(Type, ServerId),
    case maps:get({ZoneType, ZoneId}, ZoneMaps, false) of
    	false ->
    		AllDrawRecordList = [];
    	KfDrawRecordMaps ->
    	    case maps:get({Type, SubType}, KfDrawRecordMaps, false) of
    	    	false ->
    	    		AllDrawRecordList = [];
    	    	AllDrawRecordList ->
    	    	    skip
    	    end
    end,
    List1 = pack_gift_record(PersonalRecords, []),
    List2 = pack_gift_record(AllDrawRecordList, []),
    {ok, BinData} = pt_332:write(33211, [Type, SubType, RoleId, List1, List2]),
    lib_server_send:send_to_uid(RoleId, BinData).

pack_gift_record([], List) -> List;
pack_gift_record([DrawRecord| L], List) ->
    case DrawRecord of
        #kf_draw_role{server_id = ServerId, platform = Platform, server_num = ServerNum,
                      name = RoleName, grade_id = GradeId, time = Time} ->
            pack_gift_record(L, [{ServerId, Platform, ServerNum, RoleName, GradeId, Time} | List]);
        #draw_role{grade_id = GradeId, time = Time} ->
            pack_gift_record(L, [{GradeId, Time} | List]);
        _ ->
            pack_gift_record(L, List)
    end.

%% 清除活动记录 转到玩家进程清除玩家个人数据
act_end(Type, SubType, State) ->
    KfActZoneList = lib_draw_record_api:get_kf_zone_act_list(),
    KfActWholeList = lib_draw_record_api:get_kf_whole_act_list(),
    KfActList = KfActZoneList ++ KfActWholeList,
    case lists:member(Type, KfActList) of
        true ->
            act_end_core(Type, SubType, State);
        false ->
            State
    end.

act_end_core(Type, SubType, State) ->
    #kf_draw_record_state{zone_max_id = ZoneIdMaps, zone_maps = ZoneMaps} = State,
    ZoneType = get_act_zone_type(Type),
    case ZoneType of
        0 ->
            MaxId = 0;
        _ ->
            MaxId = maps:get(ZoneType, ZoneIdMaps, 1)
    end,
    ZoneIds = lists:seq(1, MaxId),
    spawn(fun()-> db_kf_draw_record_delete(Type, SubType, ZoneIds) end),
    F1 = fun(ZoneId, TmpZoneMaps) ->
        case maps:get({ZoneType, ZoneId}, TmpZoneMaps, false) of
            false ->
                TmpZoneMaps;
            KfDrawRecordMaps ->
                NewKfDrawRecordMaps = maps:remove({Type, SubType}, KfDrawRecordMaps),
                maps:put({ZoneType, ZoneId}, NewKfDrawRecordMaps, TmpZoneMaps)
        end
    end,
    NewZoneMaps = lists:foldl(F1, ZoneMaps, ZoneIds),
    clusters_center:apply_to_all_node(lib_draw_record_mod_kf, kf_act_end_local, [Type, SubType]),
    State#kf_draw_record_state{zone_maps = NewZoneMaps}.

%% 游戏服节点进程
kf_act_end_local(Type, SubType) ->
    db_kf_draw_record_local_delete(Type, SubType),
    OnlineList = ets:tab2list(?ETS_ONLINE),
    IdList = [[PlayerId, draw_record_kf, Type, SubType] || #ets_online{id = PlayerId}<-OnlineList],
    lists:foreach(fun do_act_end/1, IdList).

%% 转到玩家进程清除玩家个人记录
do_act_end([PlayerId, Atom, Type, SubType]) ->
    lib_player:apply_cast(PlayerId, 2, lib_draw_record, reset, [Atom, Type, SubType]).

%% 获取活动分区类型、分区ID, 全服活动默认{0,0}
get_act_zone_info(Type, _ServerId) ->
    IsZoneAct = lists:member(Type, lib_draw_record_api:get_kf_zone_act_list()),
    case IsZoneAct of
        true ->
            ZoneType = data_clusters_zone:get_zone_type(?MOD_AC_CUSTOM, Type),
            ZoneId = 1,
            {ZoneType, ZoneId};
        _ ->
            {0, 0}
    end.

get_act_zone_type(Type) ->
    IsZoneAct = lists:member(Type, lib_draw_record_api:get_kf_zone_act_list()),
    case IsZoneAct of
        true ->
            ZoneType = data_clusters_zone:get_zone_type(?MOD_AC_CUSTOM, Type),
            ZoneType;
        _ ->
            0
    end.

%% -------------------------------- db ---------------------------------------
db_kf_draw_record_select(Type, ServerId) ->
    SQL = io_lib:format(?sql_custom_act_draw_record_kf_select, [Type, ServerId]),
    db:get_all(SQL).
db_kf_whole_draw_record_select(Type) ->
    SQL = io_lib:format(?sql_custom_act_draw_record_kf_whole_select, [Type]),
    db:get_all(SQL).
db_kf_draw_record_delete(Type, SubType, ZoneIds) ->
    F1 = fun(ZoneId) ->
        case ZoneId of
            0 ->
                SQL = io_lib:format(?sql_custom_act_draw_record_role_kf_whole_delete, [Type, SubType]),
                db:execute(SQL),
                timer:sleep(300);
            _ ->
                ServerIds = [],
                F2 = fun(ServerId) ->
                    SQL = io_lib:format(?sql_custom_act_draw_record_role_kf_delete, [Type, SubType, ServerId]),
                    db:execute(SQL),
                    timer:sleep(300)
                end,
                lists:foreach(F2, ServerIds)
        end
    end,
    lists:foreach(F1, ZoneIds).
db_kf_draw_record_insert(KfDrawRecord) ->
    #kf_draw_role{
        type = Type,
        sub_type = SubType,
        role_id = RoleId,
        server_id = ServerId,
        platform = Platform,
        server_num = ServerNum,
        name = RoleName,
        grade_id = GradeId
    } = KfDrawRecord,
    SQL = io_lib:format(?sql_custom_act_draw_record_role_kf_insert,
                        [Type, SubType, RoleId, ServerId, util:term_to_bitstring(Platform), ServerNum, util:term_to_bitstring(RoleName), GradeId, utime:unixtime()]),
    db:execute(SQL).
db_kf_draw_record_local_delete(Type, SubType) ->
    SQL = io_lib:format(?sql_kf_draw_record_local_delete, [Type, SubType]),
    db:execute(SQL).
