%%%-------------------------------------------------------------------
%%% @author ljy
%%% @doc
%%%     个人差异化定制活动-佣兵补给
%%% @end
%%% Created : 28. 7月 2020 17:21
%%%-------------------------------------------------------------------
-module(custom_act_sellswords_resupply).
-author("ljy").

-include("custom_act.hrl").
-include("errcode.hrl").
-include("server.hrl").
-include("def_goods.hrl").
-include("common.hrl").
-include("figure.hrl").
-include("rec_recharge.hrl").
-include("def_recharge.hrl").
-include("def_module.hrl").
-include("dungeon.hrl").
-include("dungeon_galaxy.hrl").
-include("warsoul.hrl").
-include("def_fun.hrl").
-include("rec_event.hrl").
-include("def_event.hrl").

%% API
-export([
    login_load_data/1,
    receive_reward/4,
    check_reward_receive_times/3,
    calc_open_count/1,
    count_receive_times/3,
    end_sub_act/3,
    update_personal_act_data/4,
    warsoul_evolution/2
]).

login_load_data(Player) ->
    #player_status{
        id = RoleId,
        status_custom_act = StatusCustomAct
    } = Player,
    #status_custom_act{
        custom_act_personal = CustomActPerson
    } = StatusCustomAct,
    case db:get_row(?select_custom_act_personal_data, [RoleId]) of
        [] ->
            NPlayer = init_extra_data(Player, CustomActPerson);
        [Data] ->
            ExtraData = util:bitstring_to_term(Data),
            NStatusCustomAct = StatusCustomAct#status_custom_act{custom_act_personal = CustomActPerson, extra_data = ExtraData},
            NPlayer = Player#player_status{status_custom_act = NStatusCustomAct}
    end,
    NPlayer.

