%%%-------------------------------------------------------------------
%%% @author liushl
%%% @doc
%%%     装备系统接口
%%% @end
%%%-------------------------------------------------------------------
-module(equipment_api).
-author("liushl").

-include("def_goods.hrl").
-include("goods.hrl").
-include("equipment.hrl").
-include("server.hrl").
-include("def_module.hrl").
-include("predefine.hrl").
-include("def_event.hrl").
-include("errcode.hrl").
-include("language.hrl").
-include("figure.hrl").
-include("rec_offline.hrl").
-include("common.hrl").
-include("rush_rank.hrl").
%% API
-export([
    login/1
    , calc_power/3                   %% 计算装备系统战力-战力计算时的回调
    , get_attr/1                     %% 获得装备系统总总属性-战力计算时的回调
    , get_equipment_power/1          %% 获得装备系统总战力
    , when_init_equipment/1          %% 装备生成初始化
    , update_equipment_power/1       %% 更新装备系统战力
    , include_equipment_attr/1       %% 统计装备属性
    %% 物品进化之装备进化
    , equipment_evolution_check/1
    , equipment_evolution/2
    , after_equipment_evolution/3
    %% GM
    , gm_wear_equipment/3
    , gm_fix_bag/0
]).
-export([
    %% 获得所有装备
    get_all_equipment/0,
    get_all_equipment/1,
    get_all_equipment_list/0,
    get_all_equipment_list/1,
    %% 获得他人装备列表
    get_other_equipment_list/2,
    %% 获得某套装备
    get_series_equipment/1,
    get_series_equipment_list/1,
    %% 获得某个位置穿戴的装备
    get_series_pos_equipment/2,
    get_series_equipment_num/2,             %% 获得普通装备的数量
    get_equipment_wear_info/0,              %% 获得穿戴的装备信息
    get_equipment_wear_info_withno_jewelry/0, %% 获得穿戴的装备信息 无首饰
    get_equipment_wear_info1/0,             %% 获得穿戴的装备信息
    get_equipment_strength_info/0,          %% 获得装备强化信息
    get_equipment_rise_info/0,              %% 获得装备进化信息
    get_equipment_series_rise_info/0,       %% 获取装备套装进化信息
    get_equipment_empower_info/1,           %% 获得装备器灵信息
    get_equipment_empower_info_by_series/1,
    get_equipment_gems_info/1,              %% 获得宝石信息

    include_equipment_stars/0,              %% 统计装备的总星数

    %% 装备位置的信息
    get_equipment_series_pos_info/3,
    set_equipment_series_pos_info/2,

    %% 获得单件装备信息
    insert_into_equipment_attr/2,               %% 将某件装备插入一些绑定在位置的属性信息
    
    get_equipment_strength_lv/1,                %% 获得装备的强化等级
    get_equipment_strength_success_ratio/2,     %% 获得装备的强化成功率
    get_equipment_great_lv/1,                   %% 获得装备的进化等级
    get_equipment_series/1,                     %% 获得装备的套数
    get_equipment_careers/1,                    %% 获得装备的职业
    get_equipment_pos/1,                        %% 获取装备的槽位
    get_equipment_empower/3,                    %% 获得装备的器灵等级
    get_equipment_gems/3,                       %% 获得装备的宝石
    get_equipment_sp_attr/3,                    %% 获得装备的特殊属性信息
    get_equipment_cell_gems_lv/2,               %% 获得某个槽位宝石等级
    get_equipment_kind/1,                       %% 获得某件装备的种类
    
    is_series_pos_equip/2,                      %% 某个位置是否穿戴装备
    is_series_pos_equip/3,
    is_pos_equip/1,                             %% 是否是装备的位置
    check_equipment_career/2,                   %% 判断某职业能否穿某装备
    is_can_great_equip/1,                       %% 是否可以进化的装备
    %% 获得装备属性
    get_equipment_strength_attr/1,
    get_equipment_great_attr/2,
    get_equipment_part_attr/2,
    get_equipment_skills/1,
    set_equip_empower_attr/1
]).

