%% ---------------------------------------------------------
%% Author:  xyj
%% Email:   156702030@qq.com
%% Created: 2011-12-23
%% Description: 装备检查
%% --------------------------------------------------------
-module(lib_goods_check).
-compile(export_all).
-include("def_goods.hrl").
-include("goods.hrl").
-include("server.hrl").
-include("common.hrl").
-include("shop.hrl").
-include("task.hrl").
-include("drop.hrl").
-include("predefine.hrl").
-include("sell.hrl").
-include("attr.hrl").
-include("vip.hrl").
-include("figure.hrl").
-include("dungeon.hrl").
-include("errcode.hrl").
-include("def_fun.hrl").
-include("team.hrl").
-include("scene.hrl").
-include("child.hrl").

%%-------------------------------------------------------
%% @doc 检查根据物品Id删除单个物品
%% -spec check_delete(GoodsStatus, GoodsId, GoodsNum) -> {ok, GoodsInfo} | {fail, Err}
%% when
%%      GoodsStatus :: #goods_statuws{} 物品进程状态
%%      GoodsId     :: integer()        物品Id
%%      GoodsNum    :: integer()        要删除的物品数量
%%      GoodsInfo   :: #goods{}         物品信息
%%      Err         :: integer()        错误码
%% @end
%%-----------------------------------------------------------
check_delete(GoodsStatus, GoodsId, GoodsTypeId, GoodsNum) ->
    case check_goods_normal(GoodsStatus, GoodsId, GoodsTypeId) of
        {ok, GoodsInfo} ->
            if
                GoodsNum < 1 orelse GoodsInfo#goods.num < GoodsNum ->
                    %% 物品数量不正确
                    {fail, ?ERRCODE(err150_num_err)};
                true ->
                    {ok, GoodsInfo}
            end;
        ErrorRes ->
            ErrorRes
    end.
%%-------------------------------------------------------
%% @doc 指定背包中物品Id删除单个物品
%% -spec check_delete(GoodsStatus, GoodsId, GoodsNum) -> {ok, GoodsInfo} | {fail, Err}
%% when
%%      GoodsStatus :: #goods_statuws{} 物品进程状态
%%      GoodsId     :: integer()        物品Id
%%      GoodsNum    :: integer()        要删除的物品数量
%%      GoodsInfo   :: #goods{}         物品信息
%%      Err         :: integer()        错误码
%% @end
%%-----------------------------------------------------------
check_delete_id_in_location(GoodsStatus, GoodsId, GoodsNum, Location) ->
    case check_location_goods_normal(GoodsStatus, GoodsId, Location) of
        {ok, GoodsInfo} ->
            if
                GoodsNum < 1 orelse GoodsInfo#goods.num < GoodsNum ->
                    %% 物品数量不正确
                    {fail, ?ERRCODE(err150_num_err)};
                true ->
                    {ok, GoodsInfo}
            end;
        ErrorRes ->
            ErrorRes
    end.

