%%%-------------------------------------------------------------------
%%% @doc    衣橱逻辑模块
%%% Module  : lib_wardrobe.erl
%%% Created : 2020-11-19
%%% @Author : tyl
%%% @end
%%%-------------------------------------------------------------------
-module(lib_wardrobe).

-include("wardrobe.hrl").
-include("def_module.hrl").
-include("def_goods.hrl").
-include("def_fun.hrl").
-include("common.hrl").
-include("server.hrl").
-include("figure.hrl").
-include("goods.hrl").
-include("designation.hrl").
-include("role_foster.hrl").
-include("profile_photo.hrl").
-include("fashion.hrl").
-include("rec_dress_up.hrl").
-include("predefine.hrl").
-include("errcode.hrl").
-include("def_event.hrl").
-include("rec_event.hrl").

%% API
-export([
	login/1
	,handle_event/2
	,send_wardrobe_info/1       %% 衣橱总览信息

	%% 数据库
	,db_save_wardrobe_value/4
	,db_select_wardrobe_value/1

	,send_msg/3
]).

%% -------------------------------------------------------------
%% @doc 衣橱总览信息 @end
%% -------------------------------------------------------------
send_wardrobe_info(#player_status{sid = Sid, wardrobe = StatusWardrobe} = Player) ->
	#status_wardrobe{
		stage = Stage
		,wardrobe_value = SumWardrobeValue
		,wardrobe_map   = WardrobeMap
	} = StatusWardrobe,
	AllType  = data_wardrobe:get_all_type(),
	PackInfo = pack_wardrobe_info(Player, AllType, WardrobeMap, []),
	send_msg(Sid, 42200, [Stage, SumWardrobeValue, PackInfo]),
	ok.

pack_wardrobe_info(_Player, [], _WardrobeMap, PackInfo) -> PackInfo;
pack_wardrobe_info(#player_status{figure = Figure} = Player, [Type|T], WardrobeMap, PackInfo) ->
	#figure{career = Career, lv = RoleLv} = Figure,
	case maps:get(Type, WardrobeMap, []) of
		#wardrobe_appearance{
			wardrobe_value = Value
			,collect       = Collect
			,collect_sum   = CollectSum
		} ->
			%% 时装,头像,装扮才需要重新计算总数(用运营时间控制)
			CollectSum1 = lib_wardrobe_active:cfg_collect_sum(Career, Type),
			SCollectSum = case lists:member(Type, [?WARDROBE_TYPE_FASHION, ?WARDROBE_TYPE_PICTURE, ?WARDROBE_TYPE_FRAME, ?WARDROBE_TYPE_BUBBLE]) of
				              true ->
					              NotOpenNum = calc_not_open_num(Player, Type, Career, RoleLv),
					              CollectSum1+NotOpenNum;
				              _ -> CollectSum
			              end,
			PackInfo1 = [{Type, Value, Collect, SCollectSum}|PackInfo];
		_ ->
			CollectSum = lib_wardrobe_active:cfg_collect_sum(Career, Type),
			PackInfo1 = [{Type, 0, 0, CollectSum}|PackInfo]
	end,
	pack_wardrobe_info(Player, T, WardrobeMap, PackInfo1).

calc_not_open_num(Player, Type, Career, RoleLv) ->
	#player_status{
		role_fashion = RoleFashion
		,dress_up = DressUp
		,profile_photo_info = ProfilePhoto
	} = Player,
	#role_fashion{all_fashions = AllFashions} = RoleFashion,
	#profile_photo_info{photo_list = PhotoList} = ProfilePhoto,
	#status_dress_up{enabled_map = EnableMap} = DressUp,
	case Type of
		?WARDROBE_TYPE_FASHION ->
			{_, _, FashionNotOpenNum} = lib_fashion:calc_active_fashions(AllFashions),
			FashionNotOpenNum;
		?WARDROBE_TYPE_PICTURE ->
			{_, PhotoNotOpenNum} = lib_player:calc_all_profile_photo(PhotoList, Career, transform:get_transform_id(Player)),
			PhotoNotOpenNum;
		?WARDROBE_TYPE_FRAME ->
			{_, DressNotOpenNum} = lib_dress_up:calc_all_dress_up(RoleLv, 2, EnableMap),
			DressNotOpenNum;
		?WARDROBE_TYPE_BUBBLE ->
			{_, DressNotOpenNum} = lib_dress_up:calc_all_dress_up(RoleLv, 1, EnableMap),
			DressNotOpenNum;
		_ ->
			0
	end.

