%% -----------------------------------------------------
%% @author  :ljy
%% moudle   :permit_active.erl
%% desc     :活跃通行证
%% time     :2020.12.09
%% ------------------------------------------------------
-module(permit_active).

-include("server.hrl").
-include("custom_act.hrl").
-include("errcode.hrl").
-include("permit.hrl").
-include("figure.hrl").
-include("def_goods.hrl").
-include("def_module.hrl").
-include("pass_codex.hrl").
-include("def_fun.hrl").
-include("predefine.hrl").
-include("act_adventure.hrl").
-include("common.hrl").

%% API
-export([
    permit_info/2
    , reward_info/2
    , add_active/2
    , check/1
    , receive_reward/2
    , buy_ace_permit/2
    , act_end/1                               %% 活动结束
    , send_act_end_reward/3                   %% 给在线玩家补发未领取奖励
]).

%% 获取宝典活动信息
permit_info(Player, SubType) ->
    #player_status{id = RoleId, sid = Sid} = Player,
    case lib_custom_act_util:get_custom_act_open_info(?CUSTOM_ACT_TYPE_PERMIT_ACTIVE, SubType) of
        #act_info{} ->
            {_CustomData, ActData} = get_act_data(RoleId, SubType),
            {ok, BinData} = pack_permit_info(SubType, ActData),
            lib_server_send:send_to_sid(Sid, BinData),
            ok;
        _ ->
            {ok, BinData} = pt_332:write(33238, [?ERRCODE(err331_act_closed), SubType, 0, 0, 0, []]),
            lib_server_send:send_to_sid(Sid, BinData)
    end.

%% 打包宝典活动信息
pack_permit_info(SubType, ActData) ->
    #permit_active{
        active = Active,
        pay_permit = IsPay,
        normal_reward = NormalReward,
        pay_reward = PayReward
    } = ActData,
    ActType = ?CUSTOM_ACT_TYPE_PERMIT_ACTIVE,
    GradeIds = data_pass_codex:get_act_lv(ActType, SubType),
    F = fun(GradeId, Acc) ->
        NeedActive = data_pass_codex:get_lv_exp(ActType, SubType, GradeId),
        if
            is_integer(NeedActive) andalso Active >= NeedActive ->
                NormalStatus =
                    case lists:member(GradeId, NormalReward) of
                        true -> ?REWARD_2;
                        _ -> ?REWARD_1
                    end,
                PayStatus =
                    case lists:member(GradeId, PayReward) of
                        true -> ?REWARD_2;
                        _ ->
                            if IsPay == 1 -> ?REWARD_1;
                                true -> ?REWARD_0
                            end
                    end,
                [{GradeId, NeedActive, NormalStatus, PayStatus} | Acc];
            true ->
                [{GradeId, 0, ?REWARD_0, ?REWARD_0} | Acc]
        end
        end,
    RewardInfo = lists:foldl(F, [], GradeIds),
    pt_332:write(33283, [?SUCCESS, ActType, SubType, Active, IsPay, RewardInfo]).

%% 奖励信息
reward_info(Player, SubType) ->
    #player_status{sid = Sid} = Player,
    ActType = ?CUSTOM_ACT_TYPE_PERMIT_ACTIVE,
    case lib_custom_act_util:get_custom_act_open_info(ActType, SubType) of
        #act_info{key = {_, SubType}} ->
            {ok, BinData} = pack_reward_info(SubType),
            lib_server_send:send_to_sid(Sid, BinData);
        _ ->
            {ok, BinData} = pt_332:write(33286, [?ERRCODE(err331_act_closed), ActType, SubType, []]),
            lib_server_send:send_to_sid(Sid, BinData)
    end.

%% 打包奖励信息
pack_reward_info(SubType) ->
    ActType = ?CUSTOM_ACT_TYPE_PERMIT_ACTIVE,
    GradeList = data_pass_codex:get_act_lv(ActType, SubType),
    F = fun(GradeId, {Acc, Success}) ->
        case data_pass_codex:get_reward_info(ActType, SubType, GradeId) of
            #base_pass_rewards{normal_rewards = NormalReward, lv_exp = NeedActive, trump_rewards = TrumpRewards, node_reward = NodeReward} ->
                {[{GradeId, NeedActive, util:term_to_string(NormalReward), util:term_to_string(TrumpRewards), NodeReward} | Acc], Success};
            _ -> {Acc, 0}
        end
        end,
    {RewardInfo, IsSuccess} = lists:foldl(F, {[], 1}, GradeList),
    if
        IsSuccess == 1 andalso RewardInfo =/= [] ->
            pt_332:write(33286, [?SUCCESS, ActType, SubType, RewardInfo]);
        true ->
            pt_332:write(33286, [?MISSING_CONFIG, ActType, SubType, []])
    end.

