%% ---------------------------------------------------------------------------
%% @doc 跨服帮战数据库操作
%% @author zhaoyu
%% @since  2018-08-29
%% ---------------------------------------------------------------------------
-module(cross_guild_war_db).

-include("cross_guild_war.hrl").
-include("common.hrl").

-export([
        save_last_zones/2
        ,delete_last_zones/0
        ,del_zones_and_save_last_zones/2
        ,load_last_zones/0
        ,load_city_info/0
        ,load_cgw_log/0
        ,save_city_info/1
        ,del_city_info/0
        ,load_guild_info/1
        ,save_guild_info/1
        ,del_guild_info/0
        ,del_guild_info/1

        ,load_guild_help_info/1
        ,save_guild_help_info/1
        ,del_guild_help_info/0

        ,load_role_cgw/1                    %% 加载角色跨服帮战应援和领取奖励记录
        ,save_role_cgw/2                    %% 保存角色跨服帮战应援和领取奖励记录
        ,del_role_cgw/0                     %% 清空角色跨服帮战应援和领取奖励记录

        ,save_city_log/3
        ,del_city_log/2
    ]).



%% ---------------------------------------------------------------------------
%% @doc 保存上一次分区信息
del_zones_and_save_last_zones(ZoneMap,FactMap) ->
    delete_last_zones(),
    save_last_zones(ZoneMap,FactMap).


%% ---------------------------------------------------------------------------
%% @doc 保存上一次分区信息
save_last_zones(ZoneMap,FactMap) ->
    SqlArgs0 = maps:to_list(ZoneMap),
    SqlArgs  = maps_to_list(SqlArgs0,FactMap,[]),
    SqlArgs =/= [] andalso db:insert_batch(?SQL_CGWAR_LAST_ZONE_UPDATE, SqlArgs),
    ok.

maps_to_list([],_,SqlArgs)->
    SqlArgs;
maps_to_list([{SerID,ZoneId}|T],FactMap,SqlArgs)->
    Fact = maps:get(SerID,FactMap,0),
    maps_to_list(T,FactMap,[[SerID,ZoneId,Fact]|SqlArgs]).

%% ---------------------------------------------------------------------------
%% @doc 删除上一次分区信息
-spec delete_last_zones() -> ok.
%% ---------------------------------------------------------------------------
delete_last_zones() ->
    db:execute("TRUNCATE TABLE cross_guild_war_last_zone"),
    ok.



%% ---------------------------------------------------------------------------
%% @doc 加载上一次分区信息
load_last_zones() ->
    case db:get_all(?SQL_CGWAR_LAST_ZONE_GET) of
        DataList when is_list(DataList) andalso DataList =/= [] ->
            Zones = [{ServerId,ZoneId}|| [ServerId,ZoneId,_FactId] <- DataList],
            Facts = [{ServerId,FactId}|| [ServerId,_ZoneId,FactId] <- DataList],
            [maps:from_list(Zones),maps:from_list(Facts)];
        _ ->
            [#{},#{}]
    end.


%% ---------------------------------------------------------------------------
%% @doc 加载城池占领信息
-spec load_city_info() -> ok.
%% ---------------------------------------------------------------------------
load_city_info() ->
    case db:get_all(?SQL_CGWAR_CITY_GET) of
        DataList when is_list(DataList) andalso DataList =/= [] ->
            Cities = [
                #cgw_city_owner_info{
                    zone_id = ZoneId, 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
                }
                || [
                    ZoneId, CityId, ServerId, ServerNum, GuildId
                    ,GuildName, GuildPower, ChiefId, ChiefName, ChiefPower
                ] <- DataList
            ],
            ZoneList = init_city_info(Cities),
            ets:insert(?CGW_CITY_ETS, ZoneList);
        _ ->
            ok
    end,
    ok.


