%% ---------------------------------------------------------
%% Author:  zmh
%% Created: 20-06-22
%% Description: 玩家进阶珍宝
%% --------------------------------------------------------
-module(lib_role_foster_skin).
-compile(export_all).
-include("server.hrl").
-include("role_foster.hrl").
-include("predefine.hrl").
-include("skill.hrl").
-include("figure.hrl").
-include("errcode.hrl").
-include("rec_event.hrl").
-include("def_event.hrl").
-include("def_goods.hrl").
-include("def_module.hrl").
-include("goods.hrl").
-include("common.hrl").
-include("attr.hrl").


-export([
	login/1,          %%登录加载
	check/1,
	db_load/2,
	calc_power/3,
	get_foster_skin_attr/1,
	change_display/5,
	gm/1
]).



gm(Status)->
	#player_status{id=RoleID,role_foster_skin=RoleSkin}=Status,
    #role_foster_skin{fosters=Fosters} = RoleSkin,
    Types = data_foster:get_skin_types(),
    NFosters = gm_active(RoleID,Types,Fosters),
    NRoleSkin = RoleSkin#role_foster_skin{fosters=NFosters},
    NStatus = Status#player_status{role_foster_skin=NRoleSkin},
    NStatus.

gm_active(_RoleID,[],Fosters)->
	Fosters;
