%% -------------------------------------
%% desc     :定制活动-合成机
%% module   :custom_act_printer_draw.erl
%% author   :hh
%% time     :20/10/23
%% -------------------------------------

-module(custom_act_printer_draw).

-export ([
    collect/4
    ,my_collect/2
    ,composite/3
    ,achieve_callback/6
    ,get_formula/2
    ,check_formula/5
    ]).

-export([
    role_collect/4
    ,role_achieve_callback/6
    ]).

-include ("custom_act.hrl").
-include ("server.hrl").
-include ("common.hrl").
-include ("errcode.hrl").
-include ("def_fun.hrl").
-include ("def_goods.hrl").
-include ("predefine.hrl").
-include ("printer_draw.hrl").
-include ("figure.hrl").

-define (UNCOLLECT, 0).
-define (COLLECT,   1).

%% 收藏配方
collect(RoleId, SubType, Type, Id) ->
    lib_player:apply_cast(RoleId, ?APPLY_CAST_STATUS, ?MODULE, role_collect, [SubType, Type, Id]),
    ok.

%% 查看我的收藏
my_collect(Player, SubType) ->
    #player_status{sid = Sid} = Player,
    Type = ?CUSTOM_ACT_TYPE_PRINTER_DRAW,
    case is_opening_act(Type, SubType) of
        true ->
            #custom_act_data{act_data = ActData} = lib_custom_act_data:custom_act_data(Type, SubType),
            CollectList =
            case ActData of
                #custom_act_printer_draw{collect_list = C} -> C;
                _   -> []
            end,
            lib_server_send:send_to_sid(Sid, pt_332, 33294, [SubType, CollectList]),
            ok;
        _ ->
            lib_server_send:send_to_sid(Sid, pt_332, 33294, [SubType, []]),
            ok
    end.

%% 合成
composite(Player, SubType, GoodsList) ->
    #player_status{id = RoleId, sid = Sid} = Player,
    Type = ?CUSTOM_ACT_TYPE_PRINTER_DRAW,
    case is_opening_act(Type, SubType) of
        true ->
            #custom_act_data{act_data = ActData} = CustomData = lib_custom_act_data:custom_act_data(Type, SubType),
            ActData1 =
            case ActData of
                #custom_act_printer_draw{} -> ActData;
                _   -> #custom_act_printer_draw{}
            end,
            {Errcode, NewPlayer, ActData2} = composite_do(Player, ActData1, Type, SubType, GoodsList),
            NewCustomData = CustomData#custom_act_data{act_data = ActData2},
            ?IF(NewCustomData =/= CustomData, lib_custom_act_data:save_custom_data(RoleId, NewCustomData), skip),
            Errcode1 = ?SUCCESS,
            if  Errcode1 =/= Errcode ->
                    lib_server_send:send_to_sid(Sid, pt_332, 33295, [Errcode, SubType, []]);
                true ->
                    skip
            end,
            {ok, NewPlayer};
        _ ->
            lib_server_send:send_to_sid(Sid, pt_332, 33295, [?ERRCODE(err331_act_closed), SubType, []]),
            ok
    end.

achieve_callback(RoleId, SubType, ItemSuit, Id, PoolId, IsNewAchieve) ->
    lib_player:apply_cast(RoleId, ?APPLY_CAST_STATUS, ?MODULE, role_achieve_callback, [SubType, ItemSuit, Id, PoolId, IsNewAchieve]).