%%------------------------------------------------------------
%% @doc 检查根据物品Id删除多个物品
%% -spec check_delete_list(GoodsStatus, GoodsList) -> {ok, List} | {fail, Err}
%% when
%%      GoodsStatus :: #goods_statuws{} 物品进程状态
%%      GoodsList   :: list() 要删除的物品列表[{物品Id, 删除数量}]
%%      List        :: list() 要删除的物品列表[[{物品信息#goods{}], 删除数量}]
%%      Err         :: integer() 错误码
%% @end
%%----------------------------------------------------------------
check_delete_list(GoodsStatus, GoodsList) ->
    F = fun({GoodsId, GoodsTypeId, GoodsNum}, List) ->
        case check_delete(GoodsStatus, GoodsId, GoodsTypeId, GoodsNum) of
            {ok, GoodsInfo} -> {ok, [{GoodsInfo, GoodsNum} | List]};
            {fail, Res} -> {fail, Res}
        end
    end,
    list_handle(F, [], GoodsList).

%% ---------------------------------------------------------------------------
%% @doc 检查根据物品类型Id列表删除物品
-spec check_delete_type_list(GoodsStatus, GoodsTypeList) -> {ok} | {fail} when
    GoodsStatus :: #goods_status{},
    GoodsTypeList:: [{GoodsTypeId :: integer(), DeleteNum :: integer()}].
%% ---------------------------------------------------------------------------
check_delete_type_list(GoodsStatus, GoodsTypeList) ->
    #goods_status{player_id = PlayerId, dict = Dict} = GoodsStatus,
    Fun = fun({GoodsTypeId, DeleteNum}) ->
        case data_goods_type:get(GoodsTypeId) of
            #ets_goods_type{bag_location = BagLocation} ->
                GoodsList = lib_goods_util:get_type_goods_list(
                    PlayerId, GoodsTypeId, BagLocation, Dict, GoodsStatus#goods_status.player_lv
                ),
                TotalNum = lib_goods_util:get_goods_total_num(GoodsList),
                TotalNum >= DeleteNum;
            _ -> false
        end
    end,
    case lists:all(Fun, GoodsTypeList) of
        false -> {fail};
        true -> {ok}
    end.

%%-------------------------------------------------------------------------------------------------------------------
%% @doc 检查使用物品
%% @spec check_use_goods(PlayerStatus, GoodsId, GoodsNum, GoodsStatus) -> {ok, GoodsInfo, GiftInfo} | {fail, ?ERRCODE} when
%% PlayerStatus :: #player_status{}     玩家记录
%% GoodsId      :: integer()            物品Id
%% GoodsStatus  :: #goods_status{}      玩家物品进程状态
%% GoodsInfo    :: #goods{}             物品记录
%% GiftInfo     :: #ets_gift{}          礼包记录,礼包有返回，否则为{}
%% ?ERRCODE     :: integer()            错误码
%% @end
%%-------------------------------------------------------------------------------------------------------------------
check_use_goods(PlayerStatus, GoodsId, GoodsTypeId, GoodsNum, GoodsStatus) ->
    NowTime = utime:unixtime(),
    PlayerLv = PlayerStatus#player_status.figure#figure.lv,
    case check_goods_normal(GoodsStatus, GoodsId, GoodsTypeId) of
        {ok, GoodsInfo} ->
            GoodsTypeInfo = data_goods_type:get(GoodsInfo#goods.goods_id),
            if
                is_record(GoodsTypeInfo, ets_goods_type) =/=true ->
                    {fail, ?ERRCODE(err150_no_goods)};
                GoodsNum < 1 orelse GoodsInfo#goods.num < GoodsNum ->
                    {fail, ?ERRCODE(err150_num_err)};
                PlayerLv < GoodsTypeInfo#ets_goods_type.level ->
                    {fail, ?ERRCODE(err150_lv_err)};
                GoodsTypeInfo#ets_goods_type.use =:= 0 ->
                    {fail, ?ERRCODE(err150_no_use)};
                GoodsInfo#goods.expire_time > 0 andalso GoodsInfo#goods.expire_time =< NowTime ->
                    {fail, ?ERRCODE(err150_goods_expired)};
                true ->
                    if
                        GoodsInfo#goods.type =:= ?GOODS_TYPE_GIFT andalso GoodsInfo#goods.subtype =:= 2 ->
                            {ok,GoodsInfo};
                        GoodsInfo#goods.type =:= ?GOODS_TYPE_GIFT ->
                            lib_gift_check:ckeck_use_gift(PlayerStatus, GoodsStatus, GoodsInfo, GoodsNum);
                        true ->
                            {ok, GoodsInfo}
                    end
            end;
        ErrorRes ->
            ErrorRes
    end.

%%--------------------------------------------
%% 销毁物品
%%--------------------------------------------
check_throw(GoodsStatus, ThrowType, GoodsId, GoodsTypeId, GoodsNum, NowTime) ->
    case check_goods_normal(GoodsStatus, GoodsId, GoodsTypeId) of
        {ok, GoodsInfo} ->
            if
            %% 物品不在背包
                GoodsInfo#goods.location =/= ?GOODS_LOC_BAG ->
                    {fail, ?ERRCODE(err150_location_err)};
            %% 物品数量不正确
                GoodsNum < 1 orelse GoodsInfo#goods.num < GoodsNum ->
                    {fail, ?ERRCODE(err150_num_err)};
                true ->
                    IsTimeOut = is_goods_timeout(GoodsInfo, NowTime),
                    if
                        ThrowType == ?THROW_TYPE_TIMEOUT andalso IsTimeOut=/=true ->
                            {fail, ?ERRCODE(err150_goods_not_timeout)};
                        true -> {ok, GoodsInfo}
                    end
            end;
        ErrorRes ->
            ErrorRes
    end.

check_throw_list(GoodsStatus, ThrowType, GoodsList) ->
    NowTime = utime:unixtime(),
    F = fun({GoodsId, GoodsTypeId, GoodsNum}, List) ->
        case check_throw(GoodsStatus, ThrowType, GoodsId, GoodsTypeId, GoodsNum, NowTime) of
            {ok, GoodsInfo} -> {ok, [{GoodsInfo, GoodsNum} | List]};
            {fail, Res} -> {fail, Res}
        end
    end,
    list_handle(F, [], GoodsList).

%% 物品是否过期
is_goods_timeout(GoodsInfo, NowTime) ->
    #goods{type = Type, subtype = SubType, expire_time = ExpireTime} = GoodsInfo,
    if
        Type == ?GOODS_TYPE_EQUIP andalso SubType == ?EQUIP_ANGLE_DEVIL -> false; %% 过滤掉天使和恶魔
        ExpireTime>0 andalso ExpireTime=<NowTime -> true;
        true -> false
    end.
%%-----------------------------------------------------
%% 检查拆分物品
%% @param GoodsNum ::integer() 要拆分的数量
%%-----------------------------------------------------
check_split(GoodsStatus, GoodsId, GoodsTypeId, GoodsNum) ->
    case check_goods_normal(GoodsStatus, GoodsId, GoodsTypeId) of
        {ok, GoodsInfo} ->
            if
                %% 物品数量不正确
                GoodsNum < 1 ->
                    {fail, ?ERRCODE(err150_num_err)};
                GoodsInfo#goods.num =< GoodsNum ->
                    {fail, ?ERRCODE(err150_num_err)};
                true ->
                    NullCellNum = lib_goods_util:get_null_cell_num(GoodsStatus, GoodsInfo#goods.location),
                    if
                        %% 背包格子不足
                        NullCellNum =:= 0 ->
                            {fail, ?ERRCODE(err150_no_cell)};
                        true ->
                            {ok, GoodsInfo}
                    end
            end;
        ErrorRes ->
            ErrorRes
    end.

list_handle(F, Data, List) ->
    case List of
        [H|T] ->
            case F(H, Data) of
                {ok, Data2} ->
                    list_handle(F, Data2, T);
                Error ->
                    Error
            end;
        [] ->
            {ok, Data}
    end.

%% 出售物品
check_sell(PlayerStatus, _NpcId, GoodsList, GoodsStatus) ->
    %% 物品列表一个个检查
    case list_handle(fun check_sells/2, [PlayerStatus#player_status.id, [], [], GoodsStatus], GoodsList) of
        {fail, Res} ->
            {fail, Res};
        {ok, [_, MoneyList, NewGoodsList, _]} ->
            {ok, MoneyList, NewGoodsList}
    end.

check_sells({GoodsId, GoodsTypeId, GoodsNum}, [PlayerId, MoneyList, GoodsList, GoodsStatus]) ->
    NowTime   = utime:unixtime(),
    GoodsCfg = data_goods_type:get(GoodsTypeId),
    CanSell = ?IF(is_record(GoodsCfg, ets_goods_type), GoodsCfg#ets_goods_type.sell, 0),
    case check_goods_normal(GoodsStatus, GoodsId, GoodsTypeId) of
        {ok, GoodsInfo} ->
            IsSellForce = check_sell_force(GoodsInfo),
            IsTimeOutIgnore =check_timeout_ignore(GoodsInfo),
            CheckRes = if
                %% 物品不可出售
                CanSell =:= 0 andalso IsSellForce == false ->
                    {fail, ?ERRCODE(err150_not_sell)};
                %% 物品不在对应的背包 出售限制物品背包
                GoodsInfo#goods.location =/= ?GOODS_LOC_BAG ->
                    {fail, ?ERRCODE(err150_location_err)};
                %% 物品数量不足
                GoodsNum < 1 orelse GoodsInfo#goods.num < GoodsNum ->
                    {fail, ?ERRCODE(err150_num_err)};

                %% 注： 以下为有效期检查，非有效期逻辑请在之上编码
                %% 物品已过有效期
                IsTimeOutIgnore == true -> true;
                GoodsInfo#goods.expire_time > 0 andalso GoodsInfo#goods.expire_time =< NowTime ->
                    {fail, ?ERRCODE(err150_goods_expired)};
                true -> true
            end,
            case CheckRes of
                true ->
                    {PriceType, SellPrice} = data_goods:get_goods_sell_price(GoodsInfo#goods.goods_id),
                    NewMoneyList = calc_sell_money(PriceType, SellPrice, GoodsNum, MoneyList),
                    {ok, [PlayerId, NewMoneyList, [{GoodsInfo,GoodsNum}|GoodsList], GoodsStatus]};
                _ -> CheckRes
            end;
        ErrorRes ->
            ErrorRes
    end;
check_sells(_, _) ->
    {fail, ?ERRCODE(err150_fail)}.

check_sell_force(GoodsInfo) ->
    case GoodsInfo of
        #goods{type = _Type, subtype = _SubType} ->
            true;
            %% lists:member(Type, ?GOODS_TYPE_SELL_FORCE)
            %%     orelse
            %% ( Type == ?GOODS_TYPE_PROPS andalso lists:member(SubType, ?GOODS_SUBTYPE_SELL_FORCE_PROPS) );
        _ -> false
    end.

check_timeout_ignore(GoodsInfo) ->
    case GoodsInfo of
        %% 排除有效期检查：天使与恶魔
        #goods{type = ?GOODS_TYPE_EQUIP, subtype = ?EQUIP_ANGLE_DEVIL} -> true;
        _ -> false
    end.

calc_sell_money(PriceType, Price, GoodsNum, List) ->
    MomeyType = case PriceType of
                    ?TYPE_COIN  -> ?TYPE_COIN;
                    ?TYPE_BGOLD -> ?TYPE_BGOLD;
                    ?TYPE_FGOLD -> ?TYPE_FGOLD;
                    ?TYPE_GOLD -> ?TYPE_GOLD;
                    _ -> none
                end,
    SellMoney = round(Price*GoodsNum),
    NewNum = case lists:keyfind(MomeyType, 1, List) of
                 {MomeyType, _GoodsId, Num} -> SellMoney+Num;
                 _ -> SellMoney
             end,
    case MomeyType =/=none of
        true -> lists:keystore(MomeyType, 1, List, {MomeyType, 0, NewNum});
        _ -> List
    end.

%%-------------------------------------------------
%% @doc 扩展背包
%% @end
%%----------------------------------------------------
check_expand_bag(PlayerStatus, Pos, CellNum) ->
    #player_status{cell_num = BagCell, storage_num = StoCell} = PlayerStatus,
    if
        CellNum =< 0 orelse (Pos =/= ?GOODS_LOC_BAG andalso Pos =/= ?GOODS_LOC_STORAGE) ->
            {fail, ?ERRCODE(data_error)};
        true ->
            CellMax = ?IF(Pos =:= ?GOODS_LOC_BAG, data_goods:get_location_max_size(?GOODS_LOC_BAG), data_goods:get_location_max_size(?GOODS_LOC_STORAGE)),
            DefCell = ?IF(Pos =:= ?GOODS_LOC_BAG, data_goods:get_location_size(?GOODS_LOC_BAG), data_goods:get_location_size(?GOODS_LOC_STORAGE)),
            CurrentCell = ?IF(Pos =:= ?GOODS_LOC_BAG, BagCell, StoCell),
            ExpandCosts = data_bag:get_expand_costs(Pos, (CurrentCell - DefCell) + 1),
            NewCellNum = CurrentCell + CellNum,
            if
                CurrentCell + CellNum > CellMax ->
                    {fail, ?ERRCODE(cell_beyond)};
                ExpandCosts == [] ->
                    {fail, ?ERRCODE(missing_config)};
                true ->
                    %% 背包扩容钥匙
                    case calc_expand_cost(CurrentCell, NewCellNum, DefCell, Pos, []) of
                        false -> {fail, ?ERRCODE(missing_config)};
                        {true, Cost} ->
                            {ok, Cost}
                    end
            end
    end.
calc_expand_cost(NowCellNum, AfExpandCellNum, _DefCellNum, _BagType, ToCost)
    when NowCellNum >= AfExpandCellNum ->
    {true, ToCost};
calc_expand_cost(NowCellNum, AfExpandCellNum, DefCellNum, BagType, ToCost) ->
    OpenCellNum = (NowCellNum - DefCellNum) + 1,
    case data_bag:get_expand_costs(BagType, OpenCellNum) of
        [_|_] = Cost ->
            NewCost = lib_goods_util:merge_same_goods(Cost ++ ToCost),
            calc_expand_cost(NowCellNum + 1, AfExpandCellNum, DefCellNum, BagType, NewCost);
        _ ->
            false
    end.
%% 暂时只允许背包仓库互移
check_good_change_pos(PlayerStatus, GoodsStatus, GoodsId, FromPos, ToPos)->
    GoodsInfo = lib_goods_api:get_goods_info(GoodsStatus, GoodsId, FromPos),
    if  %% 物品不存在
        is_record(GoodsInfo, goods) =:= false ->
            {fail, ?ERRCODE(err150_no_goods)};
        %% 物品不属于你所有
        GoodsInfo#goods.player_id =/= GoodsStatus#goods_status.player_id ->
            {fail, ?ERRCODE(err150_palyer_err)};
        %% 不允许渔具道具存入仓库
        GoodsInfo#goods.type == ?GOODS_TYPE_FISHING andalso GoodsInfo#goods.subtype == ?GOODS_SUBTYPE_FISHING_GEAR andalso
        FromPos =:= ?GOODS_LOC_BAG andalso ToPos =:= ?GOODS_LOC_STORAGE ->
            {fail, ?ERRCODE(err177_fishing_gear_can_not_storage)};
        true ->
            lib_storage_util:check_movein_pos(PlayerStatus, GoodsStatus, GoodsInfo, ToPos)
    end.

%% ---------------------------------------------------------------------------
%% @doc 检查增加的物品列表中 GoodTypeId 是否有重复的
-spec check_give_list(GoodsList) -> {ok} | {false, duplicate} when
    GoodsList   :: [{GoodTypeId, GoodsNum}] | [{goods, GoodTypeId, GoodsNum}]
                   | [{goods, GoodTypeId, GoodsNum, Bind}]
                   | [{equip, GoodsTypeId, Prefix, Stren}]
                   | [{info, GoodsInfo}]
                   | [{goods, GoodsTypeId, GoodsNum, Prefix, Stren, Bind}]
                   | [{?TYPE_ATTR_GOODS, GoodsTypeId, GoodsNum, AttrList}]
                   | [{?TYPE_BIND_GOODS, GoodsTypeId, GoodsNum}]
                   | [{?TYPE_GOODS, GoodsTypeId, GoodsNum}]
                   | [{goods_attr, GoodsTypeId, GoodsNum, AttrList}],
    GoodTypeId  :: integer(),
    GoodsNum    :: integer(),
    Bind        :: integer(),
    Prefix      :: integer(),
    Stren       :: integer(),
    GoodsInfo   :: #goods{},
    AttrList    :: list().
%% ---------------------------------------------------------------------------
check_give_list(GoodsList) ->
    check_give_list(GoodsList, []).

check_give_list([], _GoodTypeIdL) -> {ok};
check_give_list([OneGoods | T], GoodsTypeIdL) ->
    GoodsTypeId = case OneGoods of
        {goods, GTypeId, _} -> GTypeId;
        {goods_attr, GTypeId, _, _} -> GTypeId;
        {goods, GTypeId, _GoodsNum, _Bind} -> GTypeId;
        {equip, GTypeId, _Prefix, _Stren} -> GTypeId;
        {info, GoodsInfo} -> GoodsInfo#goods.goods_id;
        {goods, GTypeId, _GoodsNum, _Prefix, _Stren, _Bind} -> GTypeId;
        {?TYPE_ATTR_GOODS, GTypeId, _, _} -> GTypeId;
        {?TYPE_BIND_GOODS, GTypeId, _} -> GTypeId;
        {?TYPE_GOODS, GTypeId, _} -> GTypeId;
        {GTypeId, _GoodsNum} when is_integer(GTypeId) -> GTypeId;
        _ -> 0
    end,
    case GoodsTypeId of
        0 ->
            {false, duplicate};
        _ ->
            case lists:member(GoodsTypeId, GoodsTypeIdL) of
                true ->
                    {false, duplicate};
                false ->
                    NewGoodTypeIdL = [GoodsTypeId | GoodsTypeIdL],
                    check_give_list(T, NewGoodTypeIdL)
            end
    end.

%% ---------------------------------------------------------------------------
%% @doc 合并物品列表(Key相同的项 GoodsNum值相加)
%% ---------------------------------------------------------------------------
combine_goods_num_list(GoodsList) ->
    F = fun
            ({Key, Value}, Result) ->
                case lists:keyfind(Key, 1, Result) of
                    false -> [{Key, Value} | Result];
                    {_, Value1} ->
                        lists:keystore(Key, 1, Result, {Key, Value + Value1})
                end;
            ({Key, Id, Value}, Result) ->
                case lists:keyfind(Key, 1, Result) of
                    false -> [{Key, Id, Value} | Result];
                    {_, Id, Value1} ->
                        lists:keystore(Key, 1, Result, {Key, Id, Value + Value1})
                end
    end,
    lists:foldl(F, [], GoodsList).

%%--------------------------------------------------
%% 检测物品分解
%% @param  GoodsList    [{GoodsId, typeId, Num}]
%% @return              {ok, GoodsInfo}|{fail, ErrorCode}
%%--------------------------------------------------
check_goods_decompose(GoodsStatus, GoodsList) ->
    case do_check_goods_decompose(GoodsStatus, GoodsList, []) of
        {ok, GoodsInfoNumList} ->
            % CombineList = combine_goods_num_list(GTypeNumList),
            case count_decompose_reward(GoodsInfoNumList, []) of
                {ok, DecomposeRewardList} ->
                %    CombineRewarList = combine_goods_num_list_ex(DecomposeRewardList),
                    case lib_goods_api:can_give_goods(GoodsStatus, DecomposeRewardList) of
                        true -> {ok, DecomposeRewardList};
                        false -> {fail, ?ERRCODE(err150_no_null_cell_decompose_fail)}
                    end;
                {fail, ErrorCode} -> {fail, ErrorCode}
            end;
        {fail, ErrorCode} -> {fail, ErrorCode}
    end.

do_check_goods_decompose(_GoodsStatus, [], Acc) -> {ok, Acc};
do_check_goods_decompose(GoodsStatus, [{GoodsId, GoodsTypeId, GoodsNum}|L], Acc) ->
    case check_same_decompose_goods(GoodsTypeId) of
        true ->
            case check_goods_normal(GoodsStatus, GoodsId, GoodsTypeId) of
                {ok, GoodsInfo} ->
                    #goods{num = OwnNum} = GoodsInfo,
                    case OwnNum >= GoodsNum of
                        true ->
                            case do_check_goods_decompose_other(GoodsInfo) of
                                true ->
                                    do_check_goods_decompose(GoodsStatus, L, [{GoodsInfo, GoodsNum}|Acc]);
                                {false, ErrorCode} -> {fail, ErrorCode}
                            end;
                        false ->
                            {fail, ?ERRCODE(goods_not_enough)}
                    end;
                {fail, ErrorCode} -> {fail, ErrorCode}
            end;
        {fail, Err} -> {fail, Err}
    end.

check_same_decompose_goods(GoodsTypeId) ->
    %% 原物品与分解得到的物品不能是同类型物品，避免死循环
    %% (检测分解得到的不能与分解前的所有物品类型Id相同)
    case data_goods_decompose:get(GoodsTypeId) of
        #goods_decompose_cfg{irregular_mat = IrrMat, regular_mat = RMat} ->
            GiveGoods = IrrMat ++ RMat,
            AllGoodsId = data_goods_decompose:get_all_decompose_goods(),
            F = fun({_, TGoodTypeId, _}) ->
                    case lists:member(TGoodTypeId, AllGoodsId) of
                        true -> false;
                        _ -> true
                    end;
                (_) -> false
            end,
            case GiveGoods =/= [] of
                true ->
                    case lists:all(F, GiveGoods) of
                        true -> true;
                        _ -> {fail, ?ERRCODE(config_err)}
                    end;
                _ -> {fail, ?ERRCODE(config_err)}
            end;
        _ ->
            {fail, ?ERRCODE(config_err)}
    end.

do_check_goods_decompose_other(#goods{type = ?GOODS_TYPE_FASHION} = GoodsInfo) ->
    lib_fashion:check_fashion_goods(GoodsInfo);
do_check_goods_decompose_other(_GoodsInfo) ->
    true.

count_decompose_reward([], AccList) -> {ok, AccList};
count_decompose_reward([{GoodsInfo, GoodsNum}|L], AccList) ->
    #goods{goods_id = GTypeId} = GoodsInfo,
    case data_goods_decompose:get(GTypeId) of
        #goods_decompose_cfg{
            irregular_num = IrregularNum,
            irregular_mat = IrregularMat,
            regular_mat = RegularMat
        } ->
            F = fun(_, Acc) ->
                TmpShuffleList = urand:list_shuffle(IrregularMat),
                TmpSubList = lists:sublist(TmpShuffleList, IrregularNum),
                TmpSubList ++ Acc
            end,
            GiveIrregularMat = lists:foldl(F, [], lists:seq(1, GoodsNum)),
            GiveRegularMat = [{ObjectType, RGTypeId, RNum * GoodsNum} || {ObjectType, RGTypeId, RNum} <- RegularMat],
            TmpGiveList = GiveRegularMat ++ GiveIrregularMat,
            %%% 如果分解后的物品需要特殊处理属性的写在这个接口里面 不能改变分解物品的id！！！！！
            %%% 叠加的物品只能改绑定属性 设置其他属性不会发物品
            GiveList = count_goods_decompose_attr(GoodsInfo, TmpGiveList),
            count_decompose_reward(L, lib_goods_util:merge_same_goods(GiveList) ++ AccList);
        _ -> {fail, ?ERRCODE(err_config)}
    end.

%%--------------------------------------------------
%% 如果分解后的物品需要特殊处理属性的写在这个接口里面 不能改变分解物品的id！！！！！
%% 不要在这里面做发奖励的逻辑！！！！！
%% @param  GoodsInfo            #goods{}
%% @param  RewardList           [{GoodsType, GoodsId, GoodsNum}]
%% @return
%%--------------------------------------------------
count_goods_decompose_attr(GoodsInfo, RewardList) ->
    warsoul_logic:decompose_return_stuff(GoodsInfo, RewardList).

check_goods_normal(GoodsStatus, GoodsId, GoodsTypeId) ->
    case data_goods_type:get(GoodsTypeId) of
        #ets_goods_type{bag_location = Location} ->
            check_location_goods_normal(GoodsStatus, GoodsId, Location);
        _ ->
            {fail, ?ERRCODE(missing_config)}
    end.
check_location_goods_normal(GoodsStatus, GoodsId, Location) ->
    GoodsInfo = lib_goods_api:get_goods_info(GoodsStatus, GoodsId, Location),
    if
        is_record(GoodsInfo, goods) =:= false ->
            {fail, ?ERRCODE(err150_no_goods)};
        GoodsInfo#goods.player_id =/= GoodsStatus#goods_status.player_id ->
            {fail, ?ERRCODE(err150_palyer_err)};
        true ->
            {ok, GoodsInfo}
    end.
check(PlayerStatus, {lv, NeedLv}) ->
    Lv = PlayerStatus#player_status.figure#figure.lv,
    if
        Lv >= NeedLv -> true;
        true -> {false, ?ERRCODE(err150_not_satisfy_compose_lv)}
    end;
check(PlayerStatus, {vip_lv, NeedVipLv}) ->
    VipLv = PlayerStatus#player_status.figure#figure.vip,
    if
        VipLv >= NeedVipLv -> true;
        true -> {false, ?ERRCODE(err150_not_satisfy_compose_vip_lv)}
    end;
check(PlayerStatus, {career, NeedCareer}) ->
    Career = PlayerStatus#player_status.figure#figure.career,
    if
        Career == NeedCareer orelse NeedCareer == 0 -> true;
        true -> {false, ?ERRCODE(err150_not_satisfy_compose_career)}
    end;
check(_PlayerStatus, _T) ->
    {false, ?FAIL}.

check_list(_PlayerStatus, []) -> true;
check_list(PlayerStatus, [H|T]) ->
    case check(PlayerStatus, H) of
        true -> check_list(PlayerStatus, T);
        {false, Res} -> ?PRINT("Condition~p~n", [H]), {false, Res}
    end.

%% 检查boss之间的等级差，太高就不给拾取
check_boss_lv(_Scene, MonId, BossLv, Lv) ->
    case data_mon:get(MonId) of
        #mon{boss = ?SCENE_TYPE_HOME_BOSS} ->
            home_boss_mgr:is_can_drop(MonId, BossLv, Lv);
        _ ->
            false
    end.


%% 检测发物品到指定背包
check_give_to_specify_loc(Location, GoodsList) ->
    case lists:member(Location, ?GOODS_LOC_BAG_TYPES) of
        true ->
            do_check_give_to_specify_loc(GoodsList, []);
        false ->
            {false, ?ERRCODE(err150_bag_location_fail)}
    end.

do_check_give_to_specify_loc([], _GoodTypeIdL) -> ok;
do_check_give_to_specify_loc([OneGoods|L], GoodsTypeIdL) ->
    GoodsTypeId = case OneGoods of
                      {location, _Loc, GTypeId, _} -> GTypeId;
                      _ -> 0
                  end,
    case GoodsTypeId of
        0 ->
            {false, duplicate};
        _ ->
            case lists:member(GoodsTypeId, GoodsTypeIdL) of
                true ->
                    {false, duplicate};
                false ->
                    do_check_give_to_specify_loc(L, [GoodsTypeId|GoodsTypeIdL])
            end
    end.

%% 检测将物品从A背包转移到B背包
check_move_a2b(GoodsStatus, GoodsId, FromLoc) ->
    case lib_goods_util:get_goods(GoodsId, GoodsStatus#goods_status.dict) of
        #goods{goods_id = GoodsTypeId} ->
            case data_goods_type:get(GoodsTypeId) of
                #ets_goods_type{bag_location = ToLoc} when FromLoc =/= ToLoc ->
                    check_move_a2b(GoodsId, GoodsStatus, FromLoc, ToLoc);
                _ ->
                    {fail, ?FAIL}
            end;
        _ ->
            {fail, ?ERRCODE(err155_goods_not_exist)}
    end.

check_move_a2b(GoodsStatus, GoodsId, FromLoc, ToLoc)->
    IsAble = check_move_a2b_type(FromLoc, ToLoc),
    NullCellNum = lib_goods_util:get_null_cell_num(GoodsStatus, ToLoc),
    if  %% 位置错误
        IsAble =:= false ->
            {fail, ?ERRCODE(err150_location_err)};
        NullCellNum =< 0 ->
            {fail, ?ERRCODE(err151_no_null_cells)};
        true ->
            do_check_move_a2b(GoodsId, GoodsStatus, FromLoc)
    end.

do_check_move_a2b(GoodsId, GoodsStatus, FromLoc) ->
    GoodsInfo = lib_goods_util:get_goods(GoodsId, GoodsStatus#goods_status.dict, FromLoc),
    if  %% 物品不存在
        is_record(GoodsInfo, goods) =:= false ->
            {fail, ?ERRCODE(err155_goods_not_exist)};
        %% 物品不属于你所有
        GoodsInfo#goods.player_id =/= GoodsStatus#goods_status.player_id ->
            {fail, ?ERRCODE(err150_palyer_err)};
        GoodsInfo#goods.location =/= FromLoc ->
            {fail, ?ERRCODE(err150_location_err)};
        true ->
            {ok, GoodsInfo}
    end.

check_move_a2b_type(FromLoc, ToLoc) ->
    %% 允许移动的类型列表
    AbleMoveTypes = [
        {?GOODS_LOC_CAPSULE_EGG_BAG, ?GOODS_LOC_BAG}
    ],
    lists:member({FromLoc, ToLoc}, AbleMoveTypes).