%% ---------------------------------------------------------------------------
%% @doc 把加载的城池占领信息按分区和房间分组
-spec init_city_info(Cities) -> ZoneList when
    Cities      :: [#cgw_city_owner_info{}],
    ZoneList    :: [#cgw_zone_city_info{}].
%% ---------------------------------------------------------------------------
init_city_info(Cities) ->
    init_city_info(Cities, []).

init_city_info([], ZoneList) ->
    ZoneList;
init_city_info([City | T], ZoneList) ->
    #cgw_city_owner_info{zone_id = ZoneId} = City,
    NewZoneList = case lists:keytake(ZoneId, #cgw_zone_city_info.zone_id, ZoneList) of
        {value, Zone = #cgw_zone_city_info{city_info = Cities}, LessZones} ->
            NewZone = Zone#cgw_zone_city_info{city_info = [City | Cities]},
            [NewZone | LessZones];
        _ ->
            NewZone = #cgw_zone_city_info{zone_id=ZoneId, city_info = [City]},
            [NewZone | ZoneList]
    end,
    init_city_info(T, NewZoneList).



%% ---------------------------------------------------------------------------
%% @doc 保存城池占领信息
-spec save_city_info(ZoneCityInfoList) -> ok when
    ZoneCityInfoList      :: [#cgw_zone_city_info{}].
%% ---------------------------------------------------------------------------
save_city_info(ZoneCityInfoList) ->
    SqlArgs = save_city_args(ZoneCityInfoList, []),
    SqlArgs =/= [] andalso db:execute(io_lib:format(?SQL_CGWAR_CITYS_SAVE, [SqlArgs])),
    ok.

save_city_args([], SqlArgs) ->
    string:join(SqlArgs, ",");
save_city_args([Zone | T], SqlArgs) ->
    #cgw_zone_city_info{city_info = Cities} = Zone,
    NewSqlArgs = room_city_args(Cities, SqlArgs),
    save_city_args(T, NewSqlArgs).

%% 每个房间
room_city_args([], SqlArgs) ->
    SqlArgs;
room_city_args([City | T], SqlArgs) ->
    #cgw_city_owner_info{
        zone_id = ZoneId, 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,
    Arg = [
        ZoneId, CityId, ServerId, ServerNum, GuildId
        ,GuildName, GuildPower, ChiefId, ChiefName, ChiefPower
    ],
    DataFormat = io_lib:format(
        "(~p, ~p, ~p, ~p, ~p, '~ts', ~p, ~p, '~ts', ~p)", Arg
    ),
    NewSqlArgs = [DataFormat | SqlArgs],
    room_city_args(T, NewSqlArgs).


%% ---------------------------------------------------------------------------
%% @doc 删除城池占领信息
-spec del_city_info() -> ok.
%% ---------------------------------------------------------------------------
del_city_info() ->
    db:execute("TRUNCATE TABLE cross_guild_war_city_info"),
    ok.

%% @doc 加载帮派报名信息
load_guild_info(FactMap) ->
    case db:get_all(?SQL_CGWAR_GUILD_INFO_GET) of
        DataList when is_list(DataList) andalso DataList =/= [] ->
            GuildList = [
                #cgw_guild_info{
                    guild_id = GuildId, server_id = ServerId,fact_id=maps:get(ServerId,FactMap,0)
                    ,server_num = ServerNum, zone_id = ZoneId
                    ,guild_name = GuildName
                    ,guild_power = GuildPower, chief_id = ChiefId
                    ,chief_name = ChiefName, chief_power = ChiefPower
                    ,sign_ups = load_list_from_db(SignUps)
                    ,supports = load_list_from_db(Supports)
                    ,support_num = SupportNum
                }
                || [
                    GuildId, ZoneId, ServerId, ServerNum
                    , GuildName, GuildPower, ChiefId, ChiefName, ChiefPower
                    ,SignUps, Supports, SupportNum
                ] <- DataList
            ],
            ZoneGuildList = init_zone_guild_info(GuildList, []),
            ZoneGuildList;
        _ ->
            []
    end.

load_guild_help_info(_FactMap) ->
    case db:get_all(?SQL_CGWAR_GUILD_HELP_INFO_GET) of
        DataList when is_list(DataList) andalso DataList =/= [] ->
            GuildList = [
                #cgw_guild_info{
                    guild_id = GuildId, server_id = ServerId
                    ,zone_id = ZoneId,fact_id=GuildId
                    ,sign_ups = load_list_from_db(HelpUps)
                }
                || [
                    GuildId, ZoneId, ServerId, HelpUps
                ] <- DataList
            ],
            ZoneGuildList = init_zone_guild_info(GuildList, []),
            ZoneGuildList;
        _ ->
            []
    end.

init_zone_guild_info([], ZoneGuildList) ->
    ZoneGuildList;
init_zone_guild_info([Guild | T], ZoneGuildList) ->
    #cgw_guild_info{zone_id = ZoneId} = Guild,
    NewZoneGuildList =
    case lists:keytake(ZoneId, #cgw_zone_guild_info.zone_id, ZoneGuildList) of
        {value, Zone = #cgw_zone_guild_info{guild_list = GuildList}, LessZones} ->
            NewZone = Zone#cgw_zone_guild_info{guild_list = [Guild | GuildList]},
            [NewZone | LessZones];
        _ ->
            NewZone = #cgw_zone_guild_info{zone_id = ZoneId, guild_list = [Guild]},
            [NewZone | ZoneGuildList]
    end,
    init_zone_guild_info(T, NewZoneGuildList).

%% 从数据库加载列表数据
load_list_from_db(ListDataDb) ->
    case util:bitstring_to_term(ListDataDb) of
        DataList when is_list(DataList) ->
            DataList;
        _ ->
            ?ERR("load_list_from_db: Error string=[~p]~n", [ListDataDb]),
            []
    end.


%% ---------------------------------------------------------------------------
%% @doc 保存帮派报名信息
-spec save_guild_info(ZoneGuildList) -> ok when
    ZoneGuildList      :: [#cgw_zone_guild_info{}].
%% ---------------------------------------------------------------------------
save_guild_info(ZoneGuildList) ->
    SqlArgs = save_guild_args(ZoneGuildList, []),
    SqlArgs =/= [] andalso db:execute(io_lib:format(?SQL_CGWAR_GUILD_INFO_SAVE, [SqlArgs])),
    ok.

save_guild_args([], SqlArgs) ->
    string:join(SqlArgs, ",");
save_guild_args([Zone | T], SqlArgs) ->
    #cgw_zone_guild_info{guild_list = GuildList} = Zone,
    NewSqlArgs = zone_guild_args(GuildList, SqlArgs),
    save_guild_args(T, NewSqlArgs).
%% 每个分区
zone_guild_args([], SqlArgs) ->
    SqlArgs;
zone_guild_args([Guild | T], SqlArgs) ->
    #cgw_guild_info{
        guild_id = GuildId, server_id = ServerId
        ,server_num = ServerNum, zone_id = ZoneId
        ,guild_name = GuildName, guild_power = GuildPower
        ,chief_id = ChiefId, chief_name = ChiefName
        ,chief_power = ChiefPower, sign_ups = SignUps
        ,supports = Supports, support_num = SupportNum
    } = Guild,
    Arg = [
        GuildId, ZoneId, ServerId, ServerNum, GuildName
        ,GuildPower, ChiefId, ChiefName, ChiefPower, util:term_to_string(SignUps)
        ,util:term_to_string(Supports), SupportNum
    ],
    DataFormat = io_lib:format(
        "(~p, ~p, ~p, ~p, '~ts', ~p, ~p, '~ts', ~p, '~ts','~ts', ~p)"
        ,Arg
    ),
    NewSqlArgs = [DataFormat | SqlArgs],
    zone_guild_args(T, NewSqlArgs).



%% ---------------------------------------------------------------------------
%% @doc 保存阵营外援信息
save_guild_help_info(ZoneGuildList) ->
    SqlArgs = save_guild_help_args(ZoneGuildList, []),
    SqlArgs =/= [] andalso db:execute(io_lib:format(?SQL_CGWAR_GUILD_HELP_INFO_SAVE, [SqlArgs])),
    ok.

save_guild_help_args([], SqlArgs) ->
    string:join(SqlArgs, ",");
save_guild_help_args([Zone | T], SqlArgs) ->
    #cgw_zone_guild_info{guild_list = GuildList} = Zone,
    NewSqlArgs = zone_guild_help_args(GuildList, SqlArgs),
    save_guild_help_args(T, NewSqlArgs).
%% 每个分区
zone_guild_help_args([], SqlArgs) ->
    SqlArgs;
zone_guild_help_args([Guild | T], SqlArgs) ->
    #cgw_guild_info{
        guild_id = GuildId, server_id = ServerId
        ,zone_id = ZoneId,sign_ups=HelpUps
    } = Guild,
    Arg = [
        GuildId, ZoneId, ServerId
        ,util:term_to_string(HelpUps)
    ],
    DataFormat = io_lib:format(
        "(~p, ~p, ~p, '~ts')"
        ,Arg
    ),
    NewSqlArgs = [DataFormat | SqlArgs],
    zone_guild_help_args(T, NewSqlArgs).

%% ---------------------------------------------------------------------------
%% @doc 删除帮派报名信息
-spec del_guild_info() -> ok.
%% ---------------------------------------------------------------------------
del_guild_info() ->
    db:execute("TRUNCATE TABLE cross_guild_war_guild_info"),
    ok.

del_guild_help_info() ->
    db:execute("TRUNCATE TABLE cross_guild_war_guild_help_info"),
    ok.

%% ---------------------------------------------------------------------------
%% @doc 删除帮派报名信息
-spec del_guild_info(ZoneId) -> ok when
    ZoneId       :: integer().
%% ---------------------------------------------------------------------------
del_guild_info(ZoneId) ->
    db:execute(io_lib:format(?SQL_CGWAR_GUILD_INFO_DEL_BY_ZONE, [ZoneId])),
    ok.


%% ---------------------------------------------------------------------------
%% @doc 加载角色跨服帮战应援和领取奖励记录
-spec load_role_cgw(RoleId) -> RoleCgw when
    RoleId      :: integer(),
    RoleCgw     :: #role_cgw{}.
%% ---------------------------------------------------------------------------
load_role_cgw(RoleId) ->
    case db:get_row(io_lib:format(?SQL_CGWAR_ROLE_GET, [RoleId])) of
        [SupportNum, SupportTime, UseFreeNum, CityAward, AwardTime,LastSign] ->
            #role_cgw{
                support_num = SupportNum, support_time = SupportTime
                ,use_free_num = UseFreeNum
                ,city_award = util:bitstring_to_term(CityAward)
                ,award_time = AwardTime
                ,last_sign = LastSign
            };
        _ ->
            #role_cgw{}
    end.


%% ---------------------------------------------------------------------------
%% @doc 保存角色跨服帮战应援和领取奖励记录
-spec save_role_cgw(RoleId, RoleCgw) -> ok when
    RoleId      :: integer(),
    RoleCgw     :: #role_cgw{}.
%% ---------------------------------------------------------------------------
save_role_cgw(RoleId, RoleCgw) ->
    #role_cgw{
        support_num = SupportNum, support_time = SupportTime
        ,use_free_num = UseFreeNum, city_award = CityAward
        ,award_time = AwardTime,last_sign=LastSign
    } = RoleCgw,
    CityAwardStr = util:term_to_string(CityAward),
    Data = [RoleId, SupportNum, SupportTime, UseFreeNum, CityAwardStr, AwardTime,LastSign],
    Sql2 = io_lib:format(?SQL_CGWAR_ROLE_SAVE, Data),
    db:execute(Sql2).


%% ---------------------------------------------------------------------------
%% @doc 清空角色跨服帮战应援和领取奖励记录
-spec del_role_cgw() -> ok.
%% ---------------------------------------------------------------------------
del_role_cgw() ->
    db:execute("TRUNCATE TABLE cross_guild_war_role").

del_city_log(_ZoneId,[])->
    ok;
del_city_log(ZoneId,[H|T])->
    #times_citys{time=Time}=H,
    Sql = io_lib:format("delete from `log_cgwar_city_info` where `zone_id` = ~p and `time` <= ~p", [ZoneId,Time]),
    db:execute(Sql),
    del_city_log(ZoneId,T).

%%加载往期战报
load_cgw_log()->
     case db:get_all(?SQL_CGQWAR_LOG_GET) of
        DataList when is_list(DataList) andalso DataList =/= [] ->
            Cities = [
                #cgw_city_owner_info{
                    zone_id = ZoneId, 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,time=Time,chief_info = util:bitstring_to_term(ChiefInfo)
                }
                || [
                    _Id,ZoneId, CityId, ServerId, ServerNum, GuildId,GuildName,
                    GuildPower, ChiefId, ChiefName, ChiefPower,Time,ChiefInfo
                ] <- DataList
            ],
            ZoneList = init_city_log_info(Cities),
            ets:insert(?CGW_CITY_LOG_ETS, ZoneList);
        _ ->
            ok
    end.

init_city_log_info(Cities) ->
    init_city_log_info(Cities, []).

init_city_log_info([], ZoneList) ->
    ZoneList;
init_city_log_info([City | T], ZoneList) ->
    #cgw_city_owner_info{zone_id = ZoneId, time=Time} = City,
    NewZoneList =  case lists:keytake(ZoneId, #cgw_zone_city_log.zone_id, ZoneList) of
        {value, Zone = #cgw_zone_city_log{times_citys = TimeList}, LessZones} ->
            case lists:keytake(Time,#times_citys.time,TimeList) of
                {value,TimesCitys = #times_citys{city_info=Cities},LessTCitys}->
                    NewTimesCitys = TimesCitys#times_citys{city_info = [City|Cities]},
                    NewTimeList = [NewTimesCitys|LessTCitys],
                    NewZone = Zone#cgw_zone_city_log{times_citys=NewTimeList},
                    [NewZone | LessZones];
                _->
                    NewTimesCitys = #times_citys{time=Time,city_info = [City]},
                    NewTimeList = [NewTimesCitys],
                    NewZone = Zone#cgw_zone_city_log{zone_id=ZoneId,times_citys=NewTimeList},
                    [NewZone | LessZones]
            end;
        _ ->
            NewTimesCitys = #times_citys{time=Time,city_info = [City]},
            NewTimeList = [NewTimesCitys],
            NewZone = #cgw_zone_city_log{zone_id=ZoneId,times_citys=NewTimeList},
            [NewZone|ZoneList]
    end,
    init_city_log_info(T, NewZoneList).


%%战报保存
save_city_log(ZoneId,Time,BattleResults)->
    ZoneLog = [#cgw_zone_city_log{
        zone_id=ZoneId,
        times_citys=[#times_citys{time=Time,city_info=BattleResults}]
    }],
    SqlArgs = save_city_log_args(ZoneLog,[]),
    SqlArgs =/= [] andalso db:execute(io_lib:format(?SQL_CGQWAR_LOG_SAVE, [SqlArgs])),
    ok.

save_city_log_args([], SqlArgs) ->
    string:join(SqlArgs, ",");
save_city_log_args([Zone | T], SqlArgs) ->
    #cgw_zone_city_log{times_citys = TimesList} = Zone,
    NewSqlArgs = zone_city_log_args(TimesList, SqlArgs),
    save_city_log_args(T, NewSqlArgs).
%% 每个分区
zone_city_log_args([], SqlArgs) ->
    SqlArgs;
zone_city_log_args([TimesCity | T], SqlArgs) ->
    #times_citys{time=Time,city_info = Cities} = TimesCity,
    NewSqlArgs = zone_times_room_city_args(Cities,Time,SqlArgs),
    zone_city_log_args(T, NewSqlArgs).

%% 每个房间
zone_times_room_city_args([], _Time, SqlArgs) ->
    SqlArgs;
zone_times_room_city_args([City | T], Time, SqlArgs) ->
    #cgw_city_owner_info{
        zone_id = ZoneId, 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, chief_info = ChiefInfo
    } = City,
    Arg = [
        ZoneId, CityId, ServerId, ServerNum, GuildId,GuildName,
        GuildPower, ChiefId, ChiefName, ChiefPower,Time,util:term_to_bitstring(ChiefInfo)
    ],
    DataFormat = io_lib:format(
        "(~p, ~p, ~p, ~p, ~p, '~ts', ~p, ~p, '~ts', ~p,~p, '~ts')", Arg
    ),
    NewSqlArgs = [DataFormat | SqlArgs],
    zone_times_room_city_args(T, Time, NewSqlArgs).