%% -------------------------------------------------------------
%% 登录
login(Player) ->
	%% 1.称号上线需要重新计算，因为有离线激活
	%% 2.进阶系统初始为1阶
	%% 3.装扮、头像初始有默认激活
	%% 4.时装有开放时间控制
	%% 其他外观直接读取数据库数据
	#player_status{
		id = RoleId
		,dsgt_status = DsgtStatus
		,role_foster = RoleFoster
		,dress_up    = DressUp
		,profile_photo_info = ProfilePhotoInfo
		,role_fashion = RoleFashion
		,figure = Figure
	} = Player,
	#figure{career = Career, lv = RoleLv} = Figure,
	#dsgt_status{dsgt_map = DsgtMap} = DsgtStatus,
	#role_foster{fosters = Fosters} = RoleFoster,
	#profile_photo_info{photo_list = PhotoList} = ProfilePhotoInfo,
	#status_dress_up{enabled_map = EnableMap} = DressUp,
	#role_fashion{all_fashions = AllFashions} = RoleFashion,
	%% 统计所以称号
	DsgtKeyValues = lib_designation:calc_all_dsgt(DsgtMap),
	WardrobeMap = calc_dsgt(Career, #{}, DsgtKeyValues),
	%% 统计所有进阶
	{_, FosterKeyValues1} = lib_role_foster:calc_all_foster(1, Fosters), %% 进阶
	{_, FosterKeyValues2} = lib_role_foster:calc_all_foster(5, Fosters), %% 伙伴
	WardrobeMap1 = calc_foster(Career, WardrobeMap, ?WARDROBE_TYPE_FOSTER, FosterKeyValues1),
	WardrobeMap2 = calc_foster(Career, WardrobeMap1, ?WARDROBE_TYPE_PARTNER, FosterKeyValues2),
	%% 统计所有装扮
	AllDressType = data_dress_up:get_all_dress_type(),
	F = fun(DressType, TWardrobeMap) ->
		{TDressKeyValues, TDressNotOpenNum} = lib_dress_up:calc_all_dress_up(RoleLv, DressType, EnableMap),
		TWardrobeMap1   = calc_dress_up(Career, TWardrobeMap, DressType, TDressKeyValues, TDressNotOpenNum),
		TWardrobeMap1
	end,
	WardrobeMap3 = lists:foldl(F, WardrobeMap2, AllDressType),
	%% 统计所有头像(包括默认激活的职业头像)
	{PhotoKeyValues, PhotoNotOpenNum} = lib_player:calc_all_profile_photo(PhotoList, Career, transform:get_transform_id(Player)),
	WardrobeMap4   = calc_photo(Career, WardrobeMap3, PhotoKeyValues, PhotoNotOpenNum),
	%% 统计所有时装
	{FashionKeyValues, _, FashionNotOpenNum} = lib_fashion:calc_active_fashions(AllFashions),
	WardrobeMap5 = calc_fashion(Career, WardrobeMap4, FashionKeyValues, FashionNotOpenNum),
	%% 其他类型的外观读取数据库
	AllType = ?ALL_WARDROBE_TYPE -- [?WARDROBE_TYPE_FASHION, ?WARDROBE_TYPE_DESG, ?WARDROBE_TYPE_FOSTER,
		?WARDROBE_TYPE_PARTNER, ?WARDROBE_TYPE_FRAME, ?WARDROBE_TYPE_BUBBLE, ?WARDROBE_TYPE_PICTURE],
	case db_select_wardrobe_value(RoleId) of
		[_|_] = DbInfo -> ok;
		_ -> DbInfo = []
	end,
	NewWardrobeMap = calc_other_appearance(Career, AllType, DbInfo, WardrobeMap5),
	SumValue = lib_wardrobe_active:calc_sum_wardrobe_value(NewWardrobeMap),
	Stage = lib_wardrobe_active:calc_wardrobe_stage(SumValue),
	Wardrobe = #status_wardrobe{
		wardrobe_value = SumValue
		,stage         = Stage
		,wardrobe_map  = NewWardrobeMap
	},
	NewPlayer = Player#player_status{
		wardrobe = Wardrobe
	},
	NewPlayer.

%% ---------------------------------------------------------------------------
%% @doc 切换场景之后需要统计衣橱值，因为有一些外观的初始值 @end
%% ---------------------------------------------------------------------------
handle_event(Player, #event_callback{type_id = ?EVENT_CLIENT_LOGIN_SUCCESS}) ->
	#player_status{wardrobe = Wardrobe} = Player,
	#status_wardrobe{wardrobe_value = SumValue} = Wardrobe,
	lib_achievement_api:wardrobe_value_event(Player, SumValue),
	{ok, Player};
handle_event(Player, _) ->
	{ok, Player}.

%% ---------------------------------------------------------------------------
%% @doc 各外观统计逻辑 @end
%% ---------------------------------------------------------------------------
calc_dsgt(Career, WardrobeMap, KeyValues) ->
	Type = ?WARDROBE_TYPE_DESG,
	SumAppearanceValue = lib_wardrobe_active:calc_appearance_value(Type, KeyValues, 0),
	F = fun({{_SubType, _Color}, Num}, Sum) ->
			Sum + Num
	    end,
	Collect = lists:foldl(F, 0, KeyValues),
	CfgCollectSum = lib_wardrobe_active:cfg_collect_sum(Career, Type),
	WardrobeAppear = #wardrobe_appearance{
		type = Type
		,wardrobe_value = SumAppearanceValue
		,collect        = Collect
		,collect_sum    = CfgCollectSum
	},
	maps:put(Type, WardrobeAppear, WardrobeMap).