%% 获取活动数据
get_act_data(RoleId, SubType) ->
    #custom_act_data{
        act_data = ActData
    } = CustomData = lib_custom_act_data:custom_act_data(?CUSTOM_ACT_TYPE_PERMIT_ACTIVE, SubType),
    NewActData =
        case ActData of
            #permit_active{} ->
                ActData;
            _ ->
                #permit_active{}
        end,
    if
        NewActData =/= ActData ->
            NewCustomData = CustomData#custom_act_data{act_data = NewActData},
            lib_custom_act_data:save_custom_data(RoleId, NewCustomData);
        true ->
            NewCustomData = CustomData
    end,
    {NewCustomData, NewActData}.

%% 增加活跃度
add_active(RoleId, AddActive) ->
    F = fun(SubType) ->
        case lib_custom_act_util:get_custom_act_open_info(?CUSTOM_ACT_TYPE_PERMIT_ACTIVE, SubType) of
            #act_info{} ->
                {CustomData, ActData} = get_act_data(RoleId, SubType),
                #permit_active{active = Active} = ActData,
                NewActData = ActData#permit_active{active = Active + AddActive},
                NewCustomData = CustomData#custom_act_data{act_data = NewActData},
                lib_custom_act_data:save_custom_data(RoleId, NewCustomData),
                {ok, BinData} = pack_permit_info(SubType, NewActData),
                lib_server_send:send_to_uid(RoleId, BinData),
                ok;
            _ ->
                skip
        end
        end,
    SubList = lib_custom_act_util:get_subtype_list(?CUSTOM_ACT_TYPE_PERMIT_ACTIVE),
    lists:map(F, SubList),
    ok.