role_achieve_callback(Player, SubType, ItemSuit, _Id, PoolId, IsNewAchieve) ->
    #player_status{id = RoleId, sid = Sid, figure = #figure{lv = Lv, vip = Vip}} = Player,
    {PosIds, RandGoods} = calc_composite_goods(SubType, PoolId, ItemSuit, IsNewAchieve),
    NewPlayer = lib_goods_api:send_reward(Player, RandGoods, printer_draw_reward),
    %% 日志
    Type = ?CUSTOM_ACT_TYPE_PRINTER_DRAW,
    NowTime = utime:unixtime(),
    PosLen  = length(PosIds),
    if PosLen >= 1 -> [LogPos|_] = PosIds;
        true -> LogPos = 0
    end,
    WLv = util:get_world_lv(),
    ExtraArgs = util:term_to_bitstring(PosIds),
    lib_log_api:log_custom_act_reward(RoleId, Type, SubType, LogPos, WLv, RandGoods, ExtraArgs,
        Vip, Lv, Player#player_status.gold, NewPlayer#player_status.gold, Player#player_status.bgold, NewPlayer#player_status.bgold, NowTime),
    Rewards1 = [{GoodsIdx, GoodsNum} || {_, GoodsIdx, GoodsNum} <- RandGoods],
    lib_server_send:send_to_sid(Sid, pt_332, 33295, [?SUCCESS, SubType, Rewards1]),
    {ok, NewPlayer}.

%% 获取配方
get_formula(Player, SubType) ->
    #player_status{id = RoleId, sid = Sid} = Player,
    Type = ?CUSTOM_ACT_TYPE_PRINTER_DRAW,
    #custom_act_cfg{condition = Condition} = lib_custom_act_util:get_act_cfg_info(Type, SubType),
    ItemSuitRet = check_item_suit_cfg(Condition),
    OpenRet = is_opening_act(Type, SubType),
    if 
        not OpenRet ->
            lib_server_send:send_to_sid(Sid, pt_332, 33296, [SubType, 0, []]);
        not ItemSuitRet ->
            lib_server_send:send_to_sid(Sid, pt_332, 33296, [SubType, 0, []]);
        true ->
            #custom_act_data{act_data = ActData} = lib_custom_act_data:custom_act_data(Type, SubType),
            ActData1 =
            case ActData of
                #custom_act_printer_draw{} -> ActData;
                _   -> #custom_act_printer_draw{}
            end,
            #custom_act_printer_draw{draw_list = DrawList} = ActData1,
            printer_draw:get_formula(RoleId, SubType, ItemSuitRet, DrawList),
            ok
    end.

%% 配方检查
check_formula(SubType, RoleId1, RoleId2, ChatType, Id) ->
    Type = ?CUSTOM_ACT_TYPE_PRINTER_DRAW,
    case is_opening_act(Type, SubType) of
        true ->
            #custom_act_data{act_data = ActData} = lib_custom_act_data:custom_act_data(Type, SubType),
            DrawList =
            case ActData of
                #custom_act_printer_draw{draw_list = D} -> D;
                _   -> []
            end,
            IsUnlockDraw = lists:member(Id, DrawList),
            if ChatType == 0 andalso IsUnlockDraw ->
                    lib_server_send:send_to_uid(RoleId2, pt_332, 33292, [?ERRCODE(err331_have_unlocked_formula), SubType, ChatType, Id, RoleId1]);
                ChatType == 1 andalso not IsUnlockDraw ->
                    lib_server_send:send_to_uid(RoleId2, pt_332, 33292, [?ERRCODE(err331_have_not_unlocked_formula), SubType, ChatType, Id, RoleId1]);
                true ->
                    printer_draw:chat(SubType, RoleId1, RoleId2, ChatType, Id)
            end;
        _ ->
            lib_server_send:send_to_uid(RoleId2, pt_332, 33292, [?ERRCODE(err331_act_closed), SubType, ChatType, Id, RoleId1])
    end.

composite_do(Player, ActData, Type, SubType, GoodsList) ->
    #custom_act_cfg{condition = Condition} = lib_custom_act_util:get_act_cfg_info(Type, SubType),
    ItemSuitRet    = check_item_suit_cfg(Condition),
    GoodsFormatRet = check_goods_format(GoodsList),
    if 
        not ItemSuitRet ->
            {?MISSING_CONFIG, Player, ActData};
        not GoodsFormatRet ->
            {?FAIL, Player, ActData};
        true ->
            CostGoods = [{?TYPE_GOODS, GoodsId, GoodsNum} || {GoodsId, GoodsNum} <- GoodsList],
            case lib_goods_api:cost_object_list_with_check(Player, CostGoods, printer_draw_cost, "") of
                {true, NewPlayer, _}  ->
                    {Id, PoolId} = calc_match_composite(GoodsList, ItemSuitRet),
                    % RandGoods    = calc_composite_goods(PoolId, ItemSuitRet),
                    % NewPlayer1   = lib_goods_api:send_reward(NewPlayer, RandGoods, printer_draw_reward),
                    #custom_act_printer_draw{draw_list = DrawList} = ActData,
                    %% 是否发现新配方
                    {_NewFormula, NewDrawList} = 
                    case lists:member(Id, DrawList) of
                        true -> {false, DrawList};
                        false when Id =/= 0 -> {true, [Id|DrawList]};
                        false -> {false, DrawList}
                    end,
                    printer_draw:achieve(NewPlayer#player_status.id, SubType, ItemSuitRet, Id, PoolId),
                    NewActData = ActData#custom_act_printer_draw{draw_list = NewDrawList},
                    {?SUCCESS, NewPlayer, NewActData};
                {false, Errcode, NewPlayer} ->
                    {Errcode, NewPlayer, ActData}
            end
    end.

%% 随机配方奖励|非配方奖励
calc_composite_goods(SubType, PoolId, Item, IsNewAchieve) ->
    AllIds = data_printer_draw:get_all_pools(),
    Opday  = util:get_open_day(),
    Count = get_composite_count(SubType, IsNewAchieve),
    PoolIds = lists:foldl(fun(IdX, Acc) -> 
        case data_printer_draw:get_pool_cfg(IdX) of
            #base_printer_draw_pool{pool = PoolId, pool_type = Item, weight = Weight, goods = Rewards, opday = CfDay}
             when PoolId == 0 andalso Opday >= CfDay -> %% 非配方
                [{Weight, {PoolId, Rewards}}|Acc];
            #base_printer_draw_pool{pool = PoolId, pool_type = Item, weight = Weight, goods = Rewards, opday = CfDay}
             when Opday >= CfDay -> %% 配方
                [{Weight, {PoolId, Rewards}}|Acc];
            _ -> Acc
        end
    end, [], AllIds),
    ChosenRandGoods = lists:map(fun(_) -> 
        case urand:rand_with_weight(PoolIds) of
            {PosIdx, RandGoods = [_|_]} -> {PosIdx, RandGoods};
            _ -> {0, []}
        end
    end, lists:duplicate(Count, 1)),
    {AllPosIds, AllRandGoods} =
    lists:foldl(fun({PosId1, RandGoods1}, {PosIdx, RandGoodsx}) -> 
        {[PosId1|PosIdx], lists:append(RandGoods1, RandGoodsx)}
    end, {[], []}, ChosenRandGoods),
    {AllPosIds, AllRandGoods}.

get_composite_count(SubType, IsNewAchieve) ->
    Type = ?CUSTOM_ACT_TYPE_PRINTER_DRAW,
    ActCfg = lib_custom_act_util:get_act_cfg_info(Type, SubType),
    case ActCfg of 
        #custom_act_cfg{condition = Condition} -> ok;
        _ -> Condition = [{discover_bonus, 1}]
    end,
    case lib_custom_act_check:check_act_condtion([discover_bonus], Condition) of
        [Count|_] when IsNewAchieve -> Count;
        _   -> 1
    end.

check_item_suit_cfg(Condition) ->
    case lists:keyfind(item_suit, 1, Condition) of
        {_, Item} -> Item;
        _         -> false
    end.

check_goods_format([]) -> false;
check_goods_format(GoodsList) ->
    Ret1 = check_goods_format_1(GoodsList),
    Ret2 = check_goods_num_format(GoodsList),
    Ret1 andalso Ret2.

check_goods_format_1([]) -> true;
check_goods_format_1([{_GoodsId, _Num}|Rest]) ->
    check_goods_format_1(Rest);
check_goods_format_1([_|_Rest]) ->
    false.

check_goods_num_format(GoodsList) ->
    lists:sum([Num || {_GoodsId, Num} <- GoodsList, _GoodsId =/= 0]) == 3.

%% 寻找合适的配方
calc_match_composite(GoodsList, ItemSuitRet) when is_integer(ItemSuitRet) andalso ItemSuitRet =/= 0 ->
    GoodsList1 = lists:flatten([composite_goods(GoodsId, Num) || {GoodsId, Num} <- GoodsList]),
    GoodsList2 = lists:sort(GoodsList1),
    AllIds = data_printer_draw:get_all_printers_1(),
    PrinterIds = lists:foldl(fun(PrinterId, Acc) -> 
         case data_printer_draw:get_printer_draw(PrinterId) of
            #base_printer_draw_list{item_suit = ItemSuit, pool = PoolIdX, exchange = CfgGoodsList}
             when ItemSuit == ItemSuitRet ->
                CfgGoodsList1 = lists:sort(CfgGoodsList),
                if GoodsList2 == CfgGoodsList1 -> 
                    [{PrinterId, PoolIdX}|Acc];
                    true -> Acc
                end;
            _ -> Acc
        end
    end, [], AllIds),
    case PrinterIds of
        [{Id, PoolId}|_] -> {Id, PoolId};
        _      -> {0, 0}
    end;
calc_match_composite(_, _) ->
    {0, 0}.

composite_goods(GoodsId, Num) ->
    lists:duplicate(Num, GoodsId).


role_collect(Player, SubType, CollectType, Id) ->
    #player_status{id = RoleId, sid = Sid} = Player,
    Type = ?CUSTOM_ACT_TYPE_PRINTER_DRAW,
    case is_opening_act(Type, SubType) of
        true ->
            #custom_act_data{act_data = ActData} = CustomData = lib_custom_act_data:custom_act_data(Type, SubType),
            NewActData =
            case ActData of
                #custom_act_printer_draw{} -> ActData;
                _   -> #custom_act_printer_draw{}
            end,
            {Errcode, NewActData1} = role_collect_do(NewActData, CollectType, Id),
            NewCustomData = CustomData#custom_act_data{act_data = NewActData1},
            ?IF(NewCustomData =/= CustomData, lib_custom_act_data:save_custom_data(RoleId, NewCustomData), skip),
            lib_server_send:send_to_sid(Sid, pt_332, 33293, [Errcode, SubType, CollectType, Id]);
        _ ->
            lib_server_send:send_to_sid(Sid, pt_332, 33293, [?ERRCODE(err331_act_closed), SubType, CollectType, Id])
    end.

role_collect_do(ActData, CollectType, Id) ->
    #custom_act_printer_draw{
        draw_list = DrawList, collect_list = CollectList
    } = ActData,
    case lists:member(Id, DrawList) of
        true ->
            if CollectType == ?UNCOLLECT ->
                    NewCollectList = lists:delete(Id, CollectList);
                CollectType == ?COLLECT ->
                    NewCollectList = [Id|CollectList];
                true ->
                    NewCollectList = CollectList
            end,
            {?SUCCESS, ActData#custom_act_printer_draw{collect_list = NewCollectList}};
        _ ->
            {?ERRCODE(err331_have_not_unlocked_formula), ActData}
    end.

is_opening_act(Type, SubType) ->
    lib_custom_act_api:is_open_act(Type, SubType).