calc_foster(Career, WardrobeMap, Type, KeyValues) ->
	SumAppearanceValue = lib_wardrobe_active:calc_appearance_value(Type, KeyValues, 0),
	F = fun({{_SubType, Color}, Num}, Sum) ->
		case Type == ?WARDROBE_TYPE_FOSTER of
			true -> Sum + Color;
			_ -> Sum + Num
		end end,
	Collect = lists:foldl(F, 0, KeyValues),
	CfgCollectSum = lib_wardrobe_active:cfg_collect_sum(Career, Type),
	WardrobeAppear = #wardrobe_appearance{
		type = Type
		,wardrobe_value = SumAppearanceValue
		,collect        = Collect
		,collect_sum    = CfgCollectSum
	},
	maps:put(Type, WardrobeAppear, WardrobeMap).

calc_dress_up(Career, WardrobeMap, DressType, KeyValues, NotOpenNum) ->
	case DressType of
		?DRESS_UP_FRAME -> Type = ?WARDROBE_TYPE_FRAME;
		_ -> Type = ?WARDROBE_TYPE_BUBBLE
	end,
	SumAppearanceValue = lib_wardrobe_active:calc_appearance_value(Type, KeyValues, 0),
	F = fun({{_SubType, _Color}, Num}, Sum) ->
		Sum + Num
	    end,
	Collect = lists:foldl(F, 0, KeyValues),
	CfgCollectSum = lib_wardrobe_active:cfg_collect_sum(Career, Type),
	WardrobeAppear = #wardrobe_appearance{
		type = Type
		,wardrobe_value = SumAppearanceValue
		,collect        = Collect
		,collect_sum    = CfgCollectSum + NotOpenNum
	},
	maps:put(Type, WardrobeAppear, WardrobeMap).

calc_photo(Career, WardrobeMap, KeyValues, NotOpenNum) ->
	Type = ?WARDROBE_TYPE_PICTURE,
	SumAppearanceValue = lib_wardrobe_active:calc_appearance_value(Type, KeyValues, 0),
	F = fun({{_SubType, _Color}, Num}, Sum) ->
		Sum + Num
	    end,
	Collect = lists:foldl(F, 0, KeyValues),
	CfgCollectSum = lib_wardrobe_active:cfg_collect_sum(Career, Type),
	WardrobeAppear = #wardrobe_appearance{
		type = Type
		,wardrobe_value = SumAppearanceValue
		,collect        = Collect
		,collect_sum    = CfgCollectSum + NotOpenNum
	},
	maps:put(Type, WardrobeAppear, WardrobeMap).

calc_fashion(Career, WardrobeMap, KeyValues, NotOpenNum) ->
	Type = ?WARDROBE_TYPE_FASHION,
	SumAppearanceValue = lib_wardrobe_active:calc_appearance_value(Type, KeyValues, 0),
	F = fun({{_SubType, _Color}, Num}, Sum) ->
		Sum + Num
	    end,
	Collect = lists:foldl(F, 0, KeyValues),
	CfgCollectSum = lib_wardrobe_active:cfg_collect_sum(Career, Type),
	WardrobeAppear = #wardrobe_appearance{
		type = Type
		,wardrobe_value = SumAppearanceValue
		,collect        = Collect
		,collect_sum    = CfgCollectSum + NotOpenNum
	},
	maps:put(Type, WardrobeAppear, WardrobeMap).

calc_other_appearance(_Career, _AllType, [], WardrobeMap) -> WardrobeMap;
calc_other_appearance(Career, AllType, [[Type, Collect, Value]|L], WardrobeMap) ->
	case lists:member(Type, AllType) of
		true ->
			CfgCollectSum  = lib_wardrobe_active:cfg_collect_sum(Career, Type),
			WardrobeAppear = #wardrobe_appearance{
				type = Type
				,wardrobe_value = Value
				,collect        = Collect
				,collect_sum    = CfgCollectSum
			},
			WardrobeMap1 = maps:put(Type, WardrobeAppear, WardrobeMap),
			calc_other_appearance(Career, AllType, L, WardrobeMap1);
		_ ->
			calc_other_appearance(Career, AllType, L, WardrobeMap)
	end.

%% 发送消息
send_msg(Sid, Cmd, Msg) ->
	{ok, Bin} = pt_422:write(Cmd, Msg),
	lib_server_send:send_to_sid(Sid, Bin).

%% ----------------------------- 数据库操作 --------------------------------
db_save_wardrobe_value(RoleId, Type, Collect, Value) ->
	Sql = io_lib:format(?SQL_INSERT_WARDROBE_VALUE, [RoleId, Type, Collect, Value]),
	db:execute(Sql).

db_select_wardrobe_value(RoleId) ->
	Sql = io_lib:format(?SQL_SELECT_WARDROBE_VALUE, [RoleId]),
	db:get_all(Sql).