%% ---------------------------------------------------------
%% Author:  xyj
%% Email:   156702030@qq.com
%% Created: 2011-12-31
%% Description: 活动礼包检查类
%% --------------------------------------------------------
-module(lib_gift_check).
-compile(export_all).
-include("def_goods.hrl").
-include("def_module.hrl").
-include("goods.hrl").
-include("gift.hrl").
-include("server.hrl").
-include("figure.hrl").
-include("vip.hrl").
-include("errcode.hrl").
-include("common.hrl").
-include("guild.hrl").

%% ================================= 礼包和的等级职业礼包 =================================
%% Return = {ok, GoodsInfo, GiftInfo, Cost} | {fail, Code} | {fail, {Code, Args}}
ckeck_use_gift(Ps, Gs, GoodsInfo, GoodsNum) when is_record(GoodsInfo, goods) ->
    case data_gift:get(GoodsInfo#goods.goods_id) of
        [] -> {fail, ?ERRCODE(err150_gift_cfg_missing)};
        GiftInfo ->
            case ckeck_use_gift(Ps, Gs, GiftInfo, GoodsNum, GoodsInfo) of
                {ok, Cost} -> {ok, GoodsInfo, GiftInfo, Cost};
                Error -> Error
            end
    end.

%% Return = {ok, GoodsInfo, GiftInfo, Cost} | {fail, Code} | {fail, {Code, Args}}
ckeck_use_gift(Ps, Gs, GiftInfo, Num, GoodsInfo) when is_record(GiftInfo, ets_gift) ->
    NowTime = utime:unixtime(),
    GoodsTypeInfo = data_goods_type:get(GiftInfo#ets_gift.goods_id) ,
    if
        GiftInfo#ets_gift.status =:= 0 ->
            {fail, ?ERRCODE(err150_gift_status_error)};
        GiftInfo#ets_gift.start_time > 0 andalso NowTime < GiftInfo#ets_gift.start_time ->
            {fail, ?ERRCODE(err150_gift_nobegin)};
        GiftInfo#ets_gift.end_time > 0 andalso NowTime > GiftInfo#ets_gift.end_time ->
            {fail, ?ERRCODE(err150_gift_overtime)};
        GoodsTypeInfo == [] ->
            {fail, ?ERRCODE(err150_no_goods)};
        true ->
            %% 筛选条件
            [Lv, Sex, Career, Turn] = get_filter_items(GiftInfo#ets_gift.filter, Ps, [0, 0, 0, 0]),
            case data_gift:get_gift_reward(GiftInfo#ets_gift.goods_id, Lv, Sex, Career, Turn) of
                [] -> {fail, ?ERRCODE(err150_gift_reward_miss)};
                GiftReward ->
                    case check_null_cell_num(Gs, GiftReward, Num) of
                        true ->
                            case check_gift_condition(GiftInfo#ets_gift.condition, GiftInfo, Ps, Num, GoodsInfo, []) of
                                {true, Cost} -> {ok, Cost};
                                Res -> Res
                            end;
                        {false, Errcode} -> {fail, Errcode}
                    end
            end
    end;
ckeck_use_gift(_Ps, _Gs, GiftInfo, Num, _GoodsInfo) ->
    ?ERR("Unkown GiftInfo:~p~n", [{GiftInfo, Num}]),
    {fail, ?ERRCODE(err150_gift_cfg_missing)}.

%% 计算礼包的筛选条件
get_filter_items([], _Ps, Result) ->
    Result;
get_filter_items([H|Filter], #player_status{figure = Figure} = Ps, [Lv, Sex, Career, Turn]) ->
    case H of
        sex ->
            get_filter_items(Filter, Ps, [Lv, Figure#figure.sex, Career, Turn]);
        career ->
            get_filter_items(Filter, Ps, [Lv, Sex, Figure#figure.career, Turn]);
        turn ->
            get_filter_items(Filter, Ps, [Lv, Sex, Career, Figure#figure.turn]);
        %% lv, server_lv
        lv ->
            get_filter_items(Filter, Ps, [Figure#figure.lv, Sex, Career, Turn]);
        server_lv -> %% 世界等级
            ServerLv = util:get_world_lv(),
            get_filter_items(Filter, Ps, [ServerLv, Sex, Career, Turn]);
        _ ->
            get_filter_items(Filter, Ps, [Lv, Sex, Career, Turn])
    end.

%% 礼包开启条件检查
check_gift_condition([], _Gift, _Ps, _Num, _GoodsInfo, Cost) -> {true, Cost};
check_gift_condition([{K, V}|Condition], Gift, Ps, Num, GoodsInfo, Cost) ->
    case K of
        cost -> %% 消耗
            NewCost = format_cost_goods(V, []),
            case lib_goods_api:check_object_list(Ps, NewCost) of
                true -> check_gift_condition(Condition, Gift, Ps, Num, GoodsInfo, NewCost);
                {false, Code} -> {fail, Code}
            end;
        count -> %% 次数判断
            UseCount = lib_daily:get_count(Ps#player_status.id, ?MOD_GOODS, ?MOD_GOODS_GIFT, Gift#ets_gift.goods_id),
            if
                UseCount >= V -> {fail, ?ERRCODE(err150_num_limit)};
                UseCount + Num > V -> {fail, ?ERRCODE(err150_num_over)};
                true -> check_gift_condition(Condition, Gift, Ps, Num, GoodsInfo, Cost)
            end;
        lv -> %% 玩家等级
            if
                V > Ps#player_status.figure#figure.lv -> {fail, ?ERRCODE(err150_lv_not_enough)};
                true -> check_gift_condition(Condition, Gift, Ps, Num, GoodsInfo, Cost)
            end;
        ctime -> %% 获得之后几天后开
            DiffDay = utime:diff_day(GoodsInfo#goods.ctime),
            case DiffDay >= V of
                false -> {fail, {?ERRCODE(err150_day_not_enough), [V - DiffDay, Gift#ets_gift.goods_id]}};
                true -> check_gift_condition(Condition, Gift, Ps, Num, GoodsInfo, Cost)
            end;
        opday ->
            Opday = util:get_open_day(),
            case V of
                [Min, Max] ->
                    case Opday >= Min andalso Opday =< Max of
                        true  ->
                            check_gift_condition(Condition, Gift, Ps, Num, GoodsInfo, Cost);
                        false ->
                            {fail, ?ERRCODE(err150_no_use)}
                    end;
                _ ->
                    {fail, 0}
            end;
        _ ->
            check_gift_condition(Condition, Gift, Ps, Num, GoodsInfo, Cost)
    end.

%% 每日名望礼包获得名望券判断(策划修改需求后,暂时不作检测)
check_can_get(Ps, GiftInfo, CostNum) ->
    #player_status{guild = StatusGuild} = Ps,
    #status_guild{position = Position} = StatusGuild,
    %% 社团职位增加量
    case data_guild:get_guild_pos(Position) of
        #base_guild_pos{reputation_add = DailyAdd} -> skip;
        _ -> DailyAdd = 0
    end,
    [Lv, Sex, Career, Turn] = get_filter_items(GiftInfo#ets_gift.filter, Ps, [0, 0, 0, 0]),
    case {GiftInfo#ets_gift.goods_id, CostNum} of
        {101015, GoodNum} ->
            case data_gift:get_gift_reward(101015, Lv, Sex, Career, Turn) of
                #ets_gift_reward{fixed_gifts = [{_, _, HonourNum}]} -> skip;
                _ -> HonourNum = 0
            end,
            TodayNum = lib_daily:get_count(Ps#player_status.id, ?MOD_GOODS, 2),
            LimitNum = data_key_value:get(1500001),
            AllLimitNum = DailyAdd + LimitNum,
            %% 剩余可以开启的礼包数
            case HonourNum =< 0 of
                true -> {false, ?ERRCODE(err150_gift_reward_miss)};
                _ ->
                    LeftNum  = max((AllLimitNum - TodayNum) div HonourNum, 0),
                    case TodayNum + (GoodNum*HonourNum) > AllLimitNum of
                        true when TodayNum >= AllLimitNum -> {false, ?ERRCODE(err150_honour_max)};
                        true -> {true, LeftNum};
                        _    -> {true, GoodNum}
                    end
            end;
        _ ->
            {true, CostNum}
    end.

%% 格式化礼包扣除物品
format_cost_goods([], Objects) -> Objects;
format_cost_goods([{?TYPE_GOODS, GId, Num}|T], Objects) ->
    format_cost_goods(T, [{?TYPE_GOODS, GId, Num}|Objects]);
format_cost_goods([{?TYPE_GOLD, _OGold, NGold}|T], Objects) ->
    format_cost_goods(T, [{?TYPE_GOLD, 0, NGold}|Objects]);
format_cost_goods([{?TYPE_BGOLD, _OGold, NGold}|T], Objects) ->
    format_cost_goods(T, [{?TYPE_BGOLD, 0, NGold}|Objects]);
format_cost_goods([{?TYPE_FGOLD, _OGold, NGold}|T], Objects) ->
    format_cost_goods(T, [{?TYPE_FGOLD, 0, NGold}|Objects]);
format_cost_goods([{?TYPE_COIN, _OCoin, NCoin}|T], Objects) ->
    format_cost_goods(T, [{?TYPE_COIN, 0, NCoin}|Objects]);
format_cost_goods([_H|T], Objects) ->
    format_cost_goods(T, Objects).

%%--------------------------------------------------
%% 检查是否有足够空格子开启礼包
%% 注意：需要在玩家进程调用！！！
%% GiftReward   ::      #ets_gift_reward{}  礼包记录
%% GiftNum      ::      integer()           礼包数量
%% @return      ::      true|false
%%--------------------------------------------------
check_null_cell_num(GoodsStatus, GiftReward, GiftNum) ->
    NumMap = lib_gift_util:get_gift_cell(GiftReward, GiftNum),
    do_check_null_cell_num(maps:to_list(NumMap), GoodsStatus).

do_check_null_cell_num([], _) -> true;
do_check_null_cell_num([{Location, NeedCell}|L], GoodsStatus) ->
    HaveCell = lib_goods_util:get_null_cell_num(GoodsStatus, Location),
    case HaveCell >= NeedCell of
        true -> do_check_null_cell_num(L, GoodsStatus);
        _ -> {false, data_goods:get_no_cell_errcode(Location)}
    end.

%% ================================= 自选宝箱使用检查 =================================
check_use_optional_gift(PS, GS, Uid, GTypeID, Num, SeqList) ->
    Career = PS#player_status.figure#figure.career,
    case do_check_use_optional_gift(PS, Uid, GTypeID, Num, Career, GS) of
        {fail, Errno} -> {fail, Errno};
        {ok, GoodsInfo, OptionalGift} ->
            #optional_gift{optional_num = OpNum, list = List} = OptionalGift,
            SelectLen = lists:foldl(fun({_,SNum},InitA)->SNum+InitA end,0,SeqList),
            TotolOpNum = Num*OpNum,
            Len = length(List),
            if
                TotolOpNum =/= SelectLen  orelse OpNum == 0 orelse Len == 0-> {fail, ?ERRCODE(err150_num_notmatch)};
                true ->
                    case get_seq_goods_list(SeqList, List, []) of
                        {true, GoodsList} ->
                            NeedCellMaps = lib_gift_util:get_gifts_fixlist_cell(GoodsList, Num,#{}),
                            case do_check_null_cell_num(maps:to_list(NeedCellMaps), GS) of
                                true ->
                                    {ok, GoodsInfo, OptionalGift, GoodsList};
                                {false, Errcode} ->
                                    {fail, Errcode}
                            end;
                        Res ->
                            Res
                    end
            end
    end.

do_check_use_optional_gift(PS, Uid, GTypeID, Num, Career, GS) ->
    case lib_goods_check:check_use_goods(PS, Uid, GTypeID, Num, GS) of
        {fail, Errno} -> {fail, Errno};
        {ok, #goods{type=?GOODS_TYPE_GIFT,subtype = 2} = GoodsInfo}->
            case data_optional_gift:get_by_id(GoodsInfo#goods.goods_id, Career) of
                [] ->
                    case data_optional_gift:get_by_id(GoodsInfo#goods.goods_id, 0) of
                        []->
                            {fail, ?ERRCODE(err150_no_gift_type)};
                        OptionalGift->
                            {ok, GoodsInfo, OptionalGift}
                    end;
                OptionalGift ->
                    {ok, GoodsInfo, OptionalGift}
            end;
        _ -> {fail, ?ERRCODE(err150_no_gift_type)}
    end.

%% 获取列表内容
get_seq_goods_list([], _List, Goods)->
    if Goods == [] -> {fail, 0}; true -> {true, Goods} end;
get_seq_goods_list([{No,NoNum}|SeqList], List, Goods)->
    case lists:keyfind(No, 1, List) of
        false -> {fail, ?ERRCODE(err150_seqlist_notmatch)};
        {_, {K,T,V}} ->
            get_seq_goods_list(SeqList, List, [{K,T,V*NoNum}|Goods])
    end.

