%% ---------------------------------------------------------
%% Author:  xyj
%% Email:   156702030@qq.com
%% Created: 2011-12-13
%% Description: 物品操作
%% --------------------------------------------------------
-module(pp_goods).
-export([handle/3]).
-export([
          send_equip_list_local/3
        , send_equip_list_kf/3
        , send_goods_info_local/4
        , send_goods_info_kf/4
    ]).

-include("common.hrl").
-include("server.hrl").
-include("def_goods.hrl").
-include("sql_goods.hrl").
-include("goods.hrl").
-include("shop.hrl").
-include("attr.hrl").
-include("vip.hrl").
-include("predefine.hrl").
-include("figure.hrl").
-include("errcode.hrl").
-include("def_module.hrl").
-include("gift.hrl").
-include("chat.hrl").
-include("rec_offline.hrl").
-include("def_fun.hrl").
-include("scene.hrl").

%% 查询他人物品详细信息
handle(15000, PlayerStatus, [RoleId, GoodsId, GoodsTypeId]) ->
    #player_status{sid = Sid, server_id = MyServerId} = PlayerStatus,
    ServerId = mod_player_create:get_real_serid_by_id(RoleId),
    case MyServerId =:= ServerId of
        true  ->
            lib_player:apply_cast(RoleId, ?APPLY_CAST_STATUS, ?HAND_OFFLINE, ?MODULE, send_goods_info_local, [GoodsId, GoodsTypeId, Sid]);
        false ->
            clusters_node:apply_cast(clusters_center, apply_cast,
                [ServerId, lib_player, apply_cast,
                    [RoleId, ?APPLY_CAST_STATUS, ?HAND_OFFLINE, ?MODULE, send_goods_info_kf, [GoodsId, GoodsTypeId, Sid]]]
            )
    end,
    ok;

