%% ---------------------------------------------------------------------------
%% @doc    星辰系统
%% @author zmh
%% @since  20200817
%% ---------------------------------------------------------------------------
-module(lib_role_galaxy).


-include("role_galaxy.hrl").
-include("common.hrl").
-include("server.hrl").
-include("goods.hrl").
-include("def_goods.hrl").
-include("errcode.hrl").
-include("predefine.hrl").
-include("figure.hrl").
-include("skill.hrl").
-include("def_module.hrl").
-include("attr.hrl").
-include("def_event.hrl").
-include("rec_event.hrl").

-export([
        login/2                         %% 登录加载数据
        ,init_galaxy_goods/1            %% 生成随机技能
        ,upgrade_galaxy/3               %% 星辰升级
        ,send_galaxy_equip_info/2
        ,active_galaxy_pos/3            %% 激活槽位
        ,equip_galaxy/3                 %% 穿星辰
        ,upgrade_galaxy_skill/4         %% 升级星辰技能
        ,resolve_galaxy/2               %% 星辰分解
        ,reset_galaxy/2                 %% 星辰重置
        ,calc_power/3
        ,get_galaxy_attr/1              %% 系统哪些属性参加战力计算

        ,send_galaxy_skin_info/1        %% 查询皮肤信息
        ,upgrade_galaxy_skin/2          %% 皮肤激活/升级
        ,use_galaxy_skin/3              %% 皮肤幻化
        ,set_show_galaxy/2              %% 显示/隐藏外观

        ,send_shop_list/1               %% 发送物品列表
        ,refresh_item_list/1            %% 手动刷新物品列表
        ,buy_shop_item/2                %% 购买物品
        ,handle_event/2                 %% 每天零点刷市物品列表
        ,logout/1                       %% 下线处理
        ,send_galaxy_collect/1          %% 获取图鉴收集信息
        ,collect_goods/2                %% 图鉴收集
        ,fetch_galaxy_colllect/3        %% 领取
        ,update_galaxy_figure/2
    ]).

%% @doc 登录加载数据
login(RoleId, RoleLv) ->
    RoleGalaxy  = lib_galaxy_db:load_role_galaxy(RoleId),
    RoleGalaxy2 = calc_galaxy_attr(RoleLv, RoleGalaxy),
    RoleGalaxy3 = recalc_skill_list(RoleGalaxy2),
    RoleGalaxy3.

%% @doc 计算战力时，哪些属性参加战力计算
get_galaxy_attr(Status) ->
    #player_status{role_galaxy = RoleGalaxy} = Status,
    #role_galaxy{attrs = AttrList} = RoleGalaxy,
    AttrList.

calc_power(Status, AttrPower, BaseAttr) ->
    #player_status{role_galaxy=RoleGalaxy, figure = #figure{lv = RoleLv}}=Status,
    #role_galaxy{
        skill_list=Skills,
        skin_skills=SkinSkills,
        attrs = Attrs
    }=RoleGalaxy,
    {_,SPower} = lib_skill_attr:get_passive_skill_attr_and_power(Skills++SkinSkills, RoleLv),

    GalaxyAttr  = attr_conv:to_attr_record(Attrs),
    Power = lib_player_attr:calc_attr_power_partial(AttrPower, BaseAttr, GalaxyAttr),

    Combat = SPower+Power,
    NRoleGalaxy = RoleGalaxy#role_galaxy{power=Combat},
    NStatus = Status#player_status{role_galaxy=NRoleGalaxy},
    {NStatus, SPower}.

%% @doc 星辰升级
upgrade_galaxy(Status, Loc, Uid) ->
    case bag_galaxy_goods(Uid,Loc) of
        GoodsInfo = #goods{} ->
            upgrade_galaxy_do(Status,Loc,GoodsInfo);
        _ ->
            {false, ?ERRCODE(err148_not_goods)}
    end.

upgrade_galaxy_do(Status,Loc,GoodsInfo) ->
    #goods{
        goods_id = GoodsTypeId
    } = GoodsInfo,
    Lev = analyse_extra_data(GoodsInfo,?GOODS_OTHER_KEY_GALAXY_LV,1),
    CheckResult = case data_galaxy:get_galaxy_goods(GoodsTypeId) of
        #base_galaxy{color = Color} ->
            case data_galaxy:get_galaxy_lv(Color, Lev) of
                #base_galaxy_lv{next_lv=Lev0} when Lev0=<0->
                    {false, ?ERRCODE(err148_galaxy_max_lev)};
                #base_galaxy_lv{cost = CostList} = LevCfg ->
                    About = io_lib:format("~w, ~w", [GoodsTypeId, Color]),
                    case lib_goods_api:cost_object_list_with_check(Status, CostList, galaxy_lv_up, About) of
                        {true, Status2,_} ->
                            {true, Status2, CostList, LevCfg};
                        {false, ErrorCode, _Status2} ->
                            {false, ErrorCode}
                    end;
                _ ->
                    {false, ?ERRCODE(missing_config)}
            end;
        _ ->
            {false, ?ERRCODE(missing_config)}
    end,
    case CheckResult of
        {false, Reason} ->
            {false, Reason};
        {true, Status3, RealCostList, LevConfig} ->
            #base_galaxy_lv{broken = IsBreak,next_lv=NewLev} = LevConfig,
            GoodsInfo2 = update_extra_data(GoodsInfo, [{?GOODS_OTHER_KEY_GALAXY_LV,NewLev}]),
            case goods_logic:update_goods_info_extra([GoodsInfo2]) of
                {ok,_}->
                    %% 如果是上阵星辰的话需要重新计算战力
                    #player_status{role_galaxy = RoleGalaxy,id=RoleID,figure = #figure{name = RName, lv = RoleLv}} = Status,
                    NewStatus = case Loc =:= ?GOODS_LOC_GALAXY_EQUIP of
                        true -> %% 上阵的星辰
                            RoleGalaxy2 = calc_galaxy_attr(RoleLv, RoleGalaxy),
                            Status4 = Status3#player_status{role_galaxy = RoleGalaxy2},
                            Status5 = lib_player:count_player_attribute(Status4),
                            lib_player:send_attribute_change_notify(Status5, ?NOTIFY_ATTR),
                            Status5;
                        _ ->
                            Status3
                    end,
                    %% 传闻
                    case IsBreak of
                        1 ->
                            GalaxyName = data_goods:get_goods_name(GoodsTypeId),
                            TvData = [RName,RoleID,GalaxyName, NewLev],
                            lib_chat:send_TV(all, ?MOD_GALAXY, 1, TvData);
                        _ ->
                            ok
                    end,
                    lib_log_api:log_galaxy_change(RoleID,RName,1,GoodsTypeId,Lev,NewLev,RealCostList,[]),
                    {ok, NewStatus, NewLev};
                _R->
                    {false,?FAIL}
            end
    end.


%% @doc 星辰生成时要生成随机技能和资质
init_galaxy_goods(GoodsInfo) ->
    #goods{
        goods_id = GoodsTypeId, type = Type, subtype = SubType
        ,extra_data = GoodsOther
    } = GoodsInfo,
    case {Type, SubType} of
        {?GOODS_TYPE_GALAXY, ?GOODS_SUBTYPE_GALAXY} -> %%
            case data_galaxy:get_galaxy_goods(GoodsTypeId) of
                #base_galaxy{skill = SkillId, rand_skills = [RandNum,RandList]} ->
                    RandSkillIdList = urand:list_rand_by_weight(RandList, RandNum),
                    SkillList = init_skill_list(SkillId, RandSkillIdList),
                    NewGoodsOther =[{?GOODS_OTHER_KEY_GALAXY_SKILLS,SkillList},{?GOODS_OTHER_KEY_GALAXY_LV,1}|GoodsOther],
                    GoodsInfo#goods{extra_data = NewGoodsOther};
                _ ->
                    GoodsInfo
            end;
        _ ->
            GoodsInfo
    end.

%% 初始化技能列表
init_skill_list(SettledSkillId, SkillIdList) ->
    Skill = #f_s{
        skill_id = SettledSkillId, lev = ?DEFAULT_SKILL_LV
        ,is_settled = 1, pos = 1
    },
    init_skill_list_do(SkillIdList, 2, [Skill]).

init_skill_list_do([], _Pos, SkillList) ->
    SkillList;
init_skill_list_do([SkillId | T], Pos, SkillList) ->
    Skill = #f_s{
        skill_id = SkillId, lev = ?DEFAULT_SKILL_LV, pos = Pos
    },
    SkillList2 = [Skill | SkillList],
    init_skill_list_do(T, Pos + 1, SkillList2).


%% @doc 查询星辰上阵信息
send_galaxy_equip_info(OpTy,Status) ->
    #player_status{role_galaxy = RoleGalaxy, sid = Sid} = Status,
    #role_galaxy{
        power = Power,attrs=Attrs,pos_list=PosList,skill_list=SkillList
    } = RoleGalaxy,
    PosInfoList   = pos_list_info(OpTy,PosList),
    Data = [OpTy, Power, PosInfoList, Attrs,SkillList],
    {ok, Bin} = pt_148:write(14801, Data),
    lib_server_send:send_to_sid(Sid, Bin),
    ok.



%% 星辰上阵槽位信息
pos_list_info(OpTy,PosList) ->
    Galaxys   = get_all_equip_list(),
    PosIdList = case OpTy of
        0->
            data_galaxy:get_all_pos(0);
        1->
            data_galaxy:get_all_pos(1);
        _->
            data_galaxy:get_all_pos()
    end,
    pos_list_info(PosList, PosIdList, Galaxys, []).

