%%%-------------------------------------------------------------------
%%% @author liushl
%%% @doc
%%%     吞噬
%%% @end
%%%-------------------------------------------------------------------
-module(goods_devour).
-author("liushl").

-include("goods.hrl").
-include("equipment.hrl").
-include("server.hrl").
-include("predefine.hrl").
-include("errcode.hrl").
-include("figure.hrl").

%% API
-export([
    login/1,
    get_attr/1,
    goods_devour/2,
    set_auto/2,
    gm_set/2,
    active_point/1
]).

login(RoleId) ->
    case db_get_devour(RoleId) of
        [Lv, Exp, IsAuto, ActiveLv] ->
            calc_attr(#status_devour{lv = Lv, exp = Exp, is_auto = IsAuto, active_lv = ActiveLv});
        _ ->
            #status_devour{}
    end.

get_attr(Player) ->
    case Player#player_status.goods_devour of
        #status_devour{attr = Attr} -> Attr;
        _ -> []
    end.

calc_attr(#status_devour{lv = Lv, active_lv = ActiveLv} = Devour) ->
    Devour#status_devour{
        attr = data_goods_devour:get_devour_extra_attr(ActiveLv) ++ data_goods_devour:get_devour_lv_attr(Lv)
    }.

format_goods([GoodsId|T], GoodsMaps, List, TotalExp) ->
    case lib_goods_util:get_goods(GoodsId, GoodsMaps) of
        #goods{goods_id = TypeId, num = Num} = GoodsInfo ->
            case data_equipment:get_equipment_info(TypeId) of
                #base_equipment{devour_exp = Exp} when Exp > 0 ->
                    %% 装备可以吞噬
                    format_goods(T, GoodsMaps, [{GoodsInfo, 1}|List], TotalExp + Exp);
                _ ->
                    if
                        TypeId =:= 102602 ->
                            %% 小飞鞋可以吞噬，1个1点经验
                            format_goods(T, GoodsMaps, [{GoodsInfo, Num}|List], TotalExp + Num);
                        true ->
                            {false, ?MISSING_CONFIG}
                    end
            end;
        _ ->
            {false, ?ERRCODE(err150_no_goods)}
    end;
format_goods([], _, List, TotalExp) -> {List, TotalExp}.

%% 物品吞噬
goods_devour(Player, GoodsList) ->
    GoodsStatus = lib_goods_do:get_goods_status(),
    case format_goods(GoodsList, GoodsStatus#goods_status.dict, [], 0) of
        {false, Err} -> {false, Err};
        {CostList, AddExp} ->
            Res = lib_goods_api:delete_more_by_list(Player, CostList, goods_devour),
            case Res =:= 1 of
                true  ->
                    contract_task_api:goods_devour_trigger(Player#player_status.id, length(CostList)), 
                    {ok, add_devour_exp(Player, AddExp)};
                false -> 
                    {false, 0}
            end
    end.

add_devour_exp(Player, Exp) ->
    #player_status{goods_devour = Devour, id = RoleId, figure = Figure} = Player,
    #status_devour{exp = OldExp} = Devour,
    Devour1 = add_devour_exp_do(Devour#status_devour{exp = OldExp + Exp}),
    Devour2 = calc_attr(Devour1),
    db_save_devour(RoleId, Devour2),
    lib_log_api:log_devour(RoleId, Figure#figure.name, Exp, Devour2#status_devour.lv, Devour2#status_devour.exp),
    Player1 = Player#player_status{goods_devour = Devour2},
    case Devour2#status_devour.lv > Devour#status_devour.lv of
        true  ->
            Player2 = lib_player:count_player_attribute(Player1),
            lib_player:send_attribute_change_notify(Player2, ?NOTIFY_ATTR),
            Player2;
        false ->
            Player1
    end.

add_devour_exp_do(#status_devour{lv = Lv, exp = Exp} = Devour) ->
    case data_goods_devour:get_devour_lv_exp(Lv+1) of
        [] ->
            %% 配置满级了
            Devour;
        _  ->
            case data_goods_devour:get_devour_lv_exp(Lv) of
                0 ->
                    %% 也认为满级了，就这样
                    Devour;
                NeedExp when NeedExp =< Exp ->
                    %% 可以升一级
                    add_devour_exp_do(Devour#status_devour{lv = Lv + 1, exp = Exp - NeedExp});
                _ ->
                    %% 就这样
                    Devour
            end
    end.

%% 设置自动吞噬
set_auto(Player, IsAuto) ->
    #player_status{goods_devour = Devour, id = RoleId} = Player,
    case IsAuto =/= Devour#status_devour.is_auto of
        true  ->
            Devour1 = Devour#status_devour{is_auto = IsAuto},
            db_save_devour(RoleId, Devour1),
            Player1 = Player#player_status{goods_devour = Devour1},
            pp_goods:handle(15023, Player1, []),
            Player1;
        false ->
            Player
    end.

gm_set(Player, Lv) when Lv >= 0 ->
    #player_status{goods_devour = Devour, id = RoleId} = Player,
    Devour2 = calc_attr(Devour#status_devour{lv = Lv, exp = 0, active_lv = 0}),
    db_save_devour(RoleId, Devour2),
    Player1 = Player#player_status{goods_devour = Devour2},
    Player2 = lib_player:count_player_attribute(Player1),
    lib_player:send_attribute_change_notify(Player2, ?NOTIFY_ATTR),
    pp_goods:handle(15023, Player2, []),
    Player2.

%% 激活额外等级属性
active_point(Player) ->
    #player_status{goods_devour = Devour, id = RoleId} = Player,
    #status_devour{lv = Lv, active_lv = NowActive} = Devour,
    case get_next_lv(NowActive, data_goods_devour:get_all_active_lv()) of
        false -> {false, ?ERRCODE(err150_devour_max)};
        NextLv when NextLv > Lv -> {false, ?ERRCODE(err150_devour_condition)};
        NextLv ->
            Devour1 = Devour#status_devour{active_lv = NextLv},
            db_save_devour(RoleId, Devour1),
            Devour2 = calc_attr(Devour1),
            Player1 = Player#player_status{goods_devour = Devour2},
            Player2 = lib_player:count_player_attribute(Player1),
            lib_player:send_attribute_change_notify(Player2, ?NOTIFY_ATTR),
            {ok, Player2, NextLv}
    end.

get_next_lv(NowLv, [Lv|_]) when Lv > NowLv -> Lv;
get_next_lv(NowLv, [_|T]) -> get_next_lv(NowLv, T);
get_next_lv(_NowLv, []) -> false.
%% ---------------------------------------------------------------------------
%% @doc DB
%% ---------------------------------------------------------------------------
db_get_devour(RoleId) ->
    Sql = io_lib:format(<<"select devour_lv,devour_exp,is_auto,active_lv from player_devour where role_id=~p">>, [RoleId]),
    db:get_row(Sql).

db_save_devour(RoleId, StatusDevour) ->
    #status_devour{lv = Lv, exp = Exp, is_auto = IsAuto, active_lv = ActiveLv} = StatusDevour,
    Sql = io_lib:format(<<"replace into player_devour(role_id,devour_lv,devour_exp,is_auto,active_lv) values(~p,~p,~p,~p,~p)">>, [RoleId, Lv, Exp, IsAuto, ActiveLv]),
    db:execute(Sql).