%% 购买王牌宝典
buy_ace_permit(Player, SubType) ->
    #player_status{id = RoleId, sid = Sid} = Player,
    case get_role_permit(RoleId, SubType) of
        {true, #act_info{key = {_, SubType}}, ActData} ->
            CheckL = [
                {buy_cost_check, Player, ?CUSTOM_ACT_TYPE_PERMIT_ACTIVE, SubType},
                {payed_check, ActData}
            ],
            case util:check_lists(?MODULE, CheckL) of
                true ->
                    do_buy_ace_permit(Player, SubType);
                {false, Errcode} ->
                    {ok, BinData} = pt_332:write(33285, [Errcode, ?CUSTOM_ACT_TYPE_PERMIT_ACTIVE, SubType]),
                    lib_server_send:send_to_sid(Sid, BinData)
            end;
        {false, Errcode} ->
            {ok, BinData} = pt_332:write(33285, [Errcode, ?CUSTOM_ACT_TYPE_PERMIT_ACTIVE, SubType]),
            lib_server_send:send_to_sid(Sid, BinData)
    end.

%% 获取玩家活动数据
get_role_permit(RoleId, SubType) ->
    case lib_custom_act_util:get_custom_act_open_info(?CUSTOM_ACT_TYPE_PERMIT_ACTIVE, SubType) of
        ActInfo = #act_info{key = {_, SubType}} ->
            {_CustomData, ActData} = get_act_data(RoleId, SubType),
            {true, ActInfo, ActData};
        _ ->
            {false, ?ERRCODE(err331_act_closed)}
    end.

do_buy_ace_permit(Player, SubType) ->
    #player_status{id = RoleId, sid = Sid, figure = #figure{name = Name}} = Player,
    #custom_act_cfg{name = ActName, condition = Condition} = lib_custom_act_util:get_act_cfg_info(?CUSTOM_ACT_TYPE_PERMIT_ACTIVE, SubType),
    {limit_cost, Price} = lists:keyfind(limit_cost, 1, Condition),
    Cost = [{?TYPE_GOLD, 0, Price}],
    case lib_goods_api:cost_object_list_with_check(Player, Cost, ace_permit_cost, "") of
        {true, NewPlayer, _} ->
            {CustomData, ActData} = get_act_data(RoleId, SubType),
            {RewardList, SendList, NewActData} = calc_reward(RoleId, SubType, CustomData, ActData#permit_active{pay_permit = 1}, save),
            if
                SendList == [] ->
                    {ok, BinData} = pt_332:write(33284, [?ERRCODE(err331_have_contract_reward), SubType, SendList]);
                true ->
                    {ok, BinData} = pt_332:write(33284, [?SUCCESS, SubType, SendList])
            end,
            NewPlayer2 = lib_goods_api:send_reward(NewPlayer, RewardList, permit_active_reward),
            {ok, BinData2} = pt_332:write(33285, [?SUCCESS, SubType]),
            {ok, BinData3} = pack_permit_info(SubType, NewActData),
            lib_server_send:send_to_sid(Sid, <<BinData/binary, BinData2/binary, BinData3/binary>>),
            lib_chat:send_TV({all}, ?MOD_AC_CUSTOM, 38, [Name, ActName, SubType]),
            lib_log_api:custom_act_reward_log(NewPlayer, Player, ?CUSTOM_ACT_TYPE_PERMIT_ACTIVE, SubType, 0, util:term_to_bitstring([buy, SendList]), RewardList),
            {ok, NewPlayer2};
        {false, Errcode, _} ->
            {ok, BinData} = pt_332:write(33285, [Errcode, SubType]),
            lib_server_send:send_to_sid(Sid, BinData)
    end.


%% 领取等级奖励
receive_reward(Player, SubType) ->
    #player_status{id = RoleId, sid = Sid} = Player,
    CheckL = [
        {act_is_open, SubType}
    ],
    case util:check_lists(?MODULE, CheckL) of
        true ->
            {CustomActData, ActData} = get_act_data(RoleId, SubType),
            {RewardList, SendList, _NewActData} = calc_reward(RoleId, SubType, CustomActData, ActData, save),
            if
                SendList == [] ->
                    NewPlayer = Player,
                    {ok, BinData} = pt_332:write(33284, [?ERRCODE(err331_have_contract_reward), SubType, SendList]);
                true ->
                    NewPlayer = lib_goods_api:send_reward(Player, RewardList, permit_active_reward),
                    lib_log_api:custom_act_reward_log(NewPlayer, Player, ?CUSTOM_ACT_TYPE_PERMIT_ACTIVE, SubType, 0, util:term_to_bitstring(SendList), RewardList),
                    {ok, BinData} = pt_332:write(33284, [?SUCCESS, SubType, SendList])
            end,
            lib_server_send:send_to_sid(Sid, BinData),
            {ok, NewPlayer};
        {false, Errcode} ->
            {ok, BinData} = pt_332:write(33284, [Errcode, SubType, []]),
            lib_server_send:send_to_sid(Sid, BinData)
    end.

%% 计算奖励
calc_reward(RoleId, SubType, CustomActData, ActData, IsSave) ->
    #permit_active{
        normal_reward = NormalReward,
        pay_reward = PayReward,
        pay_permit = IsPay,
        active = Active
    } = ActData,
    ActType = ?CUSTOM_ACT_TYPE_PERMIT_ACTIVE,
    GradeList = data_pass_codex:get_act_lv(ActType, SubType),
    F = fun(GradeId, {NormalList, PayList, RewardList, ChangeList}) ->
        case data_pass_codex:get_reward_info(ActType, SubType, GradeId) of
            #base_pass_rewards{lv_exp = NeedActive, normal_rewards = Reward1, trump_rewards = Reward2} when Active >= NeedActive ->
                IsNormalReward = lists:member(GradeId, NormalReward),
                IsPayReward = (IsPay == 1 andalso (not lists:member(GradeId, PayReward))),
                if
                    (not IsNormalReward) andalso IsPayReward ->
                        {[GradeId | NormalList], [GradeId | PayList], Reward1 ++ Reward2 ++ RewardList, [{GradeId, 3} | ChangeList]};
                    not IsNormalReward ->
                        {[GradeId | NormalList], PayList, Reward1 ++ RewardList, [{GradeId, 1} | ChangeList]};
                    IsPayReward ->
                        {NormalList, [GradeId | PayList], Reward2 ++ RewardList, [{GradeId, 2} | ChangeList]};
                    true ->
                        {NormalList, PayList, RewardList, ChangeList}
                end;
            _ ->
                {NormalList, PayList, RewardList, ChangeList}
        end
        end,
    {NewNormalReward, NewPayReward, RewardList, SendList} = lists:foldl(F, {NormalReward, PayReward, [], []}, GradeList),
    if
        IsSave == false -> NewActData = ActData;
        true ->
            NewActData = ActData#permit_active{normal_reward = NewNormalReward, pay_reward = NewPayReward},
            lib_custom_act_data:save_custom_data(RoleId, CustomActData#custom_act_data{act_data = NewActData})
    end,
    {RewardList, SendList, NewActData}.

%% 活动结束
act_end(#act_info{key = {ActType, SubType}}) ->
    OpenLv = lib_custom_act_util:get_act_open_lv(ActType, SubType),
    SQL = io_lib:format(?SELECT_OPEN_ACT_ACTIVE_ROLES, [OpenLv]),
    Roles = lists:flatten(db:get_all(SQL)),
    [begin
         Pid = misc:get_player_process(RoleId),
         case misc:is_process_alive(Pid) of
             true ->
                 lib_player:apply_cast(Pid, ?APPLY_CAST_STATUS, ?MODULE, send_act_end_reward, [ActType, SubType]);
             false ->
                 send_offline_reward(RoleId, ActType, SubType)
         end
     end || RoleId <- Roles],
    ok.

%% 给在线玩家补发未领取奖励
send_act_end_reward(Player, ActType, SubType) ->
    #player_status{id = RoleId} = Player,
    {CustomData, ActData} = get_act_data(RoleId, SubType),
    {RewardList, _SendList, _NewActData} = calc_reward(RoleId, SubType, CustomData, ActData, false),
    send_act_end_reward(RoleId, ActType, SubType, RewardList).

%% 补发离线玩家未领取奖励
send_offline_reward(RoleId, ActType, SubType) ->
    case get_act_data(RoleId, ActType, SubType) of
        #permit_active{} = ActData ->
            {RewardList, _SendList, _NewActData} = calc_reward(RoleId, SubType, [], ActData, false),
            send_act_end_reward(RoleId, ActType, SubType, RewardList);
        _ -> skip
    end.

%% 获取离线玩家活动数据
get_act_data(RoleId, Type, SubType) ->
    SQL = io_lib:format(?SELECT_CUSTOM_ACT_DATA, [RoleId, Type, SubType]),
    case db:get_row(SQL) of
        [] -> skip;
        [BinData] ->
            ActData = util:bitstring_to_term(BinData),
            case ActData of
                #permit_active{} ->
                    ActData;
                _ -> skip
            end
    end.

%% 邮件发送奖励
send_act_end_reward(RoleId, ActType, SubType, RewardList) ->
    if
        RewardList =/= [] ->
            lib_mail_api:send_sys_mail([RoleId], ActType, SubType, utext:get(3318101), utext:get(3318102), RewardList);
        true -> skip
    end.


check({act_is_open, SubType}) ->
    case lib_custom_act_util:get_custom_act_open_info(?CUSTOM_ACT_TYPE_PERMIT_ACTIVE, SubType) of
        #act_info{} ->
            true;
        _ ->
            {false, ?ERRCODE(err331_act_closed)}
    end;
check({buy_cost_check, Player, ActType, SubType}) ->
    case lib_custom_act_util:get_act_cfg_info(ActType, SubType) of
        #custom_act_cfg{condition = Condition} ->
            case lists:keyfind(limit_cost, 1, Condition) of
                {limit_cost, Price} -> skip;
                _ -> Price = -1
            end,
            if
                Price >= 0 ->
                    lib_goods_api:check_object_list(Player, [{?TYPE_GOLD, 0, Price}]);
                true ->
                    {false, ?ERRCODE(config_err)}
            end;
        _ ->
            {false, ?ERRCODE(config_err)}
    end;
check({payed_check, ActData}) ->
    #permit_active{pay_permit = IsPay} = ActData,
    if IsPay =/= 0 ->
        {false, ?ERRCODE(err331_contract_haved_buy)};
        true ->
            true
    end;
check(_A) ->
    {false, ?FAIL}.