pos_list_info(_PosList, [],_Galaxys, InfoList) ->
    InfoList;
pos_list_info(PosList, [Pos|T], Galaxys, InfoList) ->
    case lists:keyfind(Pos,#goods.cell,Galaxys) of
        #goods{id=Uid,goods_id=TypeId}->
                skip;
            _->
                Uid = 0,TypeId=0
    end,
    Info = case lists:keyfind(Pos, 1, PosList) of
        {_,IsOpen} ->
            {Pos, IsOpen, Uid, TypeId};
        _ ->
            case data_galaxy:get_galaxy_pos(Pos) of
                #base_galaxy_pos{cost = []} -> %% 不消耗的槽位默认已开
                    {Pos, ?POS_OPEN, Uid, TypeId};
                _ ->
                    {Pos, ?POS_NOT_OPEN, 0, 0}
            end
    end,
    pos_list_info(PosList, T, Galaxys, [Info | InfoList]).


%%槽位激活
active_galaxy_pos(Status, Pos, Auto)->
    #player_status{
        id=RoleId,
        figure=#figure{name=RName},
        role_galaxy = RoleGalaxy
    } = Status,
    #role_galaxy{pos_list = PosList} = RoleGalaxy,
    IsOpen = is_galaxy_pos_open(PosList, Pos),
    PosConfig = data_galaxy:get_galaxy_pos(Pos),
    PrePos = Pos - 1,
    MinorPrePos = check_minor_pos(Pos,PrePos),
    IsSort = PrePos =< 0 orelse MinorPrePos orelse
    is_galaxy_pos_open(PosList, PrePos) =:= ?POS_OPEN,
    if
        not is_record(PosConfig, base_galaxy_pos) ->
            {false, ?ERRCODE(missing_config)};
        IsOpen =:= ?POS_OPEN ->
            {false, ?ERRCODE(err148_pos_opened)};
        not IsSort ->
            {false, ?ERRCODE(err148_need_active_sort)};
        true ->
            case open_galaxy_pos_cost(Status, PosConfig, Auto) of
                {false, ErrorCode} ->
                    {false, ErrorCode};
                {true, Status2, CostList} ->
                    NPosList = lists:keystore(Pos,1,PosList,{Pos,?POS_OPEN}),
                    RoleGalaxy2 = RoleGalaxy#role_galaxy{pos_list = NPosList},
                    Status3 = Status2#player_status{role_galaxy = RoleGalaxy2},
                    lib_galaxy_db:save_role_galaxy(RoleId,RoleGalaxy2),
                    lib_log_api:log_galaxy_pos(RoleId,RName,PosConfig#base_galaxy_pos.type,Pos,CostList),
                    {ok, Status3}
            end
    end.

%%检测星位首个激活
check_minor_pos(Pos,PrePos)->
    PosT = data_galaxy:get_pos_type(Pos),
    PrePosT = data_galaxy:get_pos_type(PrePos),
    case PosT =:= PrePosT of
        true when PosT>=1->
            false;
        _->
            true
    end.

%% @doc槽位是否开启
is_galaxy_pos_open(PosList, Pos) ->
    case lists:keyfind(Pos,1, PosList) of
        {_,IsOpen} ->
            IsOpen;
        _ ->
            %% 不消耗的槽位默认已开
            case data_galaxy:get_galaxy_pos(Pos) of
                #base_galaxy_pos{cost = []} ->
                    ?POS_OPEN;
                _ ->
                    ?POS_NOT_OPEN
            end
    end.



%% 激活星辰槽位消耗
open_galaxy_pos_cost(Status, PosConfig, Auto) ->
    #base_galaxy_pos{
        id = PosId, cost = CostL
    } = PosConfig,
    About = io_lib:format("~w", [PosId]),
    CostType = galaxy_active_pos,
    %% 自动购买
    Fun = case Auto of
        0->
            cost_object_list_with_check;
        _->
            cost_objects_with_auto_buy
    end,
    case lib_goods_api:Fun(Status, CostL, CostType, About) of
        {true, Status2, CostList2} ->
            {true, Status2, CostList2};
        {false, ErrorCode, _Status2} ->
            {false, ErrorCode}
    end.

%% @doc 星辰装备
equip_galaxy(Status, Pos, Uid) ->
    Loc = ?GOODS_LOC_GALAXY_BAG,
    case bag_galaxy_goods(Uid,Loc) of
        GoodsInfo = #goods{} ->
            PosT = data_galaxy:get_pos_type(Pos),
            do_equip_galaxy(Status,PosT,GoodsInfo,Pos);
        _ ->
            {false, ?ERRCODE(err148_not_goods)}
    end.