gm_active(RoleID,[H|T],Fosters)->
	CellSkin = case lists:keyfind(H,#cell_foster_skin.type,Fosters) of
        CValue when is_record(CValue,cell_foster_skin)->
            CValue;
        _->
            #cell_foster_skin{}
    end,
	Max = data_foster:get_skin_max(H),
	IdList = lists:seq(1,Max),
	Cells = [begin
		CellS = #cell_skin{id=Id,star=1},
		save_role_foster_skin(RoleID,H,CellS),
		CellS
	end || Id<-IdList],
    NewCellSkin = CellSkin#cell_foster_skin{skins=Cells},
    NFosters = lists:keystore(H,#cell_foster_skin.type,Fosters,NewCellSkin),
	gm_active(RoleID,T,NFosters).


%%离线加载
db_load(RoleID,Figure)->
	Sql = io_lib:format(?SQL_PLAYER_FOSTER_SKIN_GET, [RoleID]),
	Types = data_foster:get_skin_types(),
	Fosters = case db:get_all(Sql) of
        Fosters0 when is_list(Fosters0)  ->
            make_foster_skin(RoleID,Types,Fosters0,[]);
        _ ->
        	[]
    end,
    Shows   = get_foster_skin_figure(#player_status{role_foster_skin=#role_foster_skin{fosters=Fosters}}),
    NFigure = Figure#figure{foster_skin=Shows},
    NFigure.


login(Status)->
	#player_status{figure=Figure,id=RoleID}=Status,
	Sql = io_lib:format(?SQL_PLAYER_FOSTER_SKIN_GET, [RoleID]),
	Types = data_foster:get_skin_types(),
	Fosters = case db:get_all(Sql) of
        Fosters0 when is_list(Fosters0)  ->
            make_foster_skin(RoleID,Types,Fosters0,[]);
        _ ->
        	[]
    end,
    Status0 = Status#player_status{role_foster_skin=#role_foster_skin{fosters=Fosters}},
    Shows   = get_foster_skin_figure(Status0),
    NFigure = Figure#figure{foster_skin=Shows},
    % NFigure = update_lv_model(NFigure0),
    NStatus = count_foster_skin_attr(Status0),
    NStatus#player_status{figure=NFigure}.

%%数据拼接
make_foster_skin(_,[],_Loads,CellFosters)->
	CellFosters;
make_foster_skin(RoleID,[H|T],Loads,CellFosters)->
	Skins = [#cell_skin{id=ID,star=Star,display=DisStar}||[Type,ID,Star,DisStar]<-Loads,Type==H],
	Skills = merge_skills(H,Skins,[]),
	Dis   = filter_display(Skins,{0,0}),
	NFoster = #cell_foster_skin{
		type = H,
		skins = Skins,
		skills = Skills,
		display = Dis
	},
	make_foster_skin(RoleID,T,Loads,[NFoster|CellFosters]).

filter_display([],Dis)->
	Dis;
filter_display([#cell_skin{id=Id,display=D}|T],Dis)->
	case D>0 of
		true->
			{Id,D};
		_->
			filter_display(T,Dis)
	end.

merge_skills(_Type,[],Skills)->
	Skills;
merge_skills(Type,[#cell_skin{id=Id,star=Star}|T],Skills)->
	NSkills = case data_foster:get_foster_skin(Type,Id,Star) of
		#base_foster_skin{skills=Skills0}->
			Skills0++Skills;
		_->
			Skills
	end,
	merge_skills(Type,T,NSkills).

get_foster_skin_figure(Status)->
    #player_status{role_foster_skin=RoleSkin}=Status,
    #role_foster_skin{fosters = Fosters}=RoleSkin,
    Shows = [{Type,Display}||#cell_foster_skin{type=Type,display=Display}<-Fosters],
    Shows.

get_sub_foster_skin_figure(Status)->
	#player_status{role_foster = Fosters} = Status,
	#role_foster{fosters = CellFosters} = Fosters,
	F = fun(CellFoster, TList) ->
		case CellFoster of
			#cell_foster{type = Type, display_skin = Display} ->
				case Type > 4 of
					true ->
						case Display of
							{_, DisPlayStar} when DisPlayStar > 0 ->
								[{Type, Display}|TList];
							_ ->
								TList
						end;
					_ ->
						TList
				end;
			_ -> TList
		end end,
	Shows = lists:foldl(F, [], CellFosters),
	Shows.

%%激活外观
active_foster_skin(Type,Id,Status)->
	#player_status{id=RoleID,role_foster_skin=RoleSkin}=Status,
    #role_foster_skin{fosters=Fosters} = RoleSkin,
    CheckList = [
        {check_skin_exist,Type,Id},
        {check_skin_already,Type,Id,Fosters}
    ],
    case util:check_lists(?MODULE,CheckList) of
        {ok,[CellSkin,NFosters]}->
        	#base_foster_skin{cost=Cost} = data_foster:get_foster_skin(Type,Id,0),
        	 case lib_goods_api:cost_object_list_with_check(Status, Cost, role_foster_skin, ["used foster skin active"]) of
                {true,Status0,_}->
                    NRoleSkin = RoleSkin#role_foster_skin{fosters=NFosters},
                    NStatus0  = Status0#player_status{role_foster_skin=NRoleSkin},
                    NStatus1  = count_foster_skin_attr(NStatus0),
                    NStatus  = lib_player:count_player_attribute(NStatus1),
                    lib_player:send_attribute_change_notify(NStatus, ?NOTIFY_ATTR),
                    mod_scene_agent:update(NStatus, [{battle_attr, NStatus#player_status.battle_attr}]),
                    save_role_foster_skin(RoleID,Type,CellSkin),
	                case Cost of
		                [{_, GoodsId, CostNum}|_] -> ok;
						_ -> GoodsId = 0, CostNum = 0
	                end,
	                AllColorList = calc_all_foster_skin(NFosters),
	                {ok, NStatus2} = lib_wardrobe_active:active_foster_skin(NStatus, AllColorList, GoodsId),
	                handle_active_achievement(NStatus2, AllColorList),
	                handle_star_achievement(NStatus2, NFosters),
	                ta_agent_fire:treasure_up(NStatus, [lib_role_foster:get_type_name(Type), Id, 0, 1, GoodsId, CostNum]),
	                {ok,?SUCCESS,Cost,NStatus2};
                {false,Err,_}->
                    {false,Err}
            end;
        {false,Err}->
        	{false,Err}
    end.

%% 统计所有进阶外观
calc_all_foster_skin(Fosters) ->
	F = fun(#cell_foster_skin{type = SkinType, skins = Skins}, CalcList) ->
			F1 = fun(#cell_skin{id = SkinId}, TList) ->
					case data_foster:get_foster_skin(SkinType, SkinId, 0) of
						#base_foster_skin{cost = [{_, GoodsId, _}|_]} ->
							case data_goods_type:get(GoodsId) of
								#ets_goods_type{color = Color} ->
									case lists:keyfind({SkinType, Color}, 1, TList) of
										{_, Num} -> lists:keystore({SkinType, Color}, 1, TList, {{SkinType, Color}, Num + 1});
										_ -> lists:keystore({SkinType, Color}, 1, TList, {{SkinType, Color}, 1})
									end;
								_ -> TList
							end;
						_ -> TList
					end end,
			lists:foldl(F1, CalcList, Skins)
	end,
	ColorList = lists:foldl(F, [], Fosters),
	ColorList.

%% 成就
handle_active_achievement(Player, ColorList) ->
	F = fun({_, Num}, TSumNum) ->
			Num + TSumNum;
		(_, TSumNum) -> TSumNum
	    end,
	SumNum = lists:foldl(F, 0, ColorList),
	lib_achievement_api:active_foster_skin_event(Player, SumNum),
	ok.

handle_star_achievement(Player, FostersSkins) ->
	F = fun(#cell_foster_skin{skins = Skins}, TSumStar) ->
		F1 = fun(#cell_skin{star = Star}, TSumStar1) ->
			Star + TSumStar1
		end,
		lists:foldl(F1, TSumStar, Skins)
	    end,
	SumStar = lists:foldl(F, 0, FostersSkins),
	lib_achievement_api:foster_skin_event(Player, SumStar),
	ok.

%%升级外观
upgrade_foster_skin(Type,Id,Status)->
	#player_status{id=RoleID,role_foster_skin=RoleSkin}=Status,
    #role_foster_skin{fosters=Fosters} = RoleSkin,
    CheckList = [
        {check_skin_upgrade,Type,Id,Fosters}
    ],
    case util:check_lists(?MODULE,CheckList) of
        {ok,[CurStar,CurDis,CellSkin,NFosters]}->
        	#base_foster_skin{cost=Cost, next_star = NextStar} = data_foster:get_foster_skin(Type,Id,CurStar),
        	case lib_goods_api:cost_object_list_with_check(Status, Cost, role_foster_skin, ["used foster skin upgrade"]) of
                {true,Status0,_}->
                    NRoleSkin = RoleSkin#role_foster_skin{fosters=NFosters},
                    NStatus0  = Status0#player_status{role_foster_skin=NRoleSkin},
                    NStatus1  = count_foster_skin_attr(NStatus0),
                    NStatus  = lib_player:count_player_attribute(NStatus1),
                    lib_player:send_attribute_change_notify(NStatus, ?NOTIFY_ATTR),
                    mod_scene_agent:update(NStatus, [{battle_attr, NStatus#player_status.battle_attr}]),
                    save_role_foster_skin(RoleID,Type,CellSkin),
	                handle_star_achievement(NStatus, NFosters),
	                case Cost of
						[{_, CostGood, CostNum}|_] -> ok;
						_ -> CostGood = 0, CostNum = 0
	                end,
	                ta_agent_fire:treasure_up(NStatus, [lib_role_foster:get_type_name(Type), Id, CurStar, NextStar, CostGood, CostNum]),
                    {ok,?SUCCESS,CurDis,CurStar,Cost,CellSkin#cell_skin.star,NStatus};
                {false,Err,_}->
                    {false,Err}
            end;
        {false,Err}->
        	{false,Err}
    end.


save_role_foster_skin(RoleID,Type,CellSkin)->
	#cell_skin{
		id = Id,
		star = Star,
		display = Display
	} = CellSkin,
	Sql = io_lib:format(?SQL_UPDATE_FOSTER_SKIN, [RoleID,Type,Id,Star,Display]),
    db:execute(Sql).


check({check_skin_upgrade,Type,Id,Fosters})->
	case lists:keyfind(Type,#cell_foster_skin.type,Fosters) of
        CValue when is_record(CValue,cell_foster_skin)->
            #cell_foster_skin{
		        skins = Skins,
		        display = {CSkin,CStar}
		    }=CValue,
		    case lists:keyfind(Id,#cell_skin.id,Skins) of
		    	 Cell when is_record(Cell,cell_skin)->
		    	 	#cell_skin{star=CurStar}=Cell,
		    	 	#base_foster_skin{next_star=NStar}=data_foster:get_foster_skin(Type,Id,CurStar),
		    	 	case NStar>0 of
		    	 		true->
		    	 			ShowStar = case CSkin=:=Id of
		    	 				true->
		    	 					NStar;
		    	 				_->
		    	 					0
		    	 			end,
		    	 			NCell = Cell#cell_skin{id=Id,star=NStar,display=ShowStar},
		    				NSkins = lists:keystore(Id,#cell_skin.id,Skins,NCell),
		    				NewCellSkin = CValue#cell_foster_skin{skins=NSkins},
		    				NFosters = lists:keystore(Type,#cell_foster_skin.type,Fosters,NewCellSkin),
		    				{ok,[CurStar,{CSkin,CStar},NCell,NFosters]};
		    			_->
		    				{false,?ERRCODE(err146_already_max_star)}
		    		end;
		    	 _->
		    	 	{false,?ERRCODE(err146_need_active_skin)}
		    end;
        _->
            {false,?ERRCODE(err146_need_active_skin)}
    end;
check({check_skin_already,Type,Id,Fosters})->
	CellSkin = case lists:keyfind(Type,#cell_foster_skin.type,Fosters) of
        CValue when is_record(CValue,cell_foster_skin)->
            CValue;
        _->
            #cell_foster_skin{}
    end,
    #cell_foster_skin{
        skins = Skins
    }=CellSkin,
    case lists:keyfind(Id,#cell_skin.id,Skins) of
    	#cell_skin{}->
    		{false,?ERRCODE(err146_foster_skin_already_active)};
    	_->
    		Cell = #cell_skin{id=Id,star=1},
    		NSkins = lists:keystore(Id,#cell_skin.id,Skins,Cell),
    		NewCellSkin = CellSkin#cell_foster_skin{skins=NSkins},
    		NFosters = lists:keystore(Type,#cell_foster_skin.type,Fosters,NewCellSkin),
    		{ok,[Cell,NFosters]}
   	end;
check({check_skin_exist,Type,Id})->
	Max = data_foster:get_skin_max(Type),
	case Id=<Max andalso Max>0 of
		true->
			true;
		_->
			{false,?ERRCODE(missing_config)}
	end.



%%属性汇总
count_foster_skin_attr(Status)->
	#player_status{role_foster_skin=RoleSkin}=Status,
	#role_foster_skin{fosters=Fosters}=RoleSkin,
	[Attrs,NFosters] = count_cell_foster_skins_attr(Fosters),
	NRoleSkin = RoleSkin#role_foster_skin{attr=Attrs,fosters=NFosters},
	Status#player_status{role_foster_skin=NRoleSkin}.

count_cell_foster_skins_attr(Fosters)->
	count_cell_foster_skins_attr(Fosters,[],[]).

count_cell_foster_skins_attr([],Fosters,Attrs)->
	[util:combine_list(Attrs),Fosters];
count_cell_foster_skins_attr([H|T],Fosters,Attrs)->
	[CellAttrs,NewH] = count_cell_skin_attr(H),
	count_cell_foster_skins_attr(T,[NewH|Fosters],CellAttrs++Attrs).

count_cell_skin_attr(CellFoster)->
	#cell_foster_skin{
		type = Type,
		skins = Skins
	} = CellFoster,
	[Skills,Attrs0] = do_count_cell_skin(Type,Skins,[],[]),
	SkillAttr = calc_skill_attr(Skills,[]),
	Attrs1 = util:combine_list(SkillAttr++Attrs0),
	Attrs  = lib_player_attr:partial_attr_convert(Attrs1),
	NCellFoster = CellFoster#cell_foster_skin{attrs=Attrs,skills=Skills},
	[Attrs,NCellFoster].

do_count_cell_skin(_,[],Skills,Attrs)->
	[Skills,Attrs];
do_count_cell_skin(Type,[H|T],Skills,Attrs)->
	#cell_skin{
		id = Id,
		star = Star
	}=H,
	case data_foster:get_foster_skin(Type,Id,Star) of
		#base_foster_skin{attrs=Attrs0,skills=Skills0}->
			do_count_cell_skin(Type,T,Skills++Skills0,Attrs++Attrs0);
		_->
			do_count_cell_skin(Type,T,Skills,Attrs)
	end.

calc_skill_attr([],Attrs)->
	util:combine_list(Attrs);
calc_skill_attr([{SkillID,Lv}|Skills],Attrs)->
	case data_skill:get(SkillID,Lv) of
		#skill{lv_data=#skill_lv{base_attr=BAttr0}}->
			BAttr = [{T,V}||{K,T,V}<-BAttr0,K==0],
			calc_skill_attr(Skills,BAttr++Attrs);
		_->
			calc_skill_attr(Skills,Attrs)
	end.


calc_power(Status, AttrPower, BaseAttr) ->
	#player_status{role_foster_skin=RoleSkin}=Status,
	#role_foster_skin{fosters=Fosters}=RoleSkin,
	[NStatus,NFosters,_NeedUpdate,SkillPower|_] = calc_foster_skin_power(Status,AttrPower, BaseAttr, Fosters, [], [],0),
	NRoleSkin = RoleSkin#role_foster_skin{fosters=NFosters},
	NStatus1 = NStatus#player_status{role_foster_skin=NRoleSkin},
	{NStatus1, SkillPower}.

calc_foster_skin_power(Status, _AttrPower, _BaseAttr, [], Fosters, NeedUpdate,SkillPower)->
	[Status,Fosters, NeedUpdate,SkillPower];
calc_foster_skin_power(Status, AttrPower, BaseAttr, [CellFoster|T], Fosters, _NeedUpdate,SkillPower)->
	#cell_foster_skin{
		type = _Type,
		attrs = TotalAttr,
		skills = Skills
	}=CellFoster,
    RoleLv = Status#player_status.figure#figure.lv,
	{_,SPower}  = lib_skill_attr:get_passive_skill_attr_and_power(Skills, RoleLv),
	% SkillAttr   = calc_skill_attr(Skills,[]),
	% TotalAttr   = util:combine_list(SkillAttr++Attrs),
	PartialAttr = attr_conv:to_attr_record(TotalAttr),
	Power = lib_player_attr:calc_attr_power_partial(AttrPower, BaseAttr, PartialAttr),
	NewPower = Power+SPower,
	NCellFoster = CellFoster#cell_foster_skin{combat=NewPower},
	calc_foster_skin_power(Status,AttrPower,BaseAttr,T,[NCellFoster|Fosters],_NeedUpdate,SkillPower+SPower).


get_foster_skin_attr(Status)->
	#player_status{
		role_foster_skin=RoleSkin
	}=Status,
	case RoleSkin of
		#role_foster_skin{attr=Attrs}->
			Attrs;
		_->
			Attrs = []
	end,
	Attrs.


change_display(RoleID,Type,0,_Star,Fosters)->
	case lists:keyfind(Type,#cell_foster_skin.type,Fosters) of
        CValue when is_record(CValue,cell_foster_skin)->
             #cell_foster_skin{
		        skins = Skins
		    }=CValue,
		    {IsUpdate,NSkins} = update_skins(RoleID,Type,Skins,0,0,[],false),
		    {ok,IsUpdate,CValue#cell_foster_skin{skins=NSkins,display={0,0}}};
        _->
            {false,?ERRCODE(err146_need_active_skin)}
    end;
change_display(RoleID,Type,SkinID,Star,Fosters)->
	case lists:keyfind(Type,#cell_foster_skin.type,Fosters) of
        CValue when is_record(CValue,cell_foster_skin)->
             #cell_foster_skin{
		        skins = Skins
		    }=CValue,
		    case lists:keyfind(SkinID,#cell_skin.id,Skins) of
		    	#cell_skin{star=CurStar}->
		    		MinStar = min(Star,CurStar),
		    		{IsUpdate,NSkins} = update_skins(RoleID,Type,Skins,SkinID,MinStar,[],false),
		    		{ok,IsUpdate,CValue#cell_foster_skin{skins=NSkins,display={SkinID,MinStar}}};
		    	_->
		    		{false,?ERRCODE(err146_need_active_skin)}
		    end;
        _->
            {false,?ERRCODE(err146_need_active_skin)}
    end.

update_skins(_,_,[],_,_,Skins,IsUpdate)->
	{IsUpdate,Skins};
update_skins(RoleID,Type,[H|T],0,_,Skins,IsUpdate)->
	case H#cell_skin.display>0 of
		true ->
			NewH = H#cell_skin{display=0},
			save_role_foster_skin(RoleID,Type,NewH),
			update_skins(RoleID,Type,T,0,0,[NewH|Skins],true);
		_->
			update_skins(RoleID,Type,T,0,0,[H|Skins],IsUpdate)
	end;
update_skins(RoleID,Type,[H|T],SkinID,Star,Skins,IsUpdate)->
	case H#cell_skin.id =:= SkinID of
		true when H#cell_skin.display /= Star->
			NewH = H#cell_skin{display=Star},
			save_role_foster_skin(RoleID,Type,NewH),
			update_skins(RoleID,Type,T,SkinID,Star,[NewH|Skins],true);
		false when H#cell_skin.display>=0->
			NewH = H#cell_skin{display=0},
			save_role_foster_skin(RoleID,Type,NewH),
			update_skins(RoleID,Type,T,SkinID,Star,[NewH|Skins],true);
		_->
			update_skins(RoleID,Type,T,SkinID,Star,[H|Skins],IsUpdate)
	end.

%% 是否激活了AI娘珍宝
is_active_ai_skin(Player, Id) ->
	is_active(Player, ?FJARVIS, Id).

%% 是否激活了某件珍宝
is_active(Player, Type, Id) ->
	#player_status{
		role_foster_skin=RoleSkin
	}=Player,
	#role_foster_skin{fosters = Fosters} = RoleSkin,
	case lists:keyfind(Type, #cell_foster_skin.type, Fosters) of
		#cell_foster_skin{skins = Skins} ->
			lists:keymember(Id, #cell_skin.id, Skins);
		_ ->
			false
	end.