%% @doc 活动派发接口：购买礼包
receive_reward(Player, Type, SubType, GradeId) ->
    case receive_reward_do(Player, Type, SubType, GradeId) of
        {true, Player1, ActInfo, Reward} ->
            Player2 = lib_goods_api:send_reward(Player1, Reward, custom_act),
            #player_status{figure = #figure{lv = Lv, vip = Vip}} = Player2,
            lib_log_api:log_custom_act_reward(Player2#player_status.id, Type, SubType, GradeId, 0, Reward, [],
                Vip, Lv, Player#player_status.gold, Player2#player_status.gold, Player#player_status.bgold, Player2#player_status.bgold, utime:unixtime()),
            {ok, BinData} = pt_331:write(33105, [?SUCCESS, Type, SubType, GradeId]),
            lib_custom_act_do_normal:send_reward_status(Player2, ActInfo),
            lib_server_send:send_to_sid(Player2#player_status.sid, BinData),
            {ok, Player2};
        {false, Error} ->
            {ok, BinData} = pt_331:write(33105, [Error, Type, SubType, GradeId]),
            lib_server_send:send_to_sid(Player#player_status.sid, BinData),
            ok
    end.

%% 购买
receive_reward_do(Player, Type, SubType, GradeId) ->
    case custom_act_personal:is_personal_act_open(Player, Type, SubType) of
        {true, ActInfo} ->
            #custom_act_reward_cfg{condition = Condition} = lib_custom_act_util:get_act_reward_cfg_info(Type, SubType, GradeId),
            LimitTimes = case lists:keyfind(limit_times, 1, Condition) of
                             {limit_times, Times} -> Times;
                             _ -> false
                         end,
            case lib_custom_act_check:check_receive_reward_normal(Player, ActInfo, GradeId) of
                {true, ActInfo, NewReceiveTimes, RewardList, RewardCfg} when LimitTimes =/= false ->
                    case calc_buy_price(RewardCfg) of
                        {true, Cost} when NewReceiveTimes < LimitTimes ->
                            case lib_goods_api:cost_object_list_with_check(Player, Cost, custom_act, "") of
                                {true, Player1, _} ->
                                    %% 先更新购买状态
                                    Player2 = lib_custom_act:update_receive_times(Player1, Type, SubType, GradeId, NewReceiveTimes + 1),
                                    if
                                        NewReceiveTimes + 1 >= LimitTimes ->
                                            NewPlayer = end_sub_act(Player2, Type, SubType);
                                        true -> NewPlayer = Player2
                                    end,
                                    {true, NewPlayer, ActInfo, RewardList};
                                {false, Error, _} ->
                                    {false, Error}
                            end;
                        true when NewReceiveTimes < LimitTimes ->
                            Player2 = lib_custom_act:update_receive_times(Player, Type, SubType, GradeId, NewReceiveTimes + 1),
                            if
                                NewReceiveTimes + 1 >= LimitTimes ->
                                    NewPlayer = end_sub_act(Player2, Type, SubType);
                                true -> NewPlayer = Player2
                            end,
                            {true, NewPlayer, ActInfo, RewardList};
                        false ->
                            {false, ?MISSING_CONFIG};
                        _ ->
                            {false, ?FAIL}
                    end;
                {false, Error} ->
                    {false, Error};
                _ -> {false, ?MISSING_CONFIG}
            end;
        false ->
            {false, ?ERRCODE(err331_act_closed)}
    end.

count_receive_times(Player,
        #act_info{key = {Type, SubType}},
        #custom_act_reward_cfg{grade = GradeId}) ->
    RewardMap = Player#player_status.status_custom_act#status_custom_act.reward_map,
    RewardStatus = maps:get({Type, SubType, GradeId}, RewardMap, #reward_status{}),
    RewardStatus#reward_status.receive_times;
count_receive_times(_Player, _ActInfo, _RewardCfg) -> 0.

%% 计算购买价格
calc_buy_price(RwCfg) ->
    #custom_act_reward_cfg{condition = Condition} = RwCfg,
    case lists:keyfind(limit_cost, 1, Condition) of
        {_, Price} when Price > 0 ->
            case lists:keyfind(type, 1, Condition) of
                {_, 1} -> {true, [{?TYPE_GOLD, 0, Price}]};
                {_, 2} -> {true, [{?TYPE_BGOLD, 0, Price}]};
                _ -> false
            end;
        {_, Price} when Price =:= 0 ->
            true;
        _ ->
            false
    end.

%% 已领取次数
check_reward_receive_times(Player, ActInfo, RwCfg) ->
    #player_status{status_custom_act = #status_custom_act{reward_map = RewardMap}} = Player,
    #act_info{key = {Type, SubType}} = ActInfo,
    #custom_act_reward_cfg{grade = GradeId} = RwCfg,
    case maps:get({Type, SubType, GradeId}, RewardMap, []) of
        #reward_status{receive_times = ReceiveTimes} ->
            {true, ReceiveTimes};
        _ -> {true, 0}
    end.

%% 计算已开子活动数量
calc_open_count(Player) ->
    #player_status{
        status_custom_act = StatusCustomAct
    } = Player,
    #status_custom_act{
        custom_act_personal = CustomActPerson
    } = StatusCustomAct,
    NowTime = utime:unixtime(),
    F = fun(#custom_act_personal{key = {ActType, _SubType}, e_time = EndTime}, OpenNum)
        when ActType == ?CUSTOM_ACT_TYPE_SELLSWORDS_RESUPPLY ->
        case NowTime < EndTime of
            true ->
                OpenNum + 1;
            _ ->
                OpenNum
        end;
        (_, OpenNum) ->
            OpenNum
        end,
    OpenNum = lists:foldl(F, 0, CustomActPerson),
    OpenNum.

%% 将全部礼包买完的子活动关闭掉
end_sub_act(Player, Type, SubType) ->
    RewardCfgList = lib_custom_act_util:get_act_reward_grade_list(Type, SubType),
    case custom_act_personal:is_personal_act_open(Player, Type, SubType) of
        {true, ActInfo} ->
            Predicate = fun(GradeId) ->
                LimitTimes = get_limit_times(Type, SubType, GradeId),
                case lib_custom_act_util:get_act_reward_cfg_info(Type, SubType, GradeId) of
                    RewardCfg when is_record(RewardCfg, custom_act_reward_cfg) ->
                        case check_reward_receive_times(Player, ActInfo, RewardCfg) of
                            {true, ReceiveTimes} ->
                                ReceiveTimes;
                            _ -> ReceiveTimes = 0
                        end;
                    _ -> ReceiveTimes = 0
                end,
                if
                    ReceiveTimes >= LimitTimes -> true;
                    true -> false
                end
                        end,
            Result = lists:all(Predicate, RewardCfgList),
            if
                Result ->
                    #player_status{
                        status_custom_act = StatusCustomAct
                    } = Player,
                    #status_custom_act{
                        custom_act_personal = CustomActPerson
                    } = StatusCustomAct,
                    case lists:keyfind({Type, SubType}, #custom_act_personal.key, CustomActPerson) of
                        #custom_act_personal{} = Info ->
                            EenTime = utime:unixtime(),
                            NewData = Info#custom_act_personal{e_time = EenTime},
                            SQL = io_lib:format("update custom_act_personal set e_time = ~p  where role_id = ~p and type = ~p and subtype = ~p",
                                [EenTime, Player#player_status.id, Type, SubType]),
                            db:execute(SQL),
                            NewCustomActPerson = lists:keystore({Type, SubType}, #custom_act_personal.key, CustomActPerson, NewData),
                            NewStatusCustomAct = StatusCustomAct#status_custom_act{custom_act_personal = NewCustomActPerson},
                            NewPlayer = Player#player_status{status_custom_act = NewStatusCustomAct},
                            NewPlayer;
                        _ -> Player
                    end;
                true -> Player
            end;
        _ -> Player
    end.

get_limit_times(Type, SubType, GradeId) ->
    #custom_act_reward_cfg{condition = Condition} = lib_custom_act_util:get_act_reward_cfg_info(Type, SubType, GradeId),
    case lists:keyfind(limit_times, 1, Condition) of
        {limit_times, Count} -> Count;
        _ ->
            case lists:keyfind(product, 1, Condition) of
                {product, ProductId} ->
                    case data_recharge:get_recharge_goods(ProductId) of
                        #base_recharge_goods{limit = [_, Count]} ->
                            Count;
                        _ -> 1
                    end;
                _ -> 1
            end
    end.

%% 爬塔、宠物副本N个3星通关
calc_dun_finish_num(Player) ->
    #player_status{dungeon_record = DunRecord} = Player,
    DiffList = data_tower_dun:get_all_diffcult_dun(),

    F = fun(DunId, List, {TowerTimes, PetTimes}) ->
        case data_dungeon:get_dun_type(DunId) of
            ?DUNGEON_TYPE_TOWER ->
                IsDiff = lists:member(DunId, DiffList),
                case lists:keyfind(?DUNGEON_REC_MAX_STARS, 1, List) of
                    {_, StarList} when IsDiff ->
                        StarNum = length(StarList),
                        if
                            StarNum >= 3 -> {TowerTimes+1, PetTimes};
                            true -> {TowerTimes, PetTimes}
                        end;
                    _ ->
                        {TowerTimes, PetTimes}
                end;
            ?DUNGEON_TYPE_PET ->
                case lists:keyfind(?DUNGEON_REC_MAX_STARS, 1, List) of
                    {_, StarList} ->
                        StarNum = length(StarList),
                        if
                            StarNum >= 3 -> {TowerTimes, PetTimes+1};
                            true -> {TowerTimes, PetTimes}
                        end;
                    _ ->
                        {TowerTimes, PetTimes}
                end;
            _ ->
                {TowerTimes, PetTimes}
        end
        end,
    Record =
        if
            DunRecord == undefined ->
                NewPlayer = lib_dungeon:load_dungeon_record(Player),
                #player_status{dungeon_record = NDunRecord} = NewPlayer,
                NDunRecord;
            true ->
                NewPlayer = Player,
                DunRecord
        end,
    {TowerTimes, PetTimes} = maps:fold(F, {0, 0}, Record),
    {NewPlayer, TowerTimes, PetTimes}.

%% 计算各阶段战魂数量
calc_warsoul_star(Player) ->
    #player_status{role_war_soul = RoleWarSoul} = Player,
    #role_war_soul{collect = Collect} = RoleWarSoul,
    F = fun(GoodsId, StarList) ->
        case data_warsoul:get_war_soul_info(GoodsId) of
            #base_war_soul_info{star = Star} when Star >= 5->
                case lists:keyfind(Star, 1, StarList) of
                    {_, Num} ->
                        lists:keystore(Star, 1, StarList, {Star, Num+1});
                    _ ->
                        [{Star, 1}|StarList]
                end;
            _ ->
                StarList
        end
        end,
    StarList = lists:foldl(F, [], Collect),
    StarList.

%% 处于副本第几章节（所处章节需要有通关）
calc_galaxy_dun_chapter(Player) ->
    #player_status{role_dun_galaxy_chapter = ChapterInfo, dungeon_record = DunRecord} = Player,
    #role_chapter_info{chapter_id = ChapterId} = ChapterInfo,
    case data_galaxy_dun:get_chapter_cfg(ChapterId) of
        #dun_galaxy_chapter_cfg{dun_ids = DunList} when DunList =/= [] ->
            DunId = lists:max(DunList),
            Record =
                if
                    DunRecord == undefined ->
                        #{};
                    true ->
                        DunRecord
                end,
            case maps:is_key(DunId, Record) of
                true ->
                    ChapterId;
                _ ->
                    ChapterId - 1
            end;
        _ ->
            0
    end.

%% 检查数据是否更新并触发佣兵补给活动
update_personal_act_data(Player, DunId, StarNum, ResultType) ->
    DunType = data_dungeon:get_dun_type(DunId),
    IsSave =
    if
        DunType == ?DUNGEON_TYPE_TOWER ->
            %% 爬塔只记录困难模式
            DiffList = data_tower_dun:get_all_diffcult_dun(),
            lists:member(DunId, DiffList);
        DunType == ?DUNGEON_TYPE_PET ->
            true;
        true ->
            false
    end,
    if
        ResultType =/= ?DUN_RESULT_TYPE_SUCCESS ->
            Player;
        IsSave andalso StarNum>=3 ->
            #player_status{id = RoleId, status_custom_act = StatusCustomAct} = Player,
            #status_custom_act{extra_data = ExtraData} = StatusCustomAct,
            Key = ?IF(DunType == ?DUNGEON_TYPE_TOWER,?TOWER_PASS_BEST_NUM,?PET_PASS_BEST_NUM),
            {_, Times} = lists:keyfind(Key, 1, ExtraData),
            NExtraData = lists:keystore(Key, 1, ExtraData, {Key, Times + 1}),
            Sql = io_lib:format(?update_custom_act_personal_data, [RoleId, util:term_to_bitstring(NExtraData)]),
            db:execute(Sql),
            NStatusCustomAct = StatusCustomAct#status_custom_act{extra_data = NExtraData},
            Player2 = Player#player_status{status_custom_act = NStatusCustomAct},
            NewPlayer = custom_act_personal:check_personal_act(Player2, [?CUSTOM_ACT_TYPE_SELLSWORDS_RESUPPLY], []),
            NewPlayer;
        DunType == ?DUNGEON_TYPE_GALAXY andalso StarNum>=3 ->
            #player_status{id = RoleId, role_dun_galaxy_chapter = ChapterInfo,status_custom_act = StatusCustomAct} = Player,
            #role_chapter_info{chapter_id = ChapterId} = ChapterInfo,
            #status_custom_act{extra_data = ExtraData} = StatusCustomAct,
            NChapterId =
            case data_galaxy_dun:get_chapter_cfg(ChapterId) of
                #dun_galaxy_chapter_cfg{dun_ids = DunList} when DunList =/= [] ->
                    MinDunId = lists:max(DunList),
                    if
                        DunId == MinDunId ->
                            ChapterId;
                        true ->
                            ChapterId - 1
                    end;
                _ ->
                    ChapterId
            end,
            Key = ?GALAXY_DUN_CHAPTER,
            {_, CId} = lists:keyfind(Key, 1, ExtraData),
            if
                NChapterId > CId ->
                    NExtraData = lists:keystore(Key, 1, ExtraData, {Key, NChapterId}),
                    Sql = io_lib:format(?update_custom_act_personal_data, [RoleId, util:term_to_bitstring(NExtraData)]),
                    db:execute(Sql),
                    NStatusCustomAct = StatusCustomAct#status_custom_act{extra_data = NExtraData},
                    Player2 = Player#player_status{status_custom_act = NStatusCustomAct},
                    NewPlayer = custom_act_personal:check_personal_act(Player2, [?CUSTOM_ACT_TYPE_SELLSWORDS_RESUPPLY], []),
                    NewPlayer;
                true ->
                    Player
            end;
        true ->
            Player
    end.

%% 战魂进化更新数据
warsoul_evolution(Player, GoodsId) ->
    #player_status{id = RoleId, status_custom_act = StatusCustomAct} = Player,
    #status_custom_act{extra_data = ExtraData} = StatusCustomAct,
    Key = ?WARSOUL_STAR_INFO,
    {_, StarList} = lists:keyfind(Key, 1, ExtraData),
    NStarList =
    case data_warsoul:get_war_soul_info(GoodsId) of
        #base_war_soul_info{star = Star} when Star >= 5->
            case lists:keyfind(Star, 1, StarList) of
                {_, Num} ->
                    lists:keystore(Star, 1, StarList, {Star, Num+1});
                _ ->
                    [{Star, 1}|StarList]
            end;
        _ ->
            StarList
    end,
    NExtraData = lists:keystore(Key, 1, ExtraData, {Key, NStarList}),
    Sql = io_lib:format(?update_custom_act_personal_data, [RoleId, util:term_to_bitstring(NExtraData)]),
    db:execute(Sql),
    NStatusCustomAct = StatusCustomAct#status_custom_act{extra_data = NExtraData},
    Player2 = Player#player_status{status_custom_act = NStatusCustomAct},
    NewPlayer = custom_act_personal:check_personal_act(Player2, [?CUSTOM_ACT_TYPE_SELLSWORDS_RESUPPLY], []),
    NewPlayer.

%% 初始化个人定制活动额外数据
init_extra_data(Player, CustomActPerson) ->
    #player_status{
        id = RoleId,
        status_custom_act = StatusCustomAct
    } = Player,
    F = fun(#custom_act_personal{key = {ActType, SubType}}, GiftList)
        when ActType == ?CUSTOM_ACT_TYPE_SELLSWORDS_RESUPPLY ->

                case lib_custom_act_util:get_act_cfg_info(ActType, SubType) of
                    #custom_act_cfg{condition = Cond} ->
                        skip;
                    _ ->
                        Cond = []
                end,
                case lists:keyfind(gift, 1, Cond) of
                    {gift, Gift} ->
                        [Gift|GiftList];
                    _ ->
                        GiftList
                end;
        (_, GiftList) ->
            GiftList
        end,
    GiftList = lists:foldl(F, [], CustomActPerson),
    {Player1, TowerTimes, PetTimes} = calc_dun_finish_num(Player),
    StarList = calc_warsoul_star(Player1),
    Chapter = calc_galaxy_dun_chapter(Player1),
    Data = [{?ALREADY_TRIGGER_GIFT,GiftList},{?TOWER_PASS_BEST_NUM,TowerTimes},{?PET_PASS_BEST_NUM,PetTimes},
        {?WARSOUL_STAR_INFO,StarList},{?GALAXY_DUN_CHAPTER,Chapter}],
    Sql = io_lib:format(?update_custom_act_personal_data, [RoleId, util:term_to_bitstring(Data)]),
    db:execute(Sql),
    NStatusCustomAct = StatusCustomAct#status_custom_act{custom_act_personal = CustomActPerson, extra_data = Data},
    Player2 = Player1#player_status{status_custom_act = NStatusCustomAct},
    Player2.