%%阵位
do_equip_galaxy(Status,PosT,InGoodsInfo, Pos) ->
    GoodsStatus = lib_goods_do:get_goods_status(),
    #player_status{
        id = RoleID,
        scene = Scene,
        scene_pool_id = PoolID,
        copy_id = CopyId,
        x = X, y = Y,
        role_galaxy = RoleGalaxy,
        figure = Figure
    } = Status,
    #figure{name=RName, lv = RoleLv}=Figure,
    #role_galaxy{pos_list = PosList} = RoleGalaxy,
    IsOpen = is_galaxy_pos_open(PosList, Pos),
    PosConfig = data_galaxy:get_galaxy_pos(Pos),
    LocBag = ?GOODS_LOC_GALAXY_BAG,
    LocEquip = ?GOODS_LOC_GALAXY_EQUIP,
    if
        not is_record(PosConfig, base_galaxy_pos) ->
            {false, ?ERRCODE(missing_config)};
        IsOpen =:= ?POS_NOT_OPEN ->
            {false, ?ERRCODE(err148_pos_not_open)};
        true ->
            case check_put_on(PosT, InGoodsInfo) of
                {false, Reason} ->
                    {false, Reason};
                true ->
                    OutGoodsInfo =  get_pos_goods(Pos),
                    F = fun() ->
                        ok = lib_goods_dict:start_dict(),
                        case is_record(OutGoodsInfo, goods) of
                            true ->
                                [_NewInGoodsInfo, GoodsStatus1] = goods_logic:change_goods_location(InGoodsInfo, LocEquip, Pos, GoodsStatus),
                                [_NewOutGoodsInfo, NewGoodsStatus1] = goods_logic:change_goods_location(OutGoodsInfo, LocBag, 0, GoodsStatus1);
                            false ->
                                [_NewInGoodsInfo, NewGoodsStatus1] = goods_logic:change_goods_location(InGoodsInfo, LocEquip, Pos, GoodsStatus)
                        end,
                        #goods_status{
                            dict = Dict0
                        } = NewGoodsStatus1,
                        {NewGoodsDict, GoodsL0} = lib_goods_dict:handle_dict_and_notify(Dict0),
                        NewGoodsStatus2 = NewGoodsStatus1#goods_status{
                            dict = NewGoodsDict
                        },
                        {ok,NewGoodsStatus2,GoodsL0}
                    end,
                    case goods_transaction:transaction(F) of
                        {ok, NewGoodsStatus,GoodsL} ->
                            lib_goods_do:set_goods_status(NewGoodsStatus),
                            lib_goods_api:notify_client_num(RoleID, [InGoodsInfo#goods{num=0}]),
                            lib_goods_api:notify_client(RoleID, GoodsL, role_galaxy),

                            RoleGalaxy2 = calc_galaxy_attr(RoleLv, RoleGalaxy),
                            RoleGalaxy3 = recalc_skill_list(RoleGalaxy2),

                            NFigure = update_galaxy_figure(Figure,RoleGalaxy3),
                            Status1 = Status#player_status{role_galaxy = RoleGalaxy3,figure=NFigure},

                            NStatus = lib_player:count_player_attribute(Status1),
                            lib_player:send_attribute_change_notify(NStatus, ?NOTIFY_ATTR),

                            MinRoleGalaxy = update_role_show(RoleID,RoleGalaxy3),
                            update_skill_to_scene(NStatus, Status,[{role_galaxy,MinRoleGalaxy}]),
                            %%场景广播
                            {ok, Bin1} = pt_120:write(12016, [?MOD_GALAXY,3,RoleID,util:term_to_string(MinRoleGalaxy#role_galaxy.work_galaxy)]),
                            lib_server_send:send_to_area_scene(Scene,PoolID,CopyId,X,Y,Bin1),

                            case InGoodsInfo of
                                #goods{goods_id=IGoods}->
                                    skip;
                                _->
                                    IGoods=0
                            end,
                            case OutGoodsInfo of
                                #goods{goods_id=OGoods}->
                                    skip;
                                _->
                                    OGoods=0
                            end,
                            handle_galaxy_equip_achievement(NStatus),
                            lib_log_api:log_galaxy_equip(RoleID,RName,PosConfig#base_galaxy_pos.type,Pos,OGoods,IGoods),
                            {ok, NStatus};
                        _Reason->
                            ?INFO("~p ~p mod_goods equip_galaxy:~p", [?MODULE, ?LINE, _Reason]),
                            {false,?ERRCODE(fail)}
                    end
            end
    end.

handle_galaxy_equip_achievement(Player) ->
    GoodsStatus = lib_goods_do:get_goods_status(),
    List = lib_goods_util:get_goods_list(Player#player_status.id, ?GOODS_LOC_GALAXY_EQUIP, GoodsStatus#goods_status.dict),
    F = fun(#goods{color = Color}, TColorList) ->
        case lists:keyfind(Color, 1, TColorList) of
            {_, Num} -> lists:keystore(Color, 1, TColorList, {Color, Num + 1});
            _ -> lists:keystore(Color, 1, TColorList, {Color, 1})
        end;
        (_, TColorList) -> TColorList
        end,
    ColorList = lists:foldl(F, [], List),
    lib_achievement_api:galaxy_wear_event(Player, ColorList),
    ok.

%% 检查是否可以上阵
check_put_on(_,GoodsInfo) ->
    #goods{goods_id = GoodsTypeId} = GoodsInfo,
    AllMainGalaxys = get_all_equip_list(),
    case lists:keymember(GoodsTypeId, #goods.goods_id, AllMainGalaxys) of
        true -> %% 有同类型的，不能上阵
            {false, ?ERRCODE(err148_have_same_galaxy)};
        false ->
            true
    end.


%% @doc 登出加载数据
logout(Status) ->
    #player_status{id = RoleID, role_galaxy = RoleGalaxy} = Status,
    #role_galaxy{save_items = SaveItems} = RoleGalaxy,
    case SaveItems of
        1 ->
            lib_galaxy_db:save_role_galaxy(RoleID, RoleGalaxy);
        _ ->
            ok
    end,
    ok.

%% 重新计算技能列表
recalc_skill_list(RoleGalaxy) ->
    #role_galaxy{
        skin_list = SkinList
    } = RoleGalaxy,
    GoodsList = get_all_equip_list(),
    %% 星辰技能
    SkillList = recalc_skill_list_do(GoodsList, []),
    %% 皮肤技能
    SkillList2 = skin_skills([], SkinList),
    RoleGalaxy#role_galaxy{skill_list = SkillList,skin_skills=SkillList2}.

%% 星辰技能
recalc_skill_list_do([], SkillList) ->
    SkillList;
recalc_skill_list_do([Goods | T], SkillList) ->
    SkillList2 = combine_galaxy_skills(Goods, SkillList),
    recalc_skill_list_do(T, SkillList2).

%% 皮肤技能
skin_skills(SkillList, []) ->
    SkillList;
skin_skills(SkillList, [Skin | T]) ->
    SkillList2 = case Skin of
        #galaxy_skin{skin = SkinId, star = Star} ->
            case data_galaxy:get_galaxy_skin(SkinId, Star) of
                 #base_galaxy_skin{skill=SkillId} when SkinId>0->
                    [{SkillId, 1} | SkillList];
                _ ->
                    SkillList
            end;
        _ ->
            SkillList
    end,
    skin_skills(SkillList2, T).


%% @doc 合并星辰技能
combine_galaxy_skills(Goods, SkillList) ->
    GoodsSkillList = analyse_extra_data(Goods,?GOODS_OTHER_KEY_GALAXY_SKILLS,[]),
    combine_skills(GoodsSkillList, SkillList).

%% 合并技能
combine_skills([], SkillList) ->
    SkillList;
combine_skills([Skill | T], SkillList) ->
    #f_s{skill_id = SkillId, lev = Lev} = Skill,
    combine_skills(T, [{SkillId, Lev} | SkillList]).


%% @doc 计算战力属性(角色进场调用)
calc_galaxy_attr(RoleLv, RoleGalaxy, galaxy) ->
    GoodsList = get_all_equip_list(),
    GalaxyAttr  = calc_galaxy_equip_attr(RoleLv, GoodsList),
    WorkGalaxys = tidy_work_galaxy(GoodsList),
    RoleGalaxy#role_galaxy{attrs = GalaxyAttr,work_galaxy=WorkGalaxys};
calc_galaxy_attr(_RoleLv, RoleGalaxy, skin) ->
    #role_galaxy{skin_list = SkinList} = RoleGalaxy,
    SkinAttr = calc_galaxy_skin_attr(SkinList),
    RoleGalaxy#role_galaxy{skin_attr = SkinAttr}.
calc_galaxy_attr(RoleLv, RoleGalaxy) ->
    RoleGalaxy1 = calc_galaxy_attr(RoleLv, RoleGalaxy, galaxy),
    NRoleGalaxy = calc_galaxy_attr(RoleLv, RoleGalaxy1, skin),
    calc_galaxy_attr_do(NRoleGalaxy).

%% 更新战力属性
calc_galaxy_attr_do(RoleGalaxy) ->
    #role_galaxy{
         attrs = GalaxyAttr, skin_attr = SkinAttr
    } = RoleGalaxy,
    AttrList = lib_player_attr:add_attr(list, [GalaxyAttr, SkinAttr]),
    RoleGalaxy#role_galaxy{attrs = AttrList}.


%% @doc 计算灵珠物品属性
calc_galaxy_equip_attr(RoleLv, GoodsList) ->
    calc_galaxy_equip_attr(RoleLv, GoodsList, []).

calc_galaxy_equip_attr(_RoleLv, [], AttrList) ->
    AttrList;
calc_galaxy_equip_attr(RoleLv, [Goods | T], AttrList) ->
    Attr = calc_galaxy_goods_attr(Goods, RoleLv),
    AttrList2 = lib_player_attr:add_attr(list,[Attr,AttrList]),
    calc_galaxy_equip_attr(RoleLv, T, AttrList2).


%% @doc 计算星辰物品属性
calc_galaxy_goods_attr(Goods, RoleLv) ->
    #goods{goods_id = GoodsTypeId} = Goods,
    Lev = analyse_extra_data(Goods,?GOODS_OTHER_KEY_GALAXY_LV,1),
    SkillList = analyse_extra_data(Goods,?GOODS_OTHER_KEY_GALAXY_SKILLS,[]),
    LevAttr = case data_galaxy:get_galaxy_goods(GoodsTypeId) of
        #base_galaxy{attrs = AttrList,color=Color} ->
            case data_galaxy:get_galaxy_lv(Color,Lev) of
                #base_galaxy_lv{attrs=LevAttr0}->
                    lib_player_attr:add_attr(list, [LevAttr0,AttrList]);
                _->
                    AttrList
            end;
        _ ->
            []
    end,
    SkillList2 = [
        {SkillId, SLev} || #f_s{skill_id = SkillId, lev = SLev} <- SkillList
    ],
    SkillAttr = lib_skill_attr:get_passive_skill_attr(SkillList2, RoleLv),
    lib_player_attr:add_attr(list, [LevAttr, SkillAttr]).



%% @doc 计算星辰皮肤属
calc_galaxy_skin_attr(SkinList) ->
    calc_galaxy_skin_attr(SkinList, []).

calc_galaxy_skin_attr([], AttrList) ->
    lib_player_attr:add_attr(list, AttrList);
calc_galaxy_skin_attr([Skin | T], AttrList) ->
    #galaxy_skin{skin = SkinId, star = Star} = Skin,
    case data_galaxy:get_galaxy_skin(SkinId, Star) of
        #base_galaxy_skin{attrs = Attr} ->
            calc_galaxy_skin_attr(T, [Attr | AttrList]);
        _ ->
            calc_galaxy_skin_attr(T, AttrList)
    end.



%% @doc 更新技能变化到场景
update_skill_to_scene(NStatus, Status) ->
    update_skill_to_scene(NStatus, Status,[]).
update_skill_to_scene(NStatus, Status,UList) ->
    #player_status{role_galaxy = #role_galaxy{skill_list = SkillList}} = Status,
    #player_status{role_galaxy = #role_galaxy{skill_list = NewSkillList}} = NStatus,
    AddList = NewSkillList -- SkillList,
    DelList = SkillList -- NewSkillList,
    %% 既在AddList中也在DelList中的，说明只是等级变更了，需要排除
    DelList2 = [
        {SkillId, Lev} || {SkillId, Lev} <- DelList
        ,not lists:keymember(SkillId, 1, AddList)
    ],
    UpdateList = format_update_info_list(NStatus, add, AddList, UList),
    UpdateList2 = format_update_info_list(NStatus, del, DelList2, UpdateList),
    mod_scene_agent:update(NStatus, UpdateList2),
    ok.

%% 获取更新到场景的消息列表
format_update_info_list(_Role, _ChangeType, [], UpdateList) ->
    UpdateList;
format_update_info_list(Role, ChangeType, [{SkillId, Lev} | T], UpdateList) ->
    UpdateList2 = case data_skill:get(SkillId, Lev) of
        #skill{type = ?SKILL_TYPE_PASSIVE} ->
            case ChangeType of
                del ->
                    [{delete_passive_skill, [{SkillId, Lev}]} | UpdateList];
                add ->
                    [{passive_skill, [{SkillId, Lev}]} | UpdateList]
            end;
        #skill{type = ?SKILL_TYPE_PERMANENT_GAIN} ->
            case lists:keyfind(battle_attr, 1, UpdateList) of
                false ->
                    [{battle_attr, Role#player_status.battle_attr} | UpdateList];
                _ ->
                    UpdateList
            end;
        _ ->
            UpdateList
    end,
    format_update_info_list(Role, ChangeType, T, UpdateList2).


%% @doc 升级/学习星辰技能
upgrade_galaxy_skill(Status, Uid, Pos, CUid) ->
    case bag_galaxy_goods(Uid) of
        GalaxyGoods = #goods{goods_id = GoodsTypeId} ->
            GalaxyCfg = data_galaxy:get_galaxy_goods(GoodsTypeId),
            UseGoods  = bag_galaxy_goods(CUid,?GOODS_LOC_BAG),
            if
                not is_record(GalaxyCfg, base_galaxy) ->
                    {false, ?ERRCODE(missing_config)};
                Pos > GalaxyCfg#base_galaxy.skill_max ->
                    {false, ?ERRCODE(missing_config)};
                not is_record(UseGoods, goods) ->
                    {false, ?ERRCODE(err150_no_goods)};
                true ->
                    #goods{goods_id = UGoodsTypeId} = UseGoods,
                    SkillId = data_galaxy:get_item_skill(UGoodsTypeId),
                    case SkillId>0 of
                        true->
                            do_upgrade_galaxy_skill(Status, GalaxyGoods, Pos, UseGoods);
                        _->
                            {false,?ERRCODE(args_error)}
                    end
            end;
        _ ->
            {false, ?ERRCODE(err150_no_goods)}
    end.

do_upgrade_galaxy_skill(Status, GalaxyGoods, Pos, UseGoods) ->
    SkillList = analyse_extra_data(GalaxyGoods,?GOODS_OTHER_KEY_GALAXY_SKILLS),
    #goods{goods_id = GoodsTypeId} = UseGoods,
    SkillId = data_galaxy:get_item_skill(GoodsTypeId),

    % UniversalSkillGoods = data_flyman:get_config(universal_skill_goods),

    case lists:keytake(Pos, #f_s.pos, SkillList) of
        % {
        %     value, Skill = #f_s{}, RestList
        % } when GoodsTypeId =:= UniversalSkillGoods -> %% 已有技能，使用通用技能书升级
        %     upgrade_bead_skill_core(Role, GalaxyGoods, Skill, RestList, GoodsInfo);
        {value, Skill = #f_s{skill_id = SkillId}, RestList} -> %% 已有技能，升级技能
            upgrade_galaxy_skill_core(Status, GalaxyGoods, Skill, RestList, UseGoods);
        {value, #f_s{is_settled = 1}, _RestList} -> %% 已有技能，替换技能
            {false, ?ERRCODE(err148_is_settlet_skill)};
        {value, Skill, RestList} when is_integer(SkillId) -> %% 已有技能，替换技能
            GalaxyGoods2 = update_extra_data(GalaxyGoods,[{?GOODS_OTHER_KEY_GALAXY_SKILLS,RestList}]),
            learn_galaxy_skill(Status, GalaxyGoods2, Pos, UseGoods, Skill);
        _ -> %% 还没技能，学习技能
            PosList = [PosId || #f_s{pos = PosId} <- SkillList],
            NewPos = case PosList of
                [_ | _] -> lists:max(PosList) + 1;
                _ -> 1
            end,
            learn_galaxy_skill(Status, GalaxyGoods, NewPos, UseGoods, false)
    end.

%% 升级技能
upgrade_galaxy_skill_core(Status, GalaxyGoods, Skill, RestList, _UseGoods) ->
    % UniversalSkillGoods = data_flyman:get_config(universal_skill_goods),
    #f_s{skill_id = SkillId, lev = Lev} = Skill,
    NewLev = Lev + 1,
    CheckResult = case data_galaxy:get_galaxy_skill(SkillId, NewLev) of
        SkillCfg = #base_galaxy_skill{cost = Cost} ->
            % Cost2 = case GoodsTypeId of
            %     UniversalSkillGoods -> %% 是通用技能书，消耗转换为使用通用技能书
            %         [
            %             {CostType, UniversalSkillGoods, Num} ||
            %             {CostType, _, Num} <- Cost
            %         ];
            %     _ ->
            %         Cost
            % end,
            About = io_lib:format("~w, ~w", [SkillId, Lev]),
            case lib_goods_api:cost_object_list_with_check(
                    Status, Cost, galaxy_upgrade_skill, About) of
                {true, Status2,_} ->
                    {true, Status2, Cost, SkillCfg};
                {false, ErrorCode,_} ->
                    {false, ErrorCode}
            end;
        _ ->
            {false, ?ERRCODE(err148_skill_config_less)}
    end,
    case CheckResult of
        {false, Reason} ->
            {false, Reason};
        {true, Status3, _CostList, SkillConfig} ->
            Skill2 = Skill#f_s{lev = NewLev},
            SkillList = [Skill2 | RestList],
            #goods{location=CurLoc} = GalaxyGoods,
            GalaxyGoods2 = update_extra_data(GalaxyGoods,[{?GOODS_OTHER_KEY_GALAXY_SKILLS,SkillList}]),
            case goods_logic:update_goods_info_extra([GalaxyGoods2]) of
                {ok,_}->
                    %% 如果是上阵灵珠的话需要重新计算战力
                    #player_status{role_galaxy = RoleGalaxy, figure = #figure{lv = RoleLv}} = Status,
                    NewStatus = case CurLoc of
                        ?GOODS_LOC_GALAXY_EQUIP -> %%使用中的星辰
                            RoleGalaxy2 = calc_galaxy_attr(RoleLv, RoleGalaxy),
                            RoleGalaxy3 = recalc_skill_list(RoleGalaxy2),
                            Status4 = Status3#player_status{role_galaxy = RoleGalaxy3},
                            Status5 = lib_player:count_player_attribute(Status4),
                            lib_player:send_attribute_change_notify(Status5, ?NOTIFY_ATTR),
                            update_skill_to_scene(Status5, Status),
                            Status5;
                        _ ->
                            Status3
                    end,
                    %% 传闻
                    send_skill_tv(NewStatus, SkillConfig, GalaxyGoods2),
                    {ok, NewStatus, SkillId, NewLev};
                _R->
                    {false,?FAIL}
            end
    end.

%% 发送技能传闻
send_skill_tv(Status, SkillConfig, GalaxyGoods) ->
    #goods{color = Color, goods_id = GoodsTypeId} = GalaxyGoods,
    #base_galaxy_skill{
        id = SkillId,
        lv = Lev,
        color = SkillColor
    } = SkillConfig,
    #player_status{figure = #figure{name = Name}} = Status,
    GalaxyName = data_goods:get_goods_name(GoodsTypeId),
    SkillName = lib_skill_api:get_skill_name(SkillId,Lev),
    TvMsg = [Name, SkillColor, SkillName, Lev, Color, GalaxyName],
    case SkillColor of
        5 ->
            lib_chat:send_TV(all, ?MOD_GALAXY, 3, TvMsg);
        4 when Lev >= 3 ->
            lib_chat:send_TV(all, ?MOD_GALAXY, 3, TvMsg);
        _ ->
            case data_galaxy:get_galaxy_skill(SkillId, Lev + 1) of
               #base_galaxy_skill{} -> %% 不满级
                    ok;
                _ ->
                    lib_chat:send_TV(all, ?MOD_GALAXY, 3, TvMsg)
            end
    end,
    ok.

%% 学习技能
learn_galaxy_skill(Status, GalaxyGoods, Pos, UseGoods, OldSkill) ->
    #player_status{id=RoleID, figure = #figure{lv = RoleLv}}=Status,
    SkillList = analyse_extra_data(GalaxyGoods,?GOODS_OTHER_KEY_GALAXY_SKILLS),
    case check_learn_skill(Status, SkillList, UseGoods, GalaxyGoods, Pos) of
        {false, Reason} ->
            {false, Reason};
        {true, Status1, _CostList, SkillConfig, SkillId, Lev} ->
            Skill = #f_s{pos = Pos, skill_id = SkillId, lev = Lev},
            SkillList2 = [Skill | SkillList],
            #goods{location=CurLoc} = GalaxyGoods,
            GalaxyGoods2 = update_extra_data(GalaxyGoods,[{?GOODS_OTHER_KEY_GALAXY_SKILLS,SkillList2}]),

            case goods_logic:update_goods_info_extra([GalaxyGoods2]) of
                {ok, _}->
                    NewStatus = case CurLoc of
                        ?GOODS_LOC_GALAXY_EQUIP -> %% 使用中的星辰
                            #player_status{role_galaxy = RoleGalaxy} = Status,
                            RoleGalaxy2 = calc_galaxy_attr(RoleLv, RoleGalaxy),
                            RoleGalaxy3 = recalc_skill_list(RoleGalaxy2),
                            Status2 = Status1#player_status{role_galaxy = RoleGalaxy3},
                            Status3 = lib_player:count_player_attribute(Status2),
                            lib_player:send_attribute_change_notify(Status3, ?NOTIFY_ATTR),
                            update_skill_to_scene(Status3, Status),
                            Status3;
                        _ ->
                            Status1
                    end,
                    %% 传闻
                    send_skill_tv(NewStatus, SkillConfig, GalaxyGoods2),
                    % {OldSkillId, OldLev} = case OldSkill of
                    %     #f_s{skill_id = OSkillId, lev = OLev} -> {OSkillId, OLev};
                    %     _ -> {0, 0}
                    % end,
                    % LogData = [
                    %     RoleId, TypeId, OldSkillId, OldLev, SkillId, Lev
                    %     ,util:term_to_string(CostList), utime:unixtime()
                    % ],
                    % lib_log_api:log_flyman_bead_skill(LogData),
                    case OldSkill of
                        #f_s{} ->
                            Gains = calc_skill_back([OldSkill],[]),
                            Gains /= [] andalso begin
                                Produce = #produce{type=galaxy_upgrade_skill,reward=Gains},
                                lib_goods_api:send_reward_with_mail(RoleID, Produce, ?MOD_GALAXY)
                            end;
                        _->
                            skip
                    end,
                    {ok, NewStatus, SkillId, Lev};
                _R->
                    {false,?FAIL}
            end
    end.

check_learn_skill(Status, SkillList, UseGoods, GalaxyGoods, Pos) ->
    #goods{goods_id = GoodsTypeId} = UseGoods,
    Lev = ?DEFAULT_SKILL_LV,
    SkillId = data_galaxy:get_item_skill(GoodsTypeId),
    SkillConfig = data_galaxy:get_galaxy_skill(SkillId, Lev),
    #goods{goods_id = GalaxyTypeId} = GalaxyGoods,
    GalaxyConfig = data_galaxy:get_galaxy_goods(GalaxyTypeId),
    if
        not is_integer(SkillId) ->
            {false, ?ERRCODE(missing_config)};
        not is_record(SkillConfig, base_galaxy_skill) ->
            {false, ?ERRCODE(missing_config)};
        not is_record(GalaxyConfig, base_galaxy) ->
            {false, ?ERRCODE(missing_config)};
        Pos > GalaxyConfig#base_galaxy.skill_max ->
            {false, ?ERRCODE(err148_out_skill_pos)};
        true ->
            #base_galaxy_skill{cost = Cost} = SkillConfig,
            case check_is_repetitive(SkillId, SkillList) of
                {false, Reason} ->
                    {false, Reason};
                true ->
                    About = io_lib:format("~w, ~w", [SkillId, Lev]),
                    case lib_goods_api:cost_object_list_with_check(Status, Cost, galaxy_learn_skill, About) of
                        {true, Status2,_} ->
                            {true, Status2, Cost, SkillConfig, SkillId, Lev};
                        {false, ErrorCode, _} ->
                            {false, ErrorCode}
                    end
            end
    end.

%% 检查技能是否重复
check_is_repetitive(SkillId, SkillList) ->
    case data_galaxy:get_galaxy_skill(SkillId,1) of
         #base_galaxy_skill{is_repeate=1}->
            true;
        _->
            %% 不允许重复
            case lists:keyfind(SkillId, #f_s.skill_id, SkillList) of
                #f_s{} ->
                    {false, ?ERRCODE(err148_skill_pertivive)};
                _ ->
                    true
            end
    end.


%% @doc 星辰分解
resolve_galaxy(Uids,Status) ->
    #player_status{id=RoleID,figure=#figure{name=RName}}=Status,
    AllGoods = get_all_unequip_list(),
    AllDels  = filter_del_goods(Uids,AllGoods,[]),
    Gains    = calc_resolve_reback(1,AllDels),
    Costs    = [{Id,Gid,1}||#goods{id=Id,goods_id=Gid}<-AllDels],
    case lib_goods_api:delete_more_by_list(Status, Costs, galaxy_resolve) of
        1 ->
            Produce = #produce{type=galaxy_resolve,reward=Gains},
            lib_goods_api:send_reward_with_mail(RoleID, Produce, ?MOD_GALAXY),
            lib_log_api:log_galaxy_change(RoleID,RName,3,0,0,0,Costs,Gains),
            {ok,Gains};
        _R ->
            {false,?FAIL}
    end.

%% @doc 星辰重置
reset_galaxy(Uid,Status) ->
    #player_status{id=RoleID,figure=#figure{name=RName}}=Status,
    ReGoods  = bag_galaxy_goods(Uid,?GOODS_LOC_GALAXY_BAG),
    case is_record(ReGoods,goods) of
        true->
            Gains = calc_resolve_reback(0,[ReGoods]),
            OSKillList = analyse_extra_data(ReGoods,?GOODS_OTHER_KEY_GALAXY_SKILLS,[]),
            SkillList  = reset_skill(OSKillList,[]),
            KeyVs = [{?GOODS_OTHER_KEY_GALAXY_LV,1},{?GOODS_OTHER_KEY_GALAXY_SKILLS,SkillList}],
            NReGoods = update_extra_data(ReGoods,KeyVs),
            case goods_logic:update_goods_info_extra([NReGoods]) of
                {ok, _}->
                    Produce = #produce{type=galaxy_reset,reward=Gains},
                    lib_goods_api:send_reward_with_mail(RoleID, Produce, ?MOD_GALAXY),
                    lib_log_api:log_galaxy_change(RoleID,RName,2,NReGoods#goods.goods_id,0,0,[],Gains),
                    {ok,Gains};
                _R->
                    {false,?FAIL}
            end;
        _->
            {false,?ERRCODE(err148_not_goods)}
    end.


%% @doc 发送物品列表
send_shop_list(Status) ->
    #player_status{sid=Sid}=Status,
    RoleGalaxy = #role_galaxy{
        refresh_times = RefreshTimes, item_list = ItemList
    } = get_shop_data(Status),
    ItemInfoList = [
        {Pos, Id, IState} || #sale_item{pos = Pos, id = Id, status = IState}
        <- ItemList
    ],
    NTimes    = data_galaxy:get(treasure_refresh),
    LessTimes = max(0, NTimes - RefreshTimes),
    {ok, Bin} = pt_148:write(14810, [RefreshTimes, LessTimes, ItemInfoList]),
    lib_server_send:send_to_sid(Sid, Bin),
    Status#player_status{role_galaxy = RoleGalaxy}.


%% @doc 获取市场数据
get_shop_data(Status) ->
    #player_status{id = RoleId, role_galaxy = RoleGalaxy} = Status,
    #role_galaxy{refresh_time = RTime} = RoleGalaxy,
    Now = utime:unixtime(),
    case utime:is_same_day(Now, RTime) of
        true ->
            RoleGalaxy;
        false -> %% 需要刷新物品列表
            Status2 = refresh_shop_item_list(Status),
            #player_status{role_galaxy = RoleGalaxy2} = Status2,
            lib_galaxy_db:save_role_galaxy(RoleId, RoleGalaxy2),
            RoleGalaxy2#role_galaxy{save_items = 0}
    end.

%% @doc 刷新物品列表
refresh_shop_item_list(Status) ->
    #player_status{role_galaxy = RoleGalaxy} = Status,
    #role_galaxy{refresh_time = RTime, refresh_times = RTimes} = RoleGalaxy,
    Now = utime:unixtime(),
    RefreshTimes = case utime:is_same_day(Now, RTime) of
        true ->
            RTimes;
        false ->
            0
    end,
    PosList = data_galaxy:get_shop_pos_list(),
    ItemList = refresh_item_list(PosList, RefreshTimes, []),
    RoleGalaxy2 = RoleGalaxy#role_galaxy{
        refresh_time = Now, refresh_times = RefreshTimes, item_list = ItemList
    },
    Status#player_status{role_galaxy = RoleGalaxy2}.



handle_event(Status, #event_callback{type_id = ?EVENT_ZERO_CLOCK})->
    Status2 = refresh_shop_item_list(Status),
    #player_status{role_galaxy = RoleGalaxy} = Status2,
    %% 不保存数据库，标志为下线保存
    RoleGalaxy2 = RoleGalaxy#role_galaxy{save_items = 1},
    NStatus = Status2#player_status{role_galaxy = RoleGalaxy2},
    send_shop_list(NStatus),
    {ok, NStatus};
handle_event(PS, _) ->
    {ok, PS}.


%% @doc 刷新物品列表
refresh_item_list(Status) ->
    RoleGalaxy = get_shop_data(Status),
    #role_galaxy{refresh_times = RefreshTimes}=RoleGalaxy,
    CostList = refresh_cost(RefreshTimes),
    %% 宠物生活技能，每日免费刷新次数
    FreeTimes = lib_pet_api:pet_life_skill_about_galaxy_store_refresh_free(Status),
    UseTimes  = lib_daily:get_count(Status#player_status.id, ?MOD_GALAXY, 1),
    %% 有免费次数则修正消耗材料
    case UseTimes < FreeTimes of
        true ->
            lib_server_send:send_to_sid(Status#player_status.sid, pt_148, 14817,
                [max(0, FreeTimes-UseTimes-1)]
            ),
            lib_daily:increment(Status#player_status.id, ?MOD_GALAXY, 1),
            CostList1 = [];
        _ ->
            CostList1 = CostList
    end,
    About = io_lib:format("~w", [RefreshTimes]),
    case CostList1 =:= [] of
        true  ->
            do_refresh_item_list(Status#player_status{role_galaxy=RoleGalaxy#role_galaxy{refresh_times=RefreshTimes + 1}});
        false ->
            case lib_goods_api:cost_object_list_with_check(Status, CostList, galaxy_refresh_items, About) of
                {false, ErrorCode, _Status2} ->
                    {false, ErrorCode};
                {true, Status2,_} ->
                    do_refresh_item_list(Status2#player_status{role_galaxy=RoleGalaxy#role_galaxy{refresh_times=RefreshTimes + 1}})
            end
    end.

do_refresh_item_list(Status) ->
    Status1 = refresh_shop_item_list(Status),
    #player_status{id = RoleID, role_galaxy = RoleGalaxy} = Status1,
    RoleGalaxy2 = RoleGalaxy#role_galaxy{save_items = 0},
    lib_galaxy_db:save_role_galaxy(RoleID, RoleGalaxy2),
    Status2 = Status1#player_status{role_galaxy = RoleGalaxy2},
    send_shop_list(Status2),
    {ok, Status2}.

%% 刷新消耗
refresh_cost(RefreshTimes) ->
    CostConfig = case data_galaxy:get(cost_refresh) of
        CostList when is_list(CostList) ->
            lists:reverse(CostList);
        _ ->
            []
    end,
    refresh_cost(RefreshTimes, CostConfig, [{?TYPE_GOLD,0,99999}]).
refresh_cost(_RefreshTimes, [], Cost) ->
    Cost;
refresh_cost(RefreshTimes, [{Times, TimesCost} | T], Cost) ->
    case RefreshTimes >= Times of
        true ->
            TimesCost;
        false ->
            refresh_cost(RefreshTimes, T, Cost)
    end.


%% 刷新商店物品列表
refresh_item_list([], _RefreshTimes, ItemList) ->
    ItemList;
refresh_item_list([Pos | T], RefreshTimes, ItemList) ->
    WeightList = pos_candidate_list(Pos, RefreshTimes),
    ItemList2 = case urand:list_rand_by_weight(WeightList, 1) of
        [ItemId] ->
            [#sale_item{pos = Pos, id = ItemId} | ItemList];
        _ ->
            ItemList
    end,
    refresh_item_list(T, RefreshTimes, ItemList2).

%% 商店某个槽位的候选列表
pos_candidate_list(Pos, RefreshTimes) ->
    IdList = data_galaxy:get_item_list(Pos),
    pos_candidate_list_do(RefreshTimes, IdList, []).

pos_candidate_list_do(_RefreshTimes, [], CanList) ->
    CanList;
pos_candidate_list_do(RefreshTimes, [Id | T], CanList) ->
    CanList2 = case data_galaxy:get_galaxy_shop_item(Id) of
        #galaxy_shop_item{weight = Weight, times_weight = TimesWeight} ->
            TimesWeight2 = lists:reverse(TimesWeight),
            ItemWeight = item_id_weight(RefreshTimes, TimesWeight2, Weight),
            [{ItemWeight, Id} | CanList];
        _ ->
            CanList
    end,
    pos_candidate_list_do(RefreshTimes, T, CanList2).


%% 物品权重
item_id_weight(_RefreshTimes, [], Weight) ->
    Weight;
item_id_weight(RefreshTimes, [{Times, TimesWeight} | T], Weight) ->
    case RefreshTimes >= Times of
        true ->
            TimesWeight;
        false ->
            item_id_weight(RefreshTimes, T, Weight)
    end.

% ---------------------------------------------------------------------------
%% @doc 购买物品
buy_shop_item(Status, Pos) ->
    #player_status{id=RoleID}=Status,
    RoleGalaxy = #role_galaxy{item_list = ItemList} = get_shop_data(Status),
    Item = lists:keyfind(Pos, #sale_item.pos, ItemList),
    if
        not is_record(Item, sale_item) ->
            {false, ?ERRCODE(missing_config)};
        Item#sale_item.status =/= 0 ->
            {false, ?ERRCODE(err148_is_sold)};
        true ->
            case check_buy_item(Status, Item) of
                {false, Reason} ->
                    {false, Reason};
                {true, Status2, _CostList, Award, _ItemId} ->
                    Item2 = Item#sale_item{status = 1},
                    ItemList2 = lists:keystore(Pos, #sale_item.pos, ItemList, Item2),
                    RoleGalaxy2 = RoleGalaxy#role_galaxy{
                        item_list = ItemList2, save_items = 0
                    },
                    lib_galaxy_db:save_role_galaxy(RoleID, RoleGalaxy2),
                    Status3 = Status2#player_status{role_galaxy = RoleGalaxy2},
                    Produce = #produce{type=galaxy_buy_item,reward=Award},
                    lib_goods_api:send_reward_with_mail(RoleID, Produce, ?MOD_GALAXY),
                    {ok, Status3}
            end
    end.

%% 检查购买黑市物品
check_buy_item(Status, Item) ->
    #sale_item{id = Id} = Item,
    case data_galaxy:get_galaxy_shop_item(Id) of
        #galaxy_shop_item{cost=[], award = Award} ->
            CostList = [],
            {true, Status, CostList, Award, Id};
        #galaxy_shop_item{cost=CostList, award = Award} ->
            About = io_lib:format("~w", [Id]),
            case lib_goods_api:cost_object_list_with_check(Status, CostList, galaxy_buy_item, About) of
                {true, Status2,_} ->
                    {true, Status2, CostList, Award, Id};
                {false, ErrorCode, _Status2} ->
                    {false, ErrorCode}
            end;
        _ ->
            {false, ?ERRCODE(err148_item_config_miss)}
    end.



%% @doc 查询皮肤信息
send_galaxy_skin_info(Status) ->
    #player_status{role_galaxy = RoleGalaxy, sid = Sid} = Status,
    #role_galaxy{
        skin = Skin, skin_list = SkinList, display = IsDis
    } = RoleGalaxy,
    InfoList = galaxy_skin_info(SkinList),
    {ok, BinData} = pt_148:write(14807, [IsDis, Skin, InfoList]),
    lib_server_send:send_to_sid(Sid, BinData),
    ok.

%% 皮肤信息
galaxy_skin_info(SkinList) ->
    AllSkinList = data_galaxy:get_all_skins(),
    galaxy_skin_info(AllSkinList, SkinList, []).

%% 皮肤信息
galaxy_skin_info([], _SkinList, InfoList) ->
    InfoList;
galaxy_skin_info([SkinId | T], SkinList, InfoList) ->
    Info = case lists:keyfind(SkinId, #galaxy_skin.skin, SkinList) of
        #galaxy_skin{star = Star} -> {SkinId, 1, Star};
        _ -> {SkinId, 0, 0}
    end,
    galaxy_skin_info(T, SkinList, [Info | InfoList]).


%% @doc皮肤激活/升级
upgrade_galaxy_skin(SkinId,Status) ->
    #player_status{
        id = RoleId,
        scene = Scene,
        scene_pool_id = PoolID,
        copy_id = CopyId,
        x = X, y = Y,
        role_galaxy = RoleGalaxy,
        figure = Figure
    } = Status,
    #role_galaxy{
        skin = CurSkin,
        skin_list = SkinList
    } = RoleGalaxy,
    #figure{name=RName, lv = RoleLv}=Figure,
    AllIds = data_galaxy:get_all_skins(),
    case lists:member(SkinId,AllIds) of
        true->
            {
                Skin2, RestSkinList, IsActive
            } = case lists:keytake(SkinId, #galaxy_skin.skin, SkinList) of
                {value, Skin = #galaxy_skin{star = Star}, RestList} -> %% 已有，皮肤升级
                    {Skin#galaxy_skin{star = Star + 1}, RestList, false};
                _ ->
                    {#galaxy_skin{skin = SkinId}, SkinList, true}
            end,
            case upgrade_galaxy_skin_cost(Status, Skin2) of
                {false, ErrorCode} ->
                    {false, ErrorCode};
                {true, Status2, CostList} ->
                    SkinList2 = [Skin2 | RestSkinList],
                    lib_galaxy_db:save_galaxy_skin(RoleId, Skin2),
                    RoleGalaxy2 = RoleGalaxy#role_galaxy{skin_list = SkinList2},
                    RoleGalaxy3 = calc_galaxy_attr(RoleLv, RoleGalaxy2),
                    RoleGalaxy4 = recalc_skill_list(RoleGalaxy3),
                    {RoleGalaxy5, NewFigure} = case IsActive of
                        true -> %% 新激活的皮肤，默认幻化
                            lib_galaxy_db:update_skin(RoleId, SkinId),
                            RoleGalaxy4_2 = RoleGalaxy4#role_galaxy{skin = SkinId},
                            Figure2 = update_galaxy_figure(Figure,RoleGalaxy4_2),
                            {RoleGalaxy4_2, Figure2};
                        false ->
                            {RoleGalaxy4, Figure}
                    end,

                    Status3 = Status2#player_status{
                        role_galaxy = RoleGalaxy5, figure = NewFigure
                    },
                    Status4 = lib_player:count_player_attribute(Status3),
                    lib_player:send_attribute_change_notify(Status4, ?NOTIFY_ATTR),
                    case IsActive of
                        true ->
                            send_galaxy_skin_info(Status4),
                            {ok, Status5} = lib_wardrobe_active:active_galaxy(Status4, calc_galaxy_skin(SkinList2), get_active_cost(SkinId));
                        _ ->
                            Status5 = Status4
                    end,

                    #galaxy_skin{star=NStar}=Skin2,
                    case CurSkin =:= SkinId of
                        true-> %%已幻化皮肤需要更新场景和缓存
                            MinRoleGalaxy = update_role_show(RoleId,RoleGalaxy5),
                            mod_scene_agent:update(Status2, [{role_galaxy,MinRoleGalaxy}]),
                            %%场景广播
                            {ok, Bin1} = pt_120:write(12016, [?MOD_GALAXY,2,RoleId,util:term_to_string({SkinId,NStar})]),
                            lib_server_send:send_to_area_scene(Scene,PoolID,CopyId,X,Y,Bin1);
                        _->
                            skip
                    end,
                    lib_log_api:log_galaxy_skin(RoleId,RName,SkinId,CostList,NStar-1,NStar),
                    {ok,NStar,Status5}
            end;
        _->
            {false,?ERRCODE(missing_config)}
    end.

%% 统计激活的星辰皮肤
calc_galaxy_skin(SkinList) ->
    F = fun(#galaxy_skin{skin = SkinId}, TList) ->
            case data_galaxy:get_galaxy_skin(SkinId, 0) of
                #base_galaxy_skin{costs = [{_, GoodsId, _}|_]} ->
                    case data_goods_type:get(GoodsId) of
                        #ets_goods_type{color = Color} ->
                            case lists:keyfind({1, Color}, 1, TList) of
                                {_, Num} -> lists:keystore({1, Color}, 1, TList, {{1, Color}, Num + 1});
                                _ -> lists:keystore({1, Color}, 1, TList, {{1, Color}, 1})
                            end;
                        _ -> TList
                    end;
                _ -> TList
            end
        end,
    ColorList = lists:foldl(F, [], SkinList),
    ColorList.

%% 激活消耗
get_active_cost(SkinId) ->
    case data_galaxy:get_galaxy_skin(SkinId, 0) of
        #base_galaxy_skin{costs = [{_, GoodsId, _}|_]} -> ok;
        _ -> GoodsId = 0
    end,
    GoodsId.

%% 皮肤升级消耗
upgrade_galaxy_skin_cost(Status, Skin) ->
    #galaxy_skin{skin = SkinId, star = Star} = Skin,
    case data_galaxy:get_galaxy_skin(SkinId, Star) of
        #base_galaxy_skin{costs = Cost} ->
            About = io_lib:format("~w, ~w", [SkinId, Star]),
            case lib_goods_api:cost_object_list_with_check(Status, Cost, galaxy_upgrade_skin, About) of
                {true, Status2,_} ->
                    {true, Status2, Cost};
                {false, ErrorCode, _Status2} ->
                    {false, ErrorCode}
            end;
        _ ->
            {false, ?ERRCODE(err148_skin_max_star)}
    end.



%% @doc皮肤幻化
use_galaxy_skin(Status, OpTy, SkinId) ->
    #player_status{id = RoleId, role_galaxy = RoleGalaxy, figure = Figure} = Status,
    #role_galaxy{skin = UsingSkin, skin_list = SkinList} = RoleGalaxy,
    SkinInfo = case lists:keyfind(SkinId, #galaxy_skin.skin, SkinList) of
        SInfo = #galaxy_skin{} ->
            SInfo;
        _ ->
            false
    end,
    if
        not is_record(SkinInfo, galaxy_skin) andalso OpTy =:= 1 ->
            {false, ?FAIL};
        UsingSkin =:= SkinId andalso OpTy =:= 1 ->
            {false, ?ERRCODE(err148_use_same_skin)};
        true ->
            NUsingSkin = case OpTy of
                0 -> %% 取消幻化
                    0;
                _ ->
                    SkinId
            end,
            RoleGalaxy2 = RoleGalaxy#role_galaxy{skin = NUsingSkin},
            lib_galaxy_db:update_skin(RoleId, NUsingSkin),
            NFigure = update_galaxy_figure(Figure,RoleGalaxy2),
            NStatus = Status#player_status{role_galaxy = RoleGalaxy2, figure = NFigure},
            update_role_show(RoleId, RoleGalaxy2),
            {ok, NStatus}
    end.


%% @doc 角色#figure{}皮肤信息
format_galaxy_skin_info(RoleGalaxy) ->
    #role_galaxy{skin = SkinId, skin_list = SkinList} = RoleGalaxy,
    Star = case lists:keyfind(SkinId, #galaxy_skin.skin, SkinList) of
        #galaxy_skin{skin = SkinId, star = Star0} ->
            Star0;
        _ ->
            0
    end,
    {SkinId, Star}.


%% @doc 显示/隐藏星辰外观
set_show_galaxy(Status, Dis) ->
    #player_status{
        id = RoleId,
        scene = Scene,
        scene_pool_id = PoolID,
        copy_id = CopyId,
        x = X, y = Y,
        role_galaxy = RoleGalaxy,
        figure=Figure
    } = Status,
    #role_galaxy{display = CurDis} = RoleGalaxy,
    if
        Dis =:= CurDis ->
            NStatus = Status;
        true ->
            NRoleGalaxy = RoleGalaxy#role_galaxy{display = Dis},
            lib_galaxy_db:update_galaxy_display(RoleId, NRoleGalaxy),
            NFigure = update_galaxy_figure(Figure,NRoleGalaxy),
            NStatus = Status#player_status{role_galaxy = NRoleGalaxy,figure=NFigure},
            NStatus
    end,
    {ok,Bin} = pt_148:write(14816,[?SUCCESS,Dis]),
    lib_server_send:send_to_uid(RoleId,Bin),

    %%场景广播
    {ok, Bin1} = pt_120:write(12016, [?MOD_GALAXY,1,RoleId,Dis]),
    lib_server_send:send_to_area_scene(Scene,PoolID,CopyId,X,Y,Bin1),
    MinRoleGalaxy = update_role_show(RoleId,NStatus#player_status.role_galaxy),
    mod_scene_agent:update(NStatus,[{role_galaxy,MinRoleGalaxy}]),

    NStatus.


%%解析extra
analyse_extra_data(GoodsInfo,Key)->
    analyse_extra_data(GoodsInfo,Key,[]).
analyse_extra_data(GoodsInfo,Key,Default)->
    case GoodsInfo of
        #goods{extra_data=Extras}->
            case lists:keyfind(Key,1,Extras) of
                {_,Value}->
                    skip;
                _->
                    Value=Default
            end,
            Value;
        _->
            Default
    end.

%%更新extra
update_extra_data(GoodsInfo,[])->
    GoodsInfo;
update_extra_data(GoodsInfo,[{Key,Value}|T])->
    #goods{extra_data=Extras}=GoodsInfo,
    NExtras = lists:keystore(Key,1,Extras,{Key,Value}),
    update_extra_data(GoodsInfo#goods{extra_data=NExtras},T).


%%按照位置查找道具
get_pos_goods(Pos)->
    AllGoods = get_all_equip_list(),
    do_get_pos_goods(Pos,AllGoods).
do_get_pos_goods(Pos,AllGoods)->
    Galaxys = [G||G<-AllGoods,G#goods.cell=:=Pos],
    case Galaxys of
        [Galaxy|_]->
            Galaxy;
        _->
            none
    end.

%%查找道具
bag_galaxy_goods(Uid)->
    GoodsStatus = lib_goods_do:get_goods_status(),
    bag_galaxy_goods(Uid,GoodsStatus,[?GOODS_LOC_GALAXY_EQUIP,?GOODS_LOC_GALAXY_BAG]).

bag_galaxy_goods(Uid,Loc)->
    GoodsStatus = lib_goods_do:get_goods_status(),
    bag_galaxy_goods(Uid,GoodsStatus,[Loc]).

bag_galaxy_goods(_Uid,_GoodsStatus,[])->
    none;
bag_galaxy_goods(Uid,GoodsStatus,[Loc|T])->
    case lib_goods_util:get_goods(Uid, GoodsStatus#goods_status.dict, Loc) of
        GoodsInfo = #goods{} ->
            GoodsInfo;
        _ ->
            bag_galaxy_goods(Uid,GoodsStatus,T)
    end.


%%获取星辰背包所有道具
get_all_unequip_list()->
    GoodsStatus = lib_goods_do:get_goods_status(),
    LocEquip = ?GOODS_LOC_GALAXY_BAG,
    AllGoods = lib_goods_util:get_goods_list(GoodsStatus#goods_status.dict, LocEquip),
    AllGoods.


%% 获得所有装备 list 格式返回
get_all_equip_list() ->
    get_all_equip_list(all).
get_all_equip_list(Type) ->
    GoodsStatus = lib_goods_do:get_goods_status(),
    get_all_equip_list(Type,GoodsStatus).
get_all_equip_list(Type,GoodsStatus) ->
    LocEquip = ?GOODS_LOC_GALAXY_EQUIP,
    AllGoods = lib_goods_util:get_goods_list(GoodsStatus#goods_status.dict, LocEquip),
    case Type of
        all->
            AllGoods;
        _->
            filter_equips_pos_type(Type,AllGoods,[])
    end.

filter_equips_pos_type(_,[],AllGoods)->
    AllGoods;
filter_equips_pos_type(Type,[H|T],AllGoods)->
    #goods{cell=Pos}=H,
    PosT = data_galaxy:get_pos_type(Pos),
    case PosT =:= Type of
        true->
            filter_equips_pos_type(Type,T,[H|AllGoods]);
        _->
            filter_equips_pos_type(Type,T,AllGoods)
    end.


%%技能重置
reset_skill([],Skills)->
    Skills;
reset_skill([H|T],Skills)->
    case H of
        #f_s{is_settled=1}->
            reset_skill(T,[H#f_s{lev=1}|Skills]);
        _->
            reset_skill(T,Skills)
    end.

%%过滤筛选有效道具
filter_del_goods([],_AllGoods,DelList)->
    DelList;
filter_del_goods([H|T],AllGoods,DelList)->
    case lists:keyfind(H,#goods.id,AllGoods) of
        HGoods when is_record(HGoods,goods)->
            filter_del_goods(T,AllGoods,[HGoods|DelList]);
        _->
            filter_del_goods(T,AllGoods,DelList)
    end.

%%计算消耗
calc_resolve_reback(IsDes,AllDels)->
    calc_resolve_reback(IsDes,AllDels,[]).
calc_resolve_reback(_IsDes,[],Gains)->
    lib_goods_api:make_reward_unique(Gains);
calc_resolve_reback(IsDes,[H|T],Gains)->
    #goods{goods_id=GTypeId} = H,
    #base_galaxy{color=Color} = data_galaxy:get_galaxy_goods(GTypeId),
    Lv = analyse_extra_data(H,?GOODS_OTHER_KEY_GALAXY_LV,1),
    Skills     = analyse_extra_data(H,?GOODS_OTHER_KEY_GALAXY_SKILLS),
    GainsLv    = calc_lv_back(IsDes,GTypeId,Color,max(Lv-1,0),[]),
    GainsSkill = calc_skill_back(Skills,[]),
    Gains0 = GainsLv++GainsSkill,
    calc_resolve_reback(IsDes,T,Gains0++Gains).

calc_lv_back(0,_GTypeId,_,Lv,Gains) when Lv=<0->
    Gains;
calc_lv_back(1,GTypeId,_,Lv,Gains) when Lv=<0->
    case data_galaxy:get_galaxy_goods(GTypeId) of
        #base_galaxy{resolve=Gains0}->
            Gains0++Gains;
        _->
            Gains
    end;
calc_lv_back(IsDes,GTypeId,Color,Lv,Gains)->
    case data_galaxy:get_galaxy_lv(Color,Lv) of
        #base_galaxy_lv{cost=Cost}->
            skip;
        _->
            Cost = []
    end,
    calc_lv_back(IsDes,GTypeId,Color,Lv-1,Cost++Gains).

calc_skill_back([],Gains)->
    lib_goods_api:make_reward_unique(Gains);
calc_skill_back([H|T],Gains)->
    #f_s{skill_id=SkillId,lev=Lv,is_settled=IsSet}=H,
    Gains0 = do_calc_skill_back(SkillId,Lv,IsSet,[]),
    calc_skill_back(T,Gains0++Gains).

do_calc_skill_back(_SkillId,Lv,0,Gains) when Lv=<0->
    Gains;
do_calc_skill_back(_,Lv,1,Gains) when Lv=<1->
    Gains;
do_calc_skill_back(SkillId,Lv,IsSet,Gains)->
    case data_galaxy:get_galaxy_skill(SkillId,Lv) of
        #base_galaxy_skill{cost=Cost}->
            skip;
        _->
            Cost = []
    end,
    do_calc_skill_back(SkillId,Lv-1,IsSet,Gains++Cost).


%%整理外观表现需要格式
tidy_work_galaxy(AllGoods)->
    AllMGoods = filter_equips_pos_type(0,AllGoods,[]),
    tidy_work_galaxy(AllMGoods,AllGoods,[]).

tidy_work_galaxy([],_AllGoods,WorkGalaxys)->
    WorkGalaxys;
tidy_work_galaxy([H|T],AllGoods,WorkGalaxys)->
    #goods{cell=Pos,goods_id=GType}=H,
    OwnPosL = data_galaxy:get_own_pos(Pos),
    Minors  = tidy_minor_galaxy(OwnPosL,AllGoods,[]),
    tidy_work_galaxy(T,AllGoods,[{Pos,GType,Minors}|WorkGalaxys]).

tidy_minor_galaxy([],_AllGoods,Minors)->
    Minors;
tidy_minor_galaxy([H|T],AllGoods,Minors)->
    case lists:keyfind(H,#goods.cell,AllGoods) of
        #goods{goods_id=GType}->
            tidy_minor_galaxy(T,AllGoods,[{H,GType}|Minors]);
        _->
            tidy_minor_galaxy(T,AllGoods,Minors)
    end.

%%发送图鉴信息
send_galaxy_collect(Status)->
    #player_status{id=RoleID,role_galaxy=RoleGalaxy}=Status,
    #role_galaxy{collects=Collects}=RoleGalaxy,
    Datas = [{Type,SubT,Gains,State}||#galaxy_collect{key={Type,SubT},state=State,gains=Gains}<-Collects],
    {ok,Bin} = pt_148:write(14813,[Datas]),
    lib_server_send:send_to_uid(RoleID,Bin),
    ok.

%%图鉴领取
fetch_galaxy_colllect(Type,SubT,Status)->
    #player_status{id=RoleID,role_galaxy=RoleGalaxy}=Status,
    #role_galaxy{collects=Collects}=RoleGalaxy,
    case lists:keytake({Type,SubT},#galaxy_collect.key,Collects) of
        {value,Collect,RestList}->
            case Collect of
                #galaxy_collect{state=2}->
                    {false,?ERRCODE(err148_cant_fetch_again)};
                #galaxy_collect{state=0}->
                    {false,?ERRCODE(err148_need_finish_collect)};
                _->
                    case data_galaxy:get_galaxy_collect(Type,SubT) of
                        #base_galaxy_collect{awards=Awards}->
                            Produce = #produce{type=galaxy_collect,reward=Awards},
                            lib_goods_api:send_reward_with_mail(RoleID, Produce, ?MOD_GALAXY),
                            NCollect = Collect#galaxy_collect{state=2},
                            NCollects = [NCollect|RestList],
                            NRoleGalaxy = RoleGalaxy#role_galaxy{collects=NCollects},
                            lib_galaxy_db:save_role_collect(RoleID,NCollect),
                            update_collect_msg(RoleID,NCollect),
                            {ok,Status#player_status{role_galaxy=NRoleGalaxy}};
                        _->
                            {false,?ERRCODE(missing_config)}
                    end
            end;
        _->
            {false,?ERRCODE(err148_need_finish_collect)}
    end.


%%图鉴收集
collect_goods(Status,[])->
    Status;
collect_goods(Status,[{GType,_}|T])->
    NStatus = case data_galaxy:get_galaxy_goods(GType) of
        #base_galaxy{type=Type,subtype=SubT}->
            do_collect_goods(Status,Type,SubT,GType);
        _->
            Status
    end,
    collect_goods(NStatus,T).


do_collect_goods(Status,Type,SubT,GType)->
    #player_status{id=RoleID,role_galaxy=RoleGalaxy}=Status,
    #role_galaxy{
        collects = Collects
    } = RoleGalaxy,
    case data_galaxy:get_galaxy_collect(Type,SubT) of
        #base_galaxy_collect{items=NeedItems}->
            Len = length(NeedItems),
            case lists:keytake({Type,SubT},#galaxy_collect.key,Collects) of
                {value, SubCollect, RestList} -> %% 已有
                    #galaxy_collect{
                        gains = OGains,
                        state = CurS
                    }=SubCollect,
                    case CurS>=1 of
                        true->
                            Status;
                        _->
                            case {lists:member(GType,OGains),lists:member(GType,NeedItems)} of
                                {false,true}->
                                    Gains = [GType|OGains],
                                    S = case length(Gains)>=Len of
                                        true->
                                            1;
                                        _->
                                            0
                                    end,
                                    NCollect  = SubCollect#galaxy_collect{state=S,gains=Gains},
                                    NCollects = [NCollect|RestList],
                                    NRoleGalaxy = RoleGalaxy#role_galaxy{collects=NCollects},
                                    lib_galaxy_db:save_role_collect(RoleID,NCollect),
                                    update_collect_msg(RoleID,NCollect),
                                    Status#player_status{role_galaxy=NRoleGalaxy};
                                _->
                                    Status
                            end
                    end;
                _ ->
                    case lists:member(GType,NeedItems) of
                        true->
                            S = case 1>=Len of
                                true->
                                    1;
                                _->
                                    0
                            end,
                            NCollect  = #galaxy_collect{key={Type,SubT},state=S,gains=[GType]},
                            NCollects = [NCollect|Collects],
                            NRoleGalaxy = RoleGalaxy#role_galaxy{collects=NCollects},
                            lib_galaxy_db:save_role_collect(RoleID,NCollect),
                            update_collect_msg(RoleID,NCollect),
                            Status#player_status{role_galaxy=NRoleGalaxy};
                        _->
                            Status
                    end
            end;
        _->
            Status
    end.


%%更新推送
update_collect_msg(RoleID,Collect)->
    #galaxy_collect{
        key = {Type,SubT},
        state = CurS,
        gains =  Gains
    } = Collect,
    {ok,Bin} = pt_148:write(14814,[Type,SubT,Gains,CurS]),
    lib_server_send:send_to_uid(RoleID,Bin).

%%更新figure
update_galaxy_figure(Figure,RoleGalaxy)->
    #role_galaxy{
        work_galaxy = WorkGalaxys,
        display = Dis
    } = RoleGalaxy,
    Skin = format_galaxy_skin_info(RoleGalaxy),
    Figure#figure{
        galaxy_display  = Dis
        ,galaxy_pos_list = WorkGalaxys
        ,galaxy_skin = Skin
    }.


%%更新缓存role_show
update_role_show(RoleId,RoleGalaxy)->
    #role_galaxy{
        work_galaxy = WorkGalaxys,
        display = Dis,
        skin = Skin,
        skin_list = SkinList
    } = RoleGalaxy,
    MinRoleGalaxy = #role_galaxy{
        work_galaxy = WorkGalaxys,
        display = Dis,
        skin = Skin,
        skin_list = SkinList
    },
    lib_role:update_role_show(RoleId, [{role_galaxy,MinRoleGalaxy}]),
    MinRoleGalaxy.