login(Player) ->
    %% 装备套数位置通用信息：宝石/器灵
    EquipmentSeriesInfo =
        lists:foldl(
            fun([Series, Pos, GemsBin, Empower, SpLv, SpExp], Temp) ->
                SeriesInfo = maps:get(Series, Temp, #{}),
                PosInfo    = maps:put(
                    Pos,
                    #equipment_series{series = Series, pos = Pos, gems = util:bitstring_to_term(GemsBin), empower = Empower, sp_lv = SpLv, sp_exp = SpExp},
                    SeriesInfo
                ),
                maps:put(Series, PosInfo, Temp)
            end, #{},
            db:get_all(?SQL_GET_EQUIPMENT_SERIES, [Player#player_status.id])
        ),
    %% 星级套装
    case db:get_row(?SQL_GET_EQUIPMENT_INFO, [Player#player_status.id]) of
        [Stars,StarsInfoBin, UnlockSeries, FollowGuard, GemsSuitBin] ->
            Stars, StarsInfo = util:bitstring_to_term(StarsInfoBin), UnlockSeries, FollowGuard, GemsSuit = util:bitstring_to_term(GemsSuitBin);
        _ ->
            Stars = 0, StarsInfo = [], UnlockSeries = 1, FollowGuard = 0, GemsSuit = []
    end,
    RoleEquipment = #equipment{
        stars = Stars,
        stars_info = StarsInfo,
        unlock_series = UnlockSeries,
        equipment_series = EquipmentSeriesInfo,
        gems_suit = GemsSuit,
        follow_guard = FollowGuard
    },
    %% 装备收集
    RoleEquipment1 = equipment_collect:login(Player#player_status.id, RoleEquipment),
    Figure = Player#player_status.figure,
    Player1 = Player#player_status{equipment = RoleEquipment1, figure = Figure#figure{follow_guard = FollowGuard}},
    Player2 = include_equipment_attr(Player1),
    Player3 = set_equip_empower_attr(Player2),
    Player3.

%% 设置器灵属性
set_equip_empower_attr(Player) ->
    #player_status{equipment = Equipment} = Player,
    #equipment{} = Equipment,
    EmpowerAttr =
        maps:fold(
            fun(Series, SeriesInfo, EmpowerAttrTemp) ->
                %% 以套数为单位
                OneEmpowerAttr =
                    maps:fold(
                        fun(Pos, PosInfo, PosEmpowerAttr) ->
                            %% 以位置为单位
                            #equipment_series{empower = Empower} = PosInfo,
                            %% 器灵属性
                            case data_equipment:get_equipment_empower(Series, Pos, Empower) of
                                #base_equipment_empower{attr = OneEmpowerAttr} -> OneEmpowerAttr;
                                _ -> OneEmpowerAttr = []
                            end,
                            OneEmpowerAttr ++ PosEmpowerAttr
                        end, [], SeriesInfo
                    ),
                OneEmpowerAttr ++ EmpowerAttrTemp
            end, [], Equipment#equipment.equipment_series
        ),
    FinalEmpowerAttr = lib_player_attr:equipment_attr_convert(EmpowerAttr),
    NewEquipment = Equipment#equipment{empower_attr = FinalEmpowerAttr},
    Player#player_status{equipment = NewEquipment}.

%% 计算装备系统战力
calc_power(Player, AttrPower, BaseAttr) ->
    RoleEquipment = Player#player_status.equipment,
    case RoleEquipment of
        #equipment{extra_power = ExtraPower, attr = Attr, total_power = OldPower} ->
            PartialAttr = attr_conv:to_attr_record(Attr),
            Power       = lib_player_attr:calc_attr_power_partial(AttrPower, BaseAttr, PartialAttr) + ExtraPower,
            NewPlayer   = Player#player_status{equipment = RoleEquipment#equipment{total_power = Power}},
            lib_common_rank_api:refresh_rank_by_equip(NewPlayer),
            OldPower =/= Power andalso begin
                pp_equipment:handle(15226, NewPlayer, []),
                lib_rush_rank_api:refresh_rank_by_foster(?RANK_TYPE_RUSH_RED_EQUIP, NewPlayer),
                custom_act_circle_foster:combat_change_event(NewPlayer, ?RANK_TYPE_RUSH_RED_EQUIP)
            end,
            {NewPlayer, ExtraPower};
        _ ->
            {Player, 0}
    end.

%% 获得装备系统总总属性
get_attr(Player) ->
    case Player#player_status.equipment of
        #equipment{attr = Attr} ->
            Attr;
        _ ->
            []
    end.

%% 获得装备系统总战力
get_equipment_power(Player) ->
    case Player#player_status.equipment of
        #equipment{total_power = Power} ->
            Power;
        _ ->
            0
    end.

%%---------------------------------------------------------------------
%% @doc 更新战力，装备战力计算在回调 lib_player_attr:update_module_power/3 里通过调用equipment_api:calc_power/3计算
%%---------------------------------------------------------------------
update_equipment_power(Player) ->
    Player1 = include_equipment_attr(Player),
    Player2 = lib_player:count_player_attribute(Player1),
    lib_player:send_attribute_change_notify(Player2, ?NOTIFY_ATTR),
    mod_scene_agent:update(Player2, [{battle_attr, Player2#player_status.battle_attr}]),
    Player2.

%%---------------------------------------------------------------------
%% @doc 获得装备
%%---------------------------------------------------------------------
%% 获得所有装备 dict 格式返回
get_all_equipment() ->
    GoodsStatus = lib_goods_do:get_goods_status(),
    lib_goods_util:get_location_goods(GoodsStatus#goods_status.dict, ?GOODS_LOC_EQUIP).
get_all_equipment(GoodsStatus) ->
    lib_goods_util:get_location_goods(GoodsStatus#goods_status.dict, ?GOODS_LOC_EQUIP).

%% 获得所有装备 list 格式返回
get_all_equipment_list() ->
    GoodsStatus = lib_goods_do:get_goods_status(),
    get_all_equipment_list(GoodsStatus).
get_all_equipment_list(GoodsStatus) ->
    lib_goods_util:get_goods_list(GoodsStatus#goods_status.dict, ?GOODS_LOC_EQUIP).

%% 获得他人装备列表:插入宝石信息和器灵信息
get_other_equipment_list(Player, GoodsStatus) ->
    EquipList = get_all_equipment_list(GoodsStatus),
    [
        begin
            insert_into_equipment_attr(Player, GoodsInfo)
        end
        || GoodsInfo <- EquipList
    ].

%% 获得某套装备 dict 格式返回
get_series_equipment(Series) ->
    dict:filter(fun(_, #goods{cell = Cell}) -> ?EQUIPMENT_SERIES(Cell) =:= Series end, get_all_equipment()).

%% 获得某套装备 list 格式返回
get_series_equipment_list(Series) ->
    lists:filter(fun(#goods{cell = Cell}) -> ?EQUIPMENT_SERIES(Cell) =:= Series end, get_all_equipment_list()).

%% 获得普通装备的数量
get_series_equipment_num(Series, NeedColor) ->
    lists:foldl(
        fun
            (#goods{color = Color} = GoodsInfo, Temp) when Color =:= NeedColor ->
                case get_equipment_kind(GoodsInfo) =:= ?EQUIPMENT_KIND_NORMAL of
                    true  ->
                        Temp + 1;
                    false ->
                        Temp
                end;
            (_, Temp) -> Temp
        end, 0, get_series_equipment_list(Series)
    ).

%% 获得穿戴的装备信息 return:[{套数,品质,数量}|_]
get_equipment_wear_info() ->
    lists:foldl(
        fun(GoodsInfo, Temp) ->
            Series = get_equipment_series(GoodsInfo),
            #goods{color = Color} = GoodsInfo,
            case Series >= 0 of
                true  ->
                    case lists:keyfind(Series, 1, Temp) of
                        {_, Color, Num} ->
                            lists:keyreplace(Series, 1, Temp, {Series, Color, Num+1});
                        _ ->
                            [{Series, Color, 1}|Temp]
                    end;
                false ->
                    Temp
            end
        end, [], get_all_equipment_list()
    ).

%% 获得穿戴的装备信息 return:[{套数,品质,数量}|_]
get_equipment_wear_info_withno_jewelry() ->
    lists:foldl(
        fun(GoodsInfo, Temp) ->
            Series = get_equipment_series(GoodsInfo),
            #goods{color = Color} = GoodsInfo,
            Kind = get_equipment_kind(GoodsInfo),
            case Series >= 0 andalso Kind =/= ?EQUIPMENT_KIND_JEWELRY of
                true ->
                    case lists:keyfind(Series, 1, Temp) of
                        {_, Color, Num} ->
                            lists:keyreplace(Series, 1, Temp, {Series, Color, Num+1});
                        _ ->
                            [{Series, Color, 1}|Temp]
                    end;
                false ->
                    Temp
            end
        end, [], get_all_equipment_list()
    ).

%% 获得穿戴的装备信息 return:[{装备类型, {品质=>数量} }|_]
get_equipment_wear_info1() ->
    lists:foldl(
        fun(GoodsInfo, Temp) ->
            #goods{color = Color, subtype = EquipType} = GoodsInfo,
            case lists:keyfind(EquipType, 1, Temp) of
                {_, ColorMap} when is_map(ColorMap) ->
                    Num = maps:get(Color, ColorMap, 0),
                    ColorMap1 = maps:put(Color, Num + 1, ColorMap);
                _ ->
                    ColorMap1 = maps:put(Color, 1, #{})
            end,
            lists:keystore(EquipType, 1, Temp, {EquipType, ColorMap1})
        end, [], get_all_equipment_list()
    ).

%% 获得装备强化信息：return:[{等级,数量}|_]
get_equipment_strength_info() ->
    lists:foldl(
        fun(GoodsInfo, Temp) ->
            Lv = get_equipment_strength_lv(GoodsInfo),
            case Lv > 0 of
                true  ->
                    case lists:keyfind(Lv, 1, Temp) of
                        {_, Num} ->
                            lists:keyreplace(Lv, 1, Temp, {Lv, Num+1});
                        _ ->
                            [{Lv, 1}|Temp]
                    end;
                false ->
                    Temp
            end
        end, [], get_all_equipment_list()
    ).

%% 获得装备进化信息：return:[{等级,数量}|_]
get_equipment_rise_info() ->
    lists:foldl(
        fun(GoodsInfo, Temp) ->
            Lv = get_equipment_great_lv(GoodsInfo),
            case Lv > 0 of
                true  ->
                    case lists:keyfind(Lv, 1, Temp) of
                        {_, Num} ->
                            lists:keyreplace(Lv, 1, Temp, {Lv, Num+1});
                        _ ->
                            [{Lv, 1}|Temp]
                    end;
                false ->
                    Temp
            end
        end, [], get_all_equipment_list()
    ).

%% 获得装备进化信息：return:#{套装 => [{等级,数量}|_]...}
get_equipment_series_rise_info() ->
    lists:foldl(
        fun(GoodsInfo, Temp) ->
            Series = get_equipment_series(GoodsInfo),
            Lv  = get_equipment_great_lv(GoodsInfo),
            Pos = get_equipment_pos(GoodsInfo),
            IsNormalEquip = lists:member(Pos, ?EQUIPMENT_NORMAL),
            case Series >= 0 andalso Lv > 0 andalso IsNormalEquip == true of
                true  ->
                    List = maps:get(Series, Temp, []),
                    NewList =
                    case lists:keyfind(Lv, 1, List) of
                        {_, Num} ->
                            lists:keyreplace(Lv, 1, List, {Lv, Num+1});
                        _ ->
                            [{Lv, 1}|List]
                    end,
                    maps:put(Series, NewList, Temp);
                false ->
                    Temp
            end
        end, #{}, get_all_equipment_list()
    ).

%% 获得装备器灵信息：return:[{等级,数量}|_]
get_equipment_empower_info(#player_status{equipment = Equipment}) ->
    get_equipment_empower_info(Equipment);
get_equipment_empower_info(#equipment{equipment_series = EquipmentSeriesInfo}) ->
    get_equipment_empower_info(EquipmentSeriesInfo);
get_equipment_empower_info(EquipmentSeriesInfo) ->
    maps:fold(
        fun(_Series, SeriesInfo, SeriesGemLvTemp) ->
            %% 以套数为单位
            maps:fold(
                fun
                    (_Pos, #equipment_series{empower = Lv}, PosGemLvTemp) when Lv > 0 ->
                        %% 以位置为单位
                        case lists:keyfind(Lv, 1, PosGemLvTemp) of
                            {_, Num} ->
                                lists:keyreplace(Lv, 1, PosGemLvTemp, {Lv, Num+1});
                            _ ->
                                [{Lv, 1}|PosGemLvTemp]
                        end;
                    (_Pos, _PosInfo, PosGemLvTemp) ->
                        PosGemLvTemp
                end, SeriesGemLvTemp, SeriesInfo
            )
        end, [], EquipmentSeriesInfo
    ).

get_equipment_empower_info_by_series(EquipmentSeriesInfo) ->
    maps:fold(
        fun(Series, SeriesInfo, SeriesTemp) ->
            %% 以套数为单位
            OneSeriesNum =
            maps:fold(
                fun
                    (_Pos, #equipment_series{empower = Lv}, SeriesNum) when Lv > 0 ->
                        SeriesNum + 1;
                    (_Pos, _PosInfo, SeriesNum) ->
                        SeriesNum
                end, 0, SeriesInfo
            ),
            [{Series, OneSeriesNum}|SeriesTemp]
        end, [], EquipmentSeriesInfo
    ).

%% 获得宝石信息：return:[{等级,数量}|_]
get_equipment_gems_info(EquipmentSeriesInfo) ->
    maps:fold(
        fun(_Series, SeriesInfo, SeriesGemLvTemp) ->
            %% 以套数为单位
            maps:fold(
                fun(_Pos, PosInfo, PosGemLvTemp) ->
                    %% 以位置为单位
                    #equipment_series{gems = Gems} = PosInfo,
                    lists:foldl(
                        fun({_, GemId}, GemLvTemp) ->
                            case data_equipment:get_equipment_gem_info(GemId) of
                                #base_equipment_gems{lv = GemLv} ->
                                    case lists:keyfind(GemLv, 1, GemLvTemp) of
                                        {_, Num} ->
                                            lists:keyreplace(GemLv, 1, GemLvTemp, {GemLv, Num+1});
                                        _ ->
                                            [{GemLv, 1}|GemLvTemp]
                                    end;
                                _ ->
                                    GemLvTemp
                            end
                        end, PosGemLvTemp, Gems
                    )
                end, SeriesGemLvTemp, SeriesInfo
            )
        end, [], EquipmentSeriesInfo
    ).

%% 获得绑定在装备位置的信息
get_equipment_series_pos_info(EquipmentSeries, Series, Pos) ->
    maps:get(
        Pos,
        maps:get(Series, EquipmentSeries, #{}),
        #equipment_series{series = Series, pos = Pos}
    ).

%% 写入装备位置的信息
set_equipment_series_pos_info(EquipmentSeries, GemsInfo) ->
    #equipment_series{series = Series, pos = Pos} = GemsInfo,
    SeriesInfo = maps:get(Series, EquipmentSeries, #{}),
    maps:put(
        Series,
        maps:put(Pos, GemsInfo, SeriesInfo),
        EquipmentSeries
    ).

%% 判断某职业能否穿某装备
check_equipment_career(#goods{goods_id = GoodsTypeId}, Career) ->
    check_equipment_career(GoodsTypeId, Career);
check_equipment_career(GoodsTypeId, Career) ->
    case data_equipment:get_equipment_info(GoodsTypeId) of
        #base_equipment{career = Careers} ->
            lists:member(Career, Careers);
        _ ->
            false
    end.

%% 获得某个位置穿戴的装备
get_series_pos_equipment(Series, Pos) ->
    EquipmentList = get_all_equipment_list(),
    Cell = ?EQUIPMENT_CELL(Series, Pos),
    case lists:keyfind(Cell, #goods.cell, EquipmentList) of
        #goods{} = GoodsInfo -> GoodsInfo;
        _ -> false
    end.

%% 某个位置是否穿戴装备
is_series_pos_equip(Series, Pos) ->
    EquipmentList = get_all_equipment_list(),
    is_series_pos_equip(EquipmentList, Series, Pos).
is_series_pos_equip(EquipmentList, Series, Pos) ->
    EquipmentList = get_all_equipment_list(),
    Cell = ?EQUIPMENT_CELL(Series, Pos),
    lists:keymember(Cell, #goods.cell, EquipmentList).
%% 是否是装备的位置
is_pos_equip(Pos) ->
    EquipmentList = get_all_equipment_list(),
    lists:keymember(Pos, #goods.subtype, EquipmentList).

%% 统计装备的总星数
include_equipment_stars() ->
    GoodsDict = get_all_equipment(),
    F = fun(_Key, GoodsInfo, StarNum) ->
        StarNum + get_equipment_great_lv(GoodsInfo)
        end,
    dict:fold(F, 0, GoodsDict).

%% 是否可以进化的装备
is_can_great_equip(#goods{color = Color, type = ?GOODS_TYPE_EQUIP} = GoodsInfo) ->
    case Color >= ?PURPLE andalso get_equipment_kind(GoodsInfo) =:= ?EQUIPMENT_KIND_NORMAL of
        true  ->
            true;
        false ->
            false
    end;
is_can_great_equip(_) -> false.
%%---------------------------------------------------------------------
%% @doc 装备基础信息
%%---------------------------------------------------------------------
%% 将某件装备插入一些绑定在位置的属性信息:宝石/器灵/sp_attr
insert_into_equipment_attr(Player, GoodsInfo) ->
    #goods{subtype = Pos} = GoodsInfo,
    Series   = get_equipment_series(GoodsInfo),
    GemsInfo = get_equipment_gems(Player, Series, Pos),
    Empower  = get_equipment_empower(Player, Series, Pos),
    Info     = [{?GOODS_OTHER_KEY_EQUIPMENT_GEMS, GemsInfo}, {?GOODS_OTHER_KEY_EQUIPMENT_EMPOWER, Empower}],
    Info1    = case get_equipment_kind(GoodsInfo) =/= ?EQUIPMENT_KIND_NORMAL of
                   true  ->
                       SpAttr = get_equipment_sp_attr(Player, Series, Pos),
                       [{?GOODS_OTHER_KEY_SP_ATTR, SpAttr}|Info];
                   false ->
                       Info
               end,
    goods_extra_data:extra_data_update(GoodsInfo, Info1).

%% 获得装备的强化等级
get_equipment_strength_lv(GoodsInfo) ->
    goods_extra_data:extra_data_get(GoodsInfo, ?GOODS_INFO_EQUIPMENT_LV, 0).
%% 获得装备的强化成功率
get_equipment_strength_success_ratio(GoodsInfo, Default) ->
    goods_extra_data:extra_data_get(GoodsInfo, ?GOODS_INFO_EQUIPMENT_SUCCESS_RATIO, Default).
%% 获得装备的进化等级
get_equipment_great_lv(GoodsInfo) ->
    case goods_extra_data:extra_data_get(GoodsInfo, ?GOODS_OTHER_KEY_EQUIPMENT_GREAT_LV, nil) of
        nil ->
            case data_equipment:get_equipment_info(GoodsInfo#goods.goods_id) of
                #base_equipment{great_attr_list = AttrList} -> length(AttrList);
                _ -> 0
            end;
        N ->
            N
    end.

%% 获得装备的套数
get_equipment_series(#goods{goods_id = GoodsTypeId}) ->
    get_equipment_series(GoodsTypeId);
get_equipment_series(GoodsTypeId) ->
    case data_equipment:get_equipment_info(GoodsTypeId) of
        #base_equipment{series = Series} ->
            Series;
        _ ->
            0
    end.
%% 获得装备的职业
get_equipment_careers(#goods{goods_id = GoodsTypeId}) ->
    get_equipment_careers(GoodsTypeId);
get_equipment_careers(GoodsTypeId) ->
    case data_equipment:get_equipment_info(GoodsTypeId) of
        #base_equipment{career = Careers} ->
            Careers;
        _ ->
            []
    end.
%% 获得装备的槽位
get_equipment_pos(#goods{subtype = SubType}) ->
    SubType;
get_equipment_pos(_) ->
    0.

%% 获得某个位置的器灵等级
get_equipment_empower(Player, Series, Pos) ->
    #player_status{equipment = RoleEquipment} = Player,
    #equipment_series{empower = Lv} =
        get_equipment_series_pos_info(RoleEquipment#equipment.equipment_series, Series, Pos),
    Lv.

%% 获得某件装备的宝石信息
get_equipment_gems(Player, Series, Pos) ->
    #player_status{equipment = RoleEquipment} = Player,
    #equipment_series{gems = Gems} =
        get_equipment_series_pos_info(RoleEquipment#equipment.equipment_series, Series, Pos),
    Gems.

%% 获得某个装备位置的宝石镶嵌情况
get_equipment_cell_gems_lv(RoleEquipment, Series) ->
    case maps:find(Series, RoleEquipment#equipment.equipment_series) of
        {ok, SeriesInfo} ->
            maps:fold(
                fun(_Pos, #equipment_series{gems = Gems}, Temp) ->
                    lists:sum(
                        [
                            case data_equipment:get_equipment_gem_info(GoodsId) of
                                #base_equipment_gems{lv = Lv} -> Lv;
                                _ -> 0
                            end || {_, GoodsId} <- Gems]
                    ) + Temp
                end, 0, SeriesInfo
            );
        _ ->
            0
    end.

%% 获得装备的特殊属性信息
get_equipment_sp_attr(Player, Series, Pos) ->
    #player_status{equipment = RoleEquipment} = Player,
    #equipment_series{sp_lv = SpLv, sp_exp = SpExp} =
        get_equipment_series_pos_info(RoleEquipment#equipment.equipment_series, Series, Pos),
    [{SpLv, SpExp}].

%% 获得某件装备的种类:
%%-define(EQUIPMENT_KIND_NORMAL,   1).    %% 装备类型：武器和防具
%%-define(EQUIPMENT_KIND_JEWELRY,  2).    %% 装备类型：首饰
%%-define(EQUIPMENT_KIND_GUARD,    3).    %% 装备类型：守护
get_equipment_kind(#goods{subtype = SubType}) ->
    case SubType =:= ?EQUIPMENT_GUARD of
        true  -> ?EQUIPMENT_KIND_GUARD;
        false ->
            case lists:member(SubType, ?EQUIPMENT_JEWELRY) of
                true  -> ?EQUIPMENT_KIND_JEWELRY;
                false -> ?EQUIPMENT_KIND_NORMAL
            end
    end.
%%---------------------------------------------------------------------
%% @doc 装备属性
%%---------------------------------------------------------------------
%% 获得装备的强化属性
get_equipment_strength_attr(GoodsInfo) ->
    Lv = get_equipment_strength_lv(GoodsInfo),
    case Lv > 0 of
        true  ->
            Series = get_equipment_series(GoodsInfo),
            case data_equipment:get_equipment_strength(Series, GoodsInfo#goods.subtype, Lv) of
                #base_equipment_strength{attr = StrengthAttr} ->
                    StrengthAttr;
                _ ->
                    []
            end;
        false ->
            []
    end.
%% 获得装备的高级属性
get_equipment_great_attr(Series, GoodsInfo) ->
    case is_can_great_equip(GoodsInfo) of
        true  ->
            GreatLv = get_equipment_great_lv(GoodsInfo),
            case data_equipment:get_equipment_great(Series, GoodsInfo#goods.subtype, GreatLv) of
                #base_equipment_great{attr = CommonAttr, great_attr_list = GreatAttr} ->
                    CommonAttr ++ trans_great_attr(GreatAttr);
                _ ->
                    []
            end;
        false ->
            []
    end.

%% 获得所有装备的局部属性
get_equipment_part_attr(GoodsDict, PartList) ->
    AttrList = lists:foldl(
        fun(EquipmentType, Temp) ->
            F = fun
                    (_Key, #goods{subtype = SubType, goods_id = GoodsId}, AttrTemp)
                        when SubType =:= EquipmentType ->
                        case data_equipment:get_equipment_info(GoodsId) of
                            #base_equipment{base_attr = BaseAttr} ->
                                BaseAttr ++ AttrTemp;
                            _ ->
                                AttrTemp
                        end;
                    (_, _, AttrTemp) ->
                        AttrTemp
                end,
            EquipmentTypeAttr = dict:fold(F, [], GoodsDict),
            EquipmentTypeAttr ++ Temp
        end, [], PartList
    ),
    util:combine_list(AttrList).

get_equipment_skills(Player) ->
    case Player#player_status.equipment of
        #equipment{skills = Skills} -> Skills;
        _ -> []
    end.
%%---------------------------------------------------------------------
%% @doc 统计装备属性
%% 每件装备的 基础属性 强化属性 卓越属性
%% 每一套装备的 强化套装属性/装备套装属性
%% 每套一份：宝石属性/宝石套装
%% 只有一套：每个装备位置的 印刻属性/器灵属性
%% 其他：星级总数属性
%%---------------------------------------------------------------------
%% 套装需要10件装备
include_equipment_attr(Player) ->
    #player_status{equipment = Equipment, off = StatusOff} = Player,
    case StatusOff#status_off.goods_status of
        undefined ->
            GoodsStatus = lib_goods_do:get_goods_status(),
            AllEquipment = get_all_equipment(GoodsStatus);
        GoodsStatus ->
            AllEquipment = get_all_equipment(GoodsStatus)
    end,
    %% 综合每一件装备的属性
    {GoodsAttr, StrengthInfo, SuitInfo} = equipment_goods_attr(AllEquipment),
    %% 强化套装属性
    StrengthAttr = maps:fold(
        fun
            (Key, {StrengthLv, EquipmentNum}, Temp) when EquipmentNum >= 10  ->
                AttrTotalStrength =  data_equipment:get_equipment_strength_total(Key, StrengthLv),
                AttrTotalStrength ++ Temp;
            (_Key, _, Temp) ->
                Temp
        end, [], StrengthInfo
    ),
    %% 装备套装属性
    SuitAttr = maps:fold(
        fun({SuitSeries, SuitType}, SuitNum, Temp) ->
            data_equipment:get_equipment_suit(SuitSeries, SuitType, SuitNum) ++ Temp
        end, [], SuitInfo
    ),

    %% 套数位置：宝石/器灵/sp_attr
    SeriesAttr = equipment_series_pos_attr(Equipment),
    %% 宝石套装
    GemSuitAttr = lists:foldl(
        fun({Series, TotalLv}, Temp) ->
            data_equipment:get_equipment_gems_total(Series, TotalLv) ++ Temp
        end, [], Equipment#equipment.gems_suit
    ),

    %% 星数属性
    StarTotalAttr = data_equipment_check:get_equipment_star_total(Equipment#equipment.stars),
    %% 星数节点选择属性
    StarBranchAttr = lists:foldl(
        fun({Stars, Choice}, Temp) ->
            case data_equipment_check:get_equipment_stars_branch(Stars) of
                [_|_] = Branches ->
                    case lists:keyfind(Choice, 1, Branches) of
                        {Choice, ChoiceAttr, _} ->
                            ChoiceAttr ++ Temp;
                        _ ->
                            Temp
                    end;
                _ ->
                    Temp
            end
        end, [], Equipment#equipment.stars_info
    ),
    %% 综合属性
    SumAttr = util:combine_list(StarTotalAttr ++ StarBranchAttr ++ GemSuitAttr ++ SeriesAttr ++ SuitAttr ++ StrengthAttr ++ GoodsAttr),
    %% 处理装备系统加成属性
    FinalAttr = lib_player_attr:equipment_attr_convert(SumAttr),
    NewEquipment = Equipment#equipment{attr = FinalAttr},
    Player#player_status{equipment = NewEquipment}.

%% 每个物品综合属性
equipment_goods_attr(GoodsDict) ->
    F = fun(_Key, GoodsInfo, {AttrTemp, StrengthMap, SuitMap}) ->
            case data_equipment:get_equipment_info(GoodsInfo#goods.goods_id) of
                #base_equipment{base_attr = BaseAttr, great_attr_list = _SpGreatAttr, series = Series} ->
                    %% 基础属性  BaseAttr
                    %% 首饰和守护的高级属性
                    SpGreatAttr = trans_great_attr(_SpGreatAttr),
                    %% 强化属性
                    StrengthAttr = get_equipment_strength_attr(GoodsInfo),
                    %% 高级属性
                    GreatAttr = get_equipment_great_attr(Series, GoodsInfo),
                    
                    Kind = get_equipment_kind(GoodsInfo),
                    %% 统计强化套装:守护不参与计算
                    case Kind =/= ?EQUIPMENT_KIND_GUARD of
                        true  ->
                            StrengthLv = get_equipment_strength_lv(GoodsInfo),
                            {SeriesStrengthLv, EquipmentNum} = maps:get(Series, StrengthMap, {max, 0}),
                            NewStrengthMap = maps:put(Series, {min(SeriesStrengthLv, StrengthLv), EquipmentNum+1}, StrengthMap);
                        false ->
                            NewStrengthMap = StrengthMap
                    end,
                    %% 统计装备套装，橙色以上装备和首饰,守护不参与计算
                    case Kind =/= ?EQUIPMENT_KIND_GUARD andalso GoodsInfo#goods.color >= ?ORANGE of
                        true  ->
                            Key = {Series, Kind},
                            SuitNum = maps:get(Key, SuitMap, 0),
                            NewSuitMap = maps:put(Key, SuitNum + 1, SuitMap);
                        false ->
                            NewSuitMap = SuitMap
                    end,

                    {BaseAttr ++ SpGreatAttr ++ StrengthAttr ++ GreatAttr ++ AttrTemp, NewStrengthMap, NewSuitMap};
                _ ->
                    {AttrTemp, StrengthMap, SuitMap}
            end
        end,
    {AttrThen, StrengthInfo, SuitInfo}
        = dict:fold(F, {[], #{}, #{}}, GoodsDict),
    {AttrThen, StrengthInfo, SuitInfo}.

%% 套装位置信息：宝石属性/器灵属性
equipment_series_pos_attr(Equipment) ->
    maps:fold(
        fun(Series, SeriesInfo, SeriesAttrTemp) ->
            %% 以套数为单位
            OneSeriesAttr =
                maps:fold(
                    fun(Pos, PosInfo, PosGemAttrTemp) ->
                        %% 以位置为单位
                        #equipment_series{gems = Gems, empower = Empower, sp_lv = SpLv} = PosInfo,
                        %% 宝石属性
                        OnePosGemsAttr =
                        lists:foldl(
                            fun({_, GemId}, GemAttrTemp) ->
                                case data_equipment:get_equipment_gem_info(GemId) of
                                    #base_equipment_gems{attr = OneGemAttr} ->
                                        OneGemAttr ++ GemAttrTemp;
                                    _ ->
                                        GemAttrTemp
                                end
                            end, [], Gems
                        ),
                        %% 器灵属性
                        case data_equipment:get_equipment_empower(Series, Pos, Empower) of
                            #base_equipment_empower{attr = OneEmpowerAttr} -> OneEmpowerAttr;
                            _ -> OneEmpowerAttr = []
                        end,
                        %% 成长属性
                        OneSpAttr =
                        case lists:member(Pos, ?EQUIPMENT_SPECIAL) of
                            true  ->
                                case data_equipment:get_equipment_sp_attr(Series, Pos, SpLv) of
                                    [{SpAttr, _}] -> SpAttr;
                                    _ -> []
                                end;
                            false -> []
                        end,
                        OneSpAttr ++ OneEmpowerAttr ++ OnePosGemsAttr ++ PosGemAttrTemp
                    end, [], SeriesInfo
            ),
            OneSeriesAttr ++ SeriesAttrTemp
        end, [], Equipment#equipment.equipment_series
    ).

trans_great_attr(AttrList) ->
    [{K, V} || {K, V, _} <- AttrList].
%%---------------------------------------------------------------------
%% @doc 装备生成时
%% 装备生成规则：
%% 首饰和守护，进化等级默认为最大值（配置的所有高级属性长度），不可进化
%% 紫色以下，进化等级为0，不可进化
%% 紫色及紫色以上，进化等级默认为1，可持续进化
%% 《装备-信息表》新增高级属性字段
%%首饰和守护在该字段内配置所有的高级属性（服务端统计属性用），前端属性展示也可以用该字段，进化等级就是该字段内高级属性的数量；
%%武器和防具该字段为空[]，根据实际进化等级读取《装备-进化配置》表获得属性，武器和防具的前端展示需要根据《装备-进化配置》内对应装备的最大进化等级展示所有属性
%%---------------------------------------------------------------------
when_init_equipment(GoodsInfo) ->
    %% 紫色以上普通装备进化等级为1，其他则无
    case is_can_great_equip(GoodsInfo) of
        true  ->
            goods_extra_data:extra_data_update(GoodsInfo, [{?GOODS_OTHER_KEY_EQUIPMENT_GREAT_LV, 1}]);
        false ->
            GoodsInfo
    end.

%%---------------------------------------------------------------------
%% @doc 物品进化之装备进化
%%---------------------------------------------------------------------
%% 条件检查
equipment_evolution_check(#goods{type = ?GOODS_TYPE_EQUIP} = GoodsInfo) ->
    CanEvolutionType = lists:member(GoodsInfo#goods.subtype, ?EQUIPMENT_SPECIAL),
    if
        not CanEvolutionType -> {false, ?ERRCODE(err152_evolution_type_err)};
        true ->
            true
    end;
equipment_evolution_check(_) -> true.

%% 守护升品，直接完成
equipment_evolution(_GoodsInfo, #goods{subtype = ?EQUIPMENT_GUARD} = NewGoodsInfo) ->
    NewGoodsInfo;
%% 首饰升品 保留强化等级/强化成功率
equipment_evolution(GoodsInfo, NewGoodsInfo) ->
    StrengthLv = get_equipment_strength_lv(GoodsInfo),
    ExtraData1 = case StrengthLv > 0 of
                    true  ->
                        [{?GOODS_INFO_EQUIPMENT_LV, StrengthLv}];
                    false ->
                        []
                end,
    Ratio = get_equipment_strength_success_ratio(GoodsInfo, 0),
    ExtraData2 = case Ratio > 0 of
                     true  ->
                         [{?GOODS_INFO_EQUIPMENT_SUCCESS_RATIO, Ratio}|ExtraData1];
                     false ->
                         ExtraData1
                 end,
    goods_extra_data:extra_data_update(NewGoodsInfo, ExtraData2).

%% 升品后处理
after_equipment_evolution(Player, FromGoods, NewGoods) ->
    #player_status{figure = #figure{name = Name}, id = RoleId} = Player,
    {ok, Player1} = lib_player_event:dispatch(Player, ?EVENT_EQUIP, get_all_equipment()),
    Player2 = update_equipment_power(Player1),
    #goods{goods_id = FromId, location = Location} = FromGoods,
    #goods{goods_id = NewId, id = GoodsId, subtype = SubType} = NewGoods,
    case SubType of
        ?EQUIPMENT_GUARD ->
            lib_chat:send_TV({all}, ?MOD_EQUIP, ?LAN_TV_EQUIPMENT_COMPOSE_GUARD, [Name, FromId, NewId]);
        _ ->
            lib_chat:send_TV({all}, ?MOD_EQUIP, ?LAN_TV_EQUIPMENT_COMPOSE_JEWELRY, [Name, FromId, RoleId, GoodsId, NewId])
    end,
    %% 如果是穿戴的守护升级后，要换成新的守护跟随
    case Location =:= ?GOODS_LOC_EQUIP of
        true  ->
            Player3 = equipment_logic:check_follow_guard(Player2, NewGoods);
        false ->
            Player3 = Player2
    end,
    %% 装备任务
    Player4 = equipment_task:event_equipment_evolution(Player3, NewGoods),
    StarNum = equipment_api:include_equipment_stars(),
    lib_task_api:rise_equip(Player4,StarNum),
    Player4.
%%---------------------------------------------------------------------
%% @doc GM操作
%%---------------------------------------------------------------------
gm_wear_equipment(Player, Series, Color) ->
    #player_status{
        id = RoleId,
        cell_num = CellNum,
        storage_num = StorageNum,
        figure = #figure{lv = Lv, career = Career}
    } = Player,
    %% 删除旧装备
    [
        db:execute("delete from goods where id=~p and role_id=~p", [OldId, RoleId])
        || #goods{id = OldId} <- get_series_equipment_list(Series)
    ],
    PosList = [1,2,3,4,5,6,7,8,9,10,11],
    _ = [
            [
                lists:any(
                    fun(GoodsId) ->
                        case data_equipment:get_equipment_info(GoodsId) of
                            #base_equipment{color = TheColor, series = TheSeries, career = Careers, lv = LvNeed}
                                when TheColor =:= Color
                                andalso (TheSeries =:= Series orelse TheSeries =:= 99)
                                andalso Lv >= LvNeed ->
                                case lists:member(Career, Careers) of
                                    true  ->
                                        GoodsTypeInfo = data_goods_type:get(GoodsId),
                                        GoodsInfo = lib_goods_util:get_new_goods(RoleId, GoodsTypeInfo, []),
                                        Cell = ?EQUIPMENT_CELL(Series, Pos),
                                        %% 满级属性
                                        ExtraData = [
                                            %% 强化等级
                                            {?GOODS_INFO_EQUIPMENT_LV, get_max_strength_lv(Series, Pos)}
                                        ],
                                        ExtraData1 =
                                        case Color >= ?PURPLE andalso lists:member(Pos, [1,2,3,4,5,6,7]) of
                                            true  ->
                                                [{?GOODS_OTHER_KEY_EQUIPMENT_GREAT_LV, 1}|ExtraData];
                                            false ->
                                                ExtraData
                                        end,
                                        lib_goods_util:add_goods(
                                            GoodsInfo#goods{
                                                cell = Cell,
                                                num = 1,
                                                bind = 1,
                                                location = ?GOODS_LOC_EQUIP,
                                                extra_data = ExtraData1
                                            }
                                        ),
                                        %% 触发装备收集
                                        lib_player:apply_cast(Player#player_status.pid, ?APPLY_CAST_STATUS,
                                            equipment_collect, check_collect, [GoodsInfo]),
                                        case TheSeries =/= 99 of
                                            true  ->
                                                %% 镶嵌满级宝石
                                                SeriesPos = #equipment_series{
                                                    series = Series
                                                    , pos = Pos
                                                    , gems = [{1, 109009}, {2, 109019}, {3, 109029}]     %% 镶嵌的宝石##[{类型，宝石id}]
                                                    , empower = get_max_empower_lv(Series, Pos)         %% 满级器灵
                                                },

                                                equipment_logic:save_equipment_series_pos_info(RoleId, SeriesPos),
                                                ok;
                                            false ->
                                                ok
                                        end,
                                        true;
                                    false ->
                                        false
                                end;
                            _ ->
                                false
                        end
                    end, data_goods_type:get_by_type(?GOODS_TYPE_EQUIP, Pos))
            ]
        || Pos <- PosList
    ],
    %% 物品初始化
    GoodsStatus = lib_goods_do:login(RoleId, Lv, CellNum, StorageNum),
    lib_goods_do:init_data(GoodsStatus),
    pp_goods:handle(15010, Player, [?GOODS_LOC_EQUIP]),
    Player2 = login(Player),
    pp_equipment:handle(15208, Player2, []),
    pp_equipment:handle(15213, Player2, []),
    update_equipment_power(Player2).

get_max_strength_lv(Series, Type) ->
    get_max_strength_lv(Series, Type, 0).
get_max_strength_lv(Series, Type, Lv) ->
    case data_equipment:get_equipment_strength(Series, Type, Lv+1) of
        [] -> Lv;
        _ -> get_max_strength_lv(Series, Type, Lv+1)
    end.

get_max_empower_lv(Series, Type) ->
    get_max_empower_lv(Series, Type, 0).
get_max_empower_lv(Series, Type, Lv) ->
    case data_equipment:get_equipment_empower(Series, Type, Lv+1) of
        [] -> Lv;
        _ -> get_max_empower_lv(Series, Type, Lv+1)
    end.

%% 修复背包
gm_fix_bag() ->
    case db:get_all(<<"select id,goods_id,subtype,extra_data from goods where type=5">>) of
        [] ->
            ignore;
        GoodsList ->
            Res =
            [
                begin
                    ExtraData = util:to_term(ExtraDataBin),
                    case lists:keytake(5, 1, ExtraData) of
                        {value, {5, IdList}, Left} ->
                            case data_equipment:get_equipment_info(GoodsId) of
                                #base_equipment{color = Color, equip_type = EquipType, series = Series } ->
                                    NewExtraData =
                                        case Color >= 3 andalso lists:member(EquipType, [1,2,3,4,5,6,7]) of
                                            true ->
                                                case fix_great_lv(Series, EquipType, length(IdList) - 2) of
                                                    ignore ->
                                                        Left;
                                                    GreatLv ->
                                                        [{21, fix_great_lv(Series, EquipType, GreatLv)}|Left]
                                                end;
                                            false ->
                                                Left
                                        end,
                                    db:execute(io_lib:format(<<"update goods set extra_data='~ts' where id=~p">>, [util:term_to_bitstring(NewExtraData), Id])),
                                    1;
                                _ ->
                                    0
                            end;
                        _ ->
                            0
                    end
                end
                || [Id, GoodsId, EquipType, ExtraDataBin] <- GoodsList
            ],
            ?INFO("fix goods num [~p]", [lists:sum(Res)])
    end.

fix_great_lv(_Series, _EquipType, GreatLv)when GreatLv =< 0 -> 1;
fix_great_lv(Series, EquipType, GreatLv) ->
    case data_equipment:get_equipment_great(Series, EquipType, GreatLv) of
        #base_equipment_great{} ->
            GreatLv;
        _ ->
            fix_great_lv(Series, EquipType, GreatLv - 1)
    end.