%% 背包开启格子
handle(15002, Ps, [Pos, Num])->
    [ResCode, NewPs] = lib_goods_do:expand_bag(Ps, Pos, Num),
    AllNum = if
                 Pos == ?GOODS_LOC_STORAGE -> NewPs#player_status.storage_num;
                 true -> NewPs#player_status.cell_num
             end,
    lib_server_send:send_to_sid(Ps#player_status.sid, pt_150, 15002, [ResCode, Pos, AllNum]),
    {ok, NewPs};

%% 物品背包移动
handle(15003, Ps, [GoodId, FromPos, ToPos])->
    ResCode = lib_goods_do:change_pos(Ps, GoodId, FromPos, ToPos),
    lib_server_send:send_to_sid(Ps#player_status.sid, pt_150, 15003, [ResCode]);

%% 15004 整理背包
handle(15004, Ps, [Pos])->
    if
        Pos == ?GOODS_LOC_STORAGE orelse Pos == ?GOODS_LOC_BAG ->
            case lib_goods_do:order_bag(Ps, Pos) of
                [1] -> handle(15010, Ps, [Pos]);
                [2] ->
                    lib_server_send:send_to_sid(Ps#player_status.sid, pt_150, 15004, [1]);
                [ResCode] ->
                    lib_server_send:send_to_sid(Ps#player_status.sid, pt_150, 15004, [ResCode])
            end;
        true ->
            skip
    end;

%% 15005 拆分
handle(15005, Ps, [GoodsId, GoodsTypeId, GoodsNum]) ->
    ResCode = lib_goods_do:split(GoodsId, GoodsTypeId, GoodsNum),
    lib_server_send:send_to_sid(Ps#player_status.sid, pt_150, 15005, [ResCode]);

%% 查询单种虚拟货币
handle(15008, PS, [CurrencyId]) ->
    goods_logic:send_update_currency(PS, CurrencyId);

%% 获得虚拟货币
handle(15009, PS, []) ->
    List = maps:to_list(PS#player_status.currency_map),
    {ok, BinData} = pt_150:write(15009, [List]),
    lib_server_send:send_to_sid(PS#player_status.sid, BinData);

%% 查看物品列表
handle(15010, PlayerStatus, [Pos]) ->
    #player_status{
        sid = Sid,
        cell_num = BagCell,
        storage_num = StorageCell
    } = PlayerStatus,
    GoodsStatus = lib_goods_do:get_goods_status(),
    {NewPos, CellNum, MaxCell, DefCell} = if
        Pos =< 0 ->
            {?GOODS_LOC_EQUIP, 0, 0, 0};
        Pos =:= ?GOODS_LOC_BAG ->
            {Pos, BagCell, data_goods:get_location_max_size(Pos), data_goods:get_location_size(Pos)};
        Pos =:= ?GOODS_LOC_STORAGE ->
            {Pos, StorageCell, data_goods:get_location_max_size(Pos), data_goods:get_location_size(Pos)};
        true ->
            TmpCellNum = lib_goods_util:get_null_cell_num(GoodsStatus, Pos),
            TmpMaxCell = data_goods:get_location_max_size(Pos),
            {Pos, TmpCellNum, TmpMaxCell, 0}
    end,
    GoodsList = lib_goods_util:get_goods_list(GoodsStatus#goods_status.dict, NewPos),
    GoodsListPack = lib_goods_util:pack_goods_list(GoodsList),
    {ok, BinData} = pt_150:write(15010, [NewPos, CellNum, MaxCell, DefCell, GoodsListPack]),
    lib_server_send:send_to_sid(Sid, BinData);

%% 查询别人身上装备列表
%handle(15011, #player_status{id = RoleId}, [RoleId]) -> ok;
handle(15011, PlayerStatus, [ModId, RoleId]) ->
    #player_status{server_id = MyServerId, sid = Sid} = PlayerStatus,
    ServerId = mod_player_create:get_real_serid_by_id(RoleId),
    case MyServerId =:= ServerId of
        true  ->
            lib_player:apply_cast(RoleId, ?APPLY_CAST_STATUS, ?HAND_OFFLINE, ?MODULE, send_equip_list_local, [ModId, Sid]);
        false ->
            clusters_node:apply_cast(clusters_center, apply_cast,
                [ServerId, lib_player, apply_cast,
                    [RoleId, ?APPLY_CAST_STATUS, ?HAND_OFFLINE, ?MODULE, send_equip_list_kf, [ModId, Sid]]]
            )
    end;

%% 物品分解
handle(15019, PlayerStatus, [GoodsList]) when GoodsList =/= [] ->
    FilterGoods = lists:sublist(GoodsList, 50),
    NewGoodsList = lib_goods_util:merge_same_goods(FilterGoods),
    case lib_goods_do:goods_decompose(PlayerStatus, NewGoodsList) of
        {ok, NewPlayerStatus} ->
            {ok, BinData} = pt_150:write(15019, [1, NewGoodsList]),
            lib_server_send:send_to_sid(NewPlayerStatus#player_status.sid, BinData),
            {ok, NewPlayerStatus};
        {false, Err} ->
            {ok, BinData} = pt_150:write(15019, [Err, []]),
            lib_server_send:send_to_sid(PlayerStatus#player_status.sid, BinData),
            ok
    end;


%% 物品出售 [{GoodsId, GoodsTypeId, GoodsNum}|_]
handle(15021, PlayerStatus, [GoodsList]) ->
    FilterGoods = lists:sublist(GoodsList, 50),
    case lib_goods_do:sell_goods(PlayerStatus, 0, FilterGoods) of
        [Res, NewPlayerStatus, TypeIdList] ->
            {ok, BinData} = pt_150:write(15021, [Res, TypeIdList]),
            lib_server_send:send_to_sid(NewPlayerStatus#player_status.sid, BinData),
            %% 对出售物品有特殊处理的加在下面
            TmpPlayerStatus2 = lib_fishing:sell_fishing_rod(NewPlayerStatus, TypeIdList),
            {ok, TmpPlayerStatus2};
        Err ->
            ?ERR("sell_goods error:~p~n", [Err])
    end;

%% 物品兑换
handle(15022, Player, [GoldExchangeTimes, GoodsExchangeTimes]) when GoldExchangeTimes > 0 orelse GoodsExchangeTimes > 0 ->
    case lib_goods_exchange:exchange(Player, GoldExchangeTimes, GoodsExchangeTimes) of
        {ok, NewPlayer, Strike} ->
            {ok, BinData} = pt_150:write(15022, [1, Strike]),
            lib_server_send:send_to_sid(Player#player_status.sid, BinData),
            GoldExchangeTimes > 0 andalso
                handle(15026, NewPlayer, []),
            {ok, NewPlayer};
        {false, ErrCode} ->
            {ok, BinData} = pt_150:write(15022, [ErrCode, 0]),
            lib_server_send:send_to_sid(Player#player_status.sid, BinData),
            ok
    end;

%% 吞噬信息
handle(15023, Player, []) ->
    #player_status{sid = Sid,
        goods_devour = #status_devour{lv = Lv, exp = Exp, is_auto = IsAuto, active_lv = ActiveLv}} = Player,
    {ok, Bin} = pt_150:write(15023, [Lv, Exp, IsAuto, ActiveLv]),
    lib_server_send:send_to_sid(Sid, Bin),
    ok;

%% 吞噬 pt_15024_[536870912109,536870912111,536870912308]
handle(15024, Player, [GoodsList]) when GoodsList =/= [] ->
    FilterGoods = lists:sublist(GoodsList, 50),
    case goods_devour:goods_devour(Player, lists:usort(FilterGoods)) of
        {false, ERR} ->
            {ok, Bin} = pt_150:write(15024, [ERR]),
            lib_server_send:send_to_sid(Player#player_status.sid, Bin),
            ok;
        {ok, NewPlayer} ->
            {ok, Bin} = pt_150:write(15024, [1]),
            lib_server_send:send_to_sid(Player#player_status.sid, Bin),
            handle(15023, NewPlayer, []),
            {ok, NewPlayer}
    end;
handle(15024, _Player, _) ->
    ok;

%% 设置自动吞噬状态
handle(15025, Player, [Type]) when Type =:= 0 orelse Type =:= 1 ->
    NewPlayer =  goods_devour:set_auto(Player, Type),
    {ok, NewPlayer};

%% 兑换情况
handle(15026, Player, []) ->
    Count = lib_goods_exchange:get_exchange_info(Player),
    Time  = lib_goods_exchange:get_free_exchange_time(Player),
    {ok, Bin} = pt_150:write(15026, [Count, Time]),
    lib_server_send:send_to_sid(Player#player_status.sid, Bin),
    ok;

%% 吞噬:激活额外等级属性
handle(15027, Player, [])  ->
    case goods_devour:active_point(Player) of
        {false, ERR} ->
            {ok, Bin} = pt_150:write(15027, [ERR, 0]),
            lib_server_send:send_to_sid(Player#player_status.sid, Bin),
            ok;
        {ok, NewPlayer, NextLv} ->
            {ok, Bin} = pt_150:write(15027, [1, NextLv]),
            lib_server_send:send_to_sid(Player#player_status.sid, Bin),
            handle(15023, NewPlayer, []),
            {ok, NewPlayer}
    end;

%% 使用物品
handle(15050, PlayerStatus, [GoodsId, GoodsTypeId, Num]) ->
    case lib_goods_do:use_goods(PlayerStatus, GoodsId, GoodsTypeId, Num) of
        [ignore, NewPlayerStatus|_] ->
            {ok, NewPlayerStatus};
        [{ErrCode, Args}, NewPlayerStatus|_] ->
            {ErrorCodeInt, ErrorCodeArgs} = util:parse_error_code({ErrCode, Args}),
            {ok, BinData} = pt_110:write(11017, [?FLOAT_TEXT_ONLY, ErrorCodeInt, ErrorCodeArgs]),
            lib_server_send:send_to_sid(PlayerStatus#player_status.sid, BinData),
            {ok, NewPlayerStatus};
        [false, {ErrCode, Args}|_] ->
            {ErrorCodeInt, ErrorCodeArgs} = util:parse_error_code({ErrCode, Args}),
            {ok, BinData} = pt_110:write(11017, [?FLOAT_TEXT_ONLY, ErrorCodeInt, ErrorCodeArgs]),
            lib_server_send:send_to_sid(PlayerStatus#player_status.sid, BinData),
            {ok, PlayerStatus};            
        [false, Error] ->
            {ok, BinData} = pt_150:write(15050, [Error, GoodsId, GoodsTypeId, 0, 0, 0, []]),
            lib_server_send:send_to_sid(PlayerStatus#player_status.sid, BinData),
            ok;
        [Res, NewPlayerStatus, NewNum, GoodsList] ->
            case is_integer(Res) of
                true  ->
                    {ok, BinData} = pt_150:write(15050, [Res, GoodsId, GoodsTypeId, NewNum, 0, Num, GoodsList]),
                    lib_server_send:send_to_sid(PlayerStatus#player_status.sid, BinData);
                false ->
                    ignore
            end,
            {ok, NewPlayerStatus};
        _R ->
            ?ERR("15050 return error:~p", [GoodsTypeId]),
            ok
    end;

%% 销毁物品
handle(15051, PlayerStatus, [ThrowType, GoodsList]) ->
    Res = lib_goods_do:throw_away(ThrowType, GoodsList),
    {ok, BinData} = pt_150:write(15051, [Res]),
    lib_server_send:send_to_sid(PlayerStatus#player_status.sid, BinData),
    ok;

%% 拾取掉落
handle(15053, Ps, [DropId]) ->
    case  lib_guild_api:check_in_guild_scene(Ps#player_status.scene) of
        false->
            IsCluster = lib_scene:is_clusters_scene(Ps#player_status.scene),
            case DropId rem 2 of %% 偶数为跨服掉落
                0 when IsCluster ->
                    PsArgs = lib_drop:trans_to_ps_args(Ps, ?NODE_CENTER),
                    Node = clusters_node:get_node(),
                    clusters_node:apply_cast(mod_drop, drop_pickup, [Node, DropId, PsArgs]);
                _ ->
                    PsArgs = lib_drop:trans_to_ps_args(Ps, ?NODE_GAME),
                    mod_drop:drop_pickup(none, DropId, PsArgs)
            end;
        _->
            ok
    end;

%% 一键拾取
handle(15054, Player, []) ->
    #player_status{
        id = RoleId,
        scene = Scene,
        scene_pool_id = ScenePool,
        copy_id = CopyId
    } = Player,
    %% 限制场景-副本场景/赏金BOSS场景
    SceneInfo = data_scene:get(Scene),
    CanPickUp =
    case SceneInfo of
        #ets_scene{type = ?SCENE_TYPE_DUNGEON} ->
            true;
        #ets_scene{type = ?SCENE_TYPE_REWARD_BOSS} ->
            true;
        _ ->
            false
    end,
    case CanPickUp of
        true  ->
            case SceneInfo#ets_scene.cls_type == ?SCENE_CLS_TYPE_CENTER of %% 跨服掉落
                true ->
                    clusters_node:apply_cast(mod_drop, pick_all, [node(), RoleId, Scene, ScenePool, CopyId, undefined]);
                false ->
                    mod_drop:pick_all(node(), RoleId, Scene, ScenePool, CopyId, undefined)
            end;
        false ->
            ingore
    end,
    ok;
    

%% 获取物品buff列表
handle(15055, PlayerStatus, []) ->
    lib_goods_buff:send_buff_notice(PlayerStatus);

%% 礼包每日使用次数
handle(15085, Ps, [GoodsTypeId]) ->
    case data_gift:get(GoodsTypeId) of
        #ets_gift{condition = Condition} ->
            case lists:keyfind(count, 1, Condition) of
                false -> skip;
                {count, _Count} ->
                    UseCount = lib_daily:get_count(Ps#player_status.id, ?MOD_GOODS, ?MOD_GOODS_GIFT, GoodsTypeId),
                    lib_server_send:send_to_sid(Ps#player_status.sid, pt_150, 15085, [GoodsTypeId, UseCount])
            end;
        _ ->
            skip
    end;

%% 领取自选宝箱的物品内容
%% Num:使用的数量
handle(15086, PlayerStatus, [Uid,GTypeID,Num,InitSeqList]) ->
    SeqList = lists:usort(InitSeqList),
    GoodsStatus = lib_goods_do:get_goods_status(),
    case lib_gift_check:check_use_optional_gift(PlayerStatus, GoodsStatus, Uid, GTypeID, Num, SeqList) of
        {fail, ErrCode} ->
            {ok, BinData} = pt_150:write(15086,[ErrCode]),
            lib_server_send:send_to_sid(PlayerStatus#player_status.sid, BinData);
        {ok, GoodsInfo, OptionalGift, GoodsList} ->
            case lib_gift_new:use_optional_gift(PlayerStatus, GoodsStatus, GoodsInfo, OptionalGift, GoodsList, Num) of
                {ok, Code, NewPs} ->
                    {ok, BinData} = pt_150:write(15086,[Code]),
                    lib_server_send:send_to_sid(PlayerStatus#player_status.sid, BinData),
                    {ok, NewPs};
                {fail, Code, _Reason} ->
                    ?ERR("handle 15086 error:~p", [_Reason]),
                    {ok, BinData} = pt_150:write(15086,[Code]),
                    lib_server_send:send_to_sid(PlayerStatus#player_status.sid, BinData),
                    {ok, PlayerStatus}
            end
    end;

%% 获取礼包内容
%% TypeId:礼包类型id
handle(15087, PlayerStatus, [TypeId]) ->
    lib_gift_new:get_gift_info(PlayerStatus, TypeId);

%% 获取每日获得的名望券数量
handle(15088, PlayerStatus, []) ->
    TodayNum = lib_daily:get_count(PlayerStatus#player_status.id, ?MOD_GOODS, 2),
    {ok, BinData} = pt_150:write(15088, [TodayNum]),
    lib_server_send:send_to_sid(PlayerStatus#player_status.sid, BinData),
    {ok, PlayerStatus};

handle(_Cmd, _Status, _Data) ->
    ?PRINT("pp_goods no match :~p~n", [{_Cmd, _Data}]),
    {error, "pp_goods no match"}.

%%% ----------------------------- export function -----------------------------
%% 查看装备列表本服
send_equip_list_local(Ps, ModId, ToRole) ->
    BinData = get_equip_list(Ps, ModId),
    lib_server_send:send_to_sid(ToRole, BinData).

%% 查看其他服务器玩家装备列表
send_equip_list_kf(Player, ModId, ToRole) ->
    BinData = get_equip_list(Player, ModId),
    clusters_node:apply_cast(lib_server_send, send_to_sid, [ToRole, BinData]),
    Player.

get_equip_list(Ps, ModId) ->
    #player_status{id = RoleId, off = Off, combat_power = Power} = Ps,
    case Off#status_off.goods_status of
        undefined -> GoodsStatus = lib_goods_do:get_goods_status(); %% 在线
        GoodsStatus -> skip     %% 离线
    end,
    EquipList = equipment_api:get_other_equipment_list(Ps, GoodsStatus),
    EquipListPack = lib_goods_util:pack_equipment_list(EquipList),
    {MateStage, MateStar} = mate_api:get_mate_goods(Ps),
    {ok, BinData} = pt_150:write(15011, [ModId, RoleId, EquipListPack, MateStage, MateStar, Power]),
    BinData.

%% 查看物品信息:本服节点
send_goods_info_local(Player, GoodsId, GoodsTypeId, FromSid) ->
    Bin = get_goods_info(Player, GoodsId, GoodsTypeId),
    lib_server_send:send_to_sid(FromSid, Bin),
    Player.

%% 查看物品信息:他服节点
send_goods_info_kf(Player, GoodsId, GoodsTypeId, FromSid) ->
    Bin = get_goods_info(Player, GoodsId, GoodsTypeId),
    clusters_node:apply_cast(lib_server_send, send_to_sid, [FromSid, Bin]),
    Player.

get_goods_info(Player, GoodsId, GoodsTypeId) ->
    #player_status{off = Off, combat_power = Power} = Player,
    GoodsStatus = case Off#status_off.goods_status of
        undefined -> lib_goods_do:get_goods_status(); %% 在线
        _GoodsStatus -> _GoodsStatus     %% 离线
    end,
    case data_goods_type:get(GoodsTypeId) of
        #ets_goods_type{bag_location = Location} ->
            GoodsInfo = find_goods(GoodsId, GoodsStatus#goods_status.dict, [Location|?GOODS_LOC_ALL]),
            case is_record(GoodsInfo, goods) of
                true  ->
                    GoodsInfo1 =
                    if
                        %% 如果是穿着的装备插入一些位置属性
                        GoodsInfo#goods.type =:= ?GOODS_TYPE_EQUIP andalso GoodsInfo#goods.location =:= ?GOODS_LOC_EQUIP ->
                            equipment_api:insert_into_equipment_attr(Player, GoodsInfo);
                        true ->
                            GoodsInfo
                    end,
                    [Data] = lib_goods_util:pack_goods_list([GoodsInfo1]),
                    GoodsData = tuple_to_list(Data),
                    {ok, Bin} = pt_150:write(15000, [Power|GoodsData]),
                    Bin;
                false ->
                    {ok, Bin} = pt_110:write(11000, [?ERRCODE(err150_info_overdue)]),
                    Bin
            end;
        _ ->
            {ok, Bin} = pt_110:write(11000, [?ERRCODE(err150_info_overdue)]),
            Bin
    end.
find_goods(GoodsId, Maps, [Location|T]) ->
    case lib_goods_util:get_goods(GoodsId, Maps, Location) of
        [] -> find_goods(GoodsId, Maps, T);
        GoodsInfo -> GoodsInfo
    end;
find_goods(_, _, _) -> [].
%%% ----------------------------- local function -----------------------------
