%%%-------------------------------------------------------------------
%%% @doc    孩子-点赞逻辑
%%% Module  : lib_child_vote_mod.erl
%%% Created : 2020-02-17
%%% @Author : tyl
%%%-------------------------------------------------------------------
-module(lib_child_vote_mod).

-include("common.hrl").
-include("server.hrl").
-include("figure.hrl").
-include("role.hrl").
-include("child.hrl").
-include("goods.hrl").
-include("errcode.hrl").
-include("def_module.hrl").
-include("predefine.hrl").

-export([
	make_list/1

	,show_off_child/2                   %% 晒娃
	,change_child_name/3                %% 修改孩子名字
	% ,login_refresh/4                  %% 登录刷新榜单
	,change_player_power/3              %% 玩家战力更新

	,get_child_be_voted_count/5         %% 查询孩子被点赞次数
	,send_vote_rank_list/2              %% 点赞排行榜信息
	,get_be_voted_log/1                 %% 被点赞记录
	,add_child_vote_count/2             %% 点赞其他孩子,刷新榜单数据
	% ,update_player_vote_rank_info/2   %% 刷新被点赞玩家数据
	,send_vote_rank_reward/1            %% 12点结算当天排行榜奖励

	,sort_rank_list/1                   %% 计算点赞排名
	,do_refresh_player_vote_log/1       %% 刷新玩家点赞&晒娃记录(玩家进程)
	,do_refresh_player_child_reward/2   %% 刷新玩家奖励数据(玩家进程)

	%% 获取跨服点赞数
	,get_child_be_voted_count_via_center/3
	,get_child_be_voted_count_from_node/3
	,send_child_be_voted_count_via_center/4
	,send_child_be_voted_count_from_node/4
	,send_child_be_voted_count/3
]).

%% API
%% 查询孩子被点赞次数(跨服和游戏服查询)
%% 获取数据 FromNode-请求数据来源节点
get_child_be_voted_count_via_center(RoleId, SRoleId, FromNode) ->
	clusters_node:apply_cast(
		?MODULE, get_child_be_voted_count_from_node, [RoleId, SRoleId, FromNode]
	),
	ok.

get_child_be_voted_count_from_node(RoleId, SRoleId, FromNode) ->
	ToNode = clusters_center:get_node_by_role_id(SRoleId),
	case FromNode =/= ToNode of
		true ->
			clusters_center:apply_cast(
				ToNode, mod_child_vote_mgr, get_child_be_voted_count, [RoleId, SRoleId, FromNode, ToNode]
			);
		_ ->
			ignore
	end,
	ok.

%% 发送数据
send_child_be_voted_count_via_center(FromNode, RoleId, SRoleId, Count) ->
	clusters_node:apply_cast(
		?MODULE, send_child_be_voted_count_from_node, [FromNode, RoleId, SRoleId, Count]
	),
	ok.

send_child_be_voted_count_from_node(FromNode, RoleId, SRoleId, Count) ->
	clusters_center:apply_cast(
		FromNode, ?MODULE, send_child_be_voted_count, [RoleId, SRoleId, Count]
	),
	ok.

send_child_be_voted_count(RoleId, SRoleId, Count) ->
	{ok, Bin} = pt_165:write(16511, [SRoleId, Count]),
	lib_server_send:send_to_uid(RoleId, Bin),
	ok.

get_child_be_voted_count(ChildVoteState, RoleId, SRoleId, FromNode, ToNode) ->
	case FromNode == ToNode of
		%% 游戏服
		true ->
			#child_vote_mgr_state{rank_list = RankList} = ChildVoteState,
			case lists:keyfind(SRoleId, #vote_rank.role_id, RankList) of
				#vote_rank{be_voted_count = BeVotedCount} ->
					{ok, Bin} = pt_165:write(16511, [SRoleId, BeVotedCount]),
					lib_server_send:send_to_uid(RoleId, Bin);
				_ ->
					{ok, Bin} = pt_165:write(16511, [SRoleId, 0]),
					lib_server_send:send_to_uid(RoleId, Bin)
			end;
		%% 跨服
		_ ->
			#child_vote_mgr_state{rank_list = RankList} = ChildVoteState,
			case lists:keyfind(SRoleId, #vote_rank.role_id, RankList) of
				#vote_rank{be_voted_count = BeVotedCount} ->ok;
				_ ->
					BeVotedCount = 0
			end,
			send_child_be_voted_count_via_center(FromNode, RoleId, SRoleId, BeVotedCount)
	end.

%% 点赞排行榜信息
send_vote_rank_list(ChildVoteState, RoleId) ->
	#child_vote_mgr_state{rank_list = RankList} = ChildVoteState,
	{TopRankList, _LeftList} = ulists:split(?VOTE_RANK_LENGTH, RankList),
	MyRank = case lists:keyfind(RoleId, #vote_rank.role_id, RankList) of
		         #vote_rank{} = TVoteRank ->
			         TVoteRank;
		         _ ->
			         []
	         end,
	MyPackList = case MyRank of
					 [] -> [];
					 _  -> pack_rank_list([MyRank], [])
	             end,
	TopPackList = pack_rank_list(TopRankList, []),
	{ok, Bin} = pt_165:write(16507, [MyPackList, TopPackList]),
	lib_server_send:send_to_uid(RoleId, Bin).

%% 被点赞记录
get_be_voted_log(Player) ->
	#player_status{sid = Sid, status_child = StatusChild} = Player,
	#status_child{be_voted_log = BeVotedLog} = StatusChild,
	PackList = pack_vote_log(BeVotedLog, []),
	{ok, Bin} = pt_165:write(16508, [PackList]),
	lib_server_send:send_to_sid(Sid, Bin).

%% 晒娃
show_off_child(Player, Channel) ->
	#player_status{sid = Sid, id = RoleId, status_child = StatusChild} = Player,
	#status_child{child_sex = ChildSex, show_off_times = HasShowOffTimes, last_show_off_time = LastShowOffTime} = StatusChild,
	#child_constant_cfg{constant = VoteTimeLimit} = data_child:get_child_kv_cfg(share_limit),
	NowTime = utime:unixtime(),
	CheckList = [{has_adopt, ChildSex}, {is_show_off_times_enough, HasShowOffTimes, VoteTimeLimit},
		{is_in_show_off_cd, NowTime, LastShowOffTime}],
	case lib_child_util:check_show_off(CheckList) of
		true ->
			%% 扣除晒娃次数
			NewShowOffTimes = HasShowOffTimes + 1,
			lib_child_util:update_db_child_show_off_times(RoleId, NewShowOffTimes, NowTime),
			lib_child_util:update_db_child_last_show_off_time(RoleId, NowTime),
			NewStatusChild = StatusChild#status_child{show_off_times = NewShowOffTimes, last_show_off_time = NowTime},
			lib_child:send_msg(Sid, 16509, [Channel, NewShowOffTimes]),
			show_off_child_trigger(RoleId, 1),
			lib_task_api:show_baby(Player),
			lib_achievement_api:child_show_event(Player, 1),
			NewPlayer = lib_child_util:save_dict_status_child(NewStatusChild, Player);
		{false, Res} ->
			lib_child:send_error(Sid, Res),
			NewPlayer = Player
	end,
	{ok, NewPlayer}.

%% 点赞其他孩子
add_child_vote_count(ChildVoteState, VoteInfo) ->
	#child_vote_mgr_state{rank_list = RankList} = ChildVoteState,
	[_RoleId, {BeVotedRoleId, ChildName}] = VoteInfo,
	case lists:keyfind(BeVotedRoleId, #vote_rank.role_id, RankList) of
		#vote_rank{be_voted_count = BeVotedCount} = VoteRank ->
			NewBeVotedCount = BeVotedCount + 1,
			NewVoteRank = VoteRank#vote_rank{be_voted_count = NewBeVotedCount},
			NewRankList = lists:keystore(BeVotedRoleId, #vote_rank.role_id, RankList, NewVoteRank),
			lib_child_util:update_db_be_voted_count(BeVotedRoleId, NewBeVotedCount);
		_ ->
			BeVotedCount = 1,
			case lib_role:get_role_show(BeVotedRoleId) of
				#ets_role_show{figure = Figure} ->
					#figure{power = RolePower} = Figure;
				_ ->
					RolePower = 0
			end,
			VoteRank = #vote_rank{
				role_id        = BeVotedRoleId,
				role_power     = RolePower,
				child_name     = ChildName,
				be_voted_count = BeVotedCount
			},
			NewRankList = lists:keystore(BeVotedRoleId, #vote_rank.role_id, RankList, VoteRank),
			lib_child_util:save_db_child_vote_rank(BeVotedRoleId, ChildName, BeVotedCount)
	end,
	%% 刷新榜单
	SortRankList = sort_rank_list(NewRankList),

%%	case length(SortRankList) > 20 of
%%		true ->
%%			{TopRankList, _LeftList} = lists:splitwith(
%%				fun(Rank) -> Rank#vote_rank.rank =< 20 end, SortRankList);
%%		_ ->
%%			TopRankList = SortRankList
%%	end,
	%% 刷新被点赞玩家数据
%%	VoteRank1 = lists:keyfind(BeVotedRoleId, #vote_rank.role_id, SortRankList),
%%	#vote_rank{be_voted_count = BeVotedCount1, rank = Rank1} = VoteRank1,
%%	lib_player:apply_cast(
%%		BeVotedRoleId, ?APPLY_CAST_SAVE, ?HAND_OFFLINE, ?MODULE, update_player_vote_rank_info, [[BeVotedCount1, Rank1]]
%%	),
%%	%% 存库
%%	Rank1 =< 20 andalso spawn(fun() -> batch_update_vote_rank(TopRankList) end),

	ChildVoteState#child_vote_mgr_state{rank_list = SortRankList}.

%% 发放排行榜奖励(调整到4点，每个人都有排行)
send_vote_rank_reward(ChildVoteState) ->
	#child_vote_mgr_state{
		rank_list = RankList
	} = ChildVoteState,
	case length(RankList) > ?VOTE_RANK_LENGTH of
		true ->
			{TopRankList, _LeftList} = lists:filter(
				fun(Rank) -> Rank#vote_rank.rank =< ?VOTE_RANK_LENGTH end, RankList);
		_ ->
			TopRankList = RankList
	end,
	%% 清空排行榜表
	lib_child_util:delete_db_child_vote_rank(),
	lib_child_util:delete_db_child_vote_log(),
	%% 清空奖励信息表
	lib_child_util:delete_db_child_reward(),
	lib_child_util:update_db_roles_vote_count(0, 0),
	%% 刷新内存数据
	RoleIds = lib_player:get_online_ids(),
	[begin
		refresh_player_vote_log(RoleId),
		refresh_player_child_reward(RoleId, TopRankList)
	end
		|| RoleId <- RoleIds],
	%% 先清理再存储
	F = fun(RankInfo) ->
		#vote_rank{role_id = RoleId, child_name = ChildName, rank = Rank, be_voted_count = Vote} = RankInfo,
		%% 存储最新排名
		lib_child_util:save_db_child_reward(RoleId, 0, Rank, 0),
		lib_log_api:log_child_rank(RoleId, ChildName, Rank, Vote)
	    end,
	spawn(fun() -> timer:sleep(500), lists:map(F, TopRankList) end),
	ChildVoteState#child_vote_mgr_state{
		rank_list    = [],
		refresh_time = utime:unixtime()
	}.

refresh_player_child_reward(RoleId, TopRankList) ->
	case lists:keyfind(RoleId, #vote_rank.role_id, TopRankList) of
		#vote_rank{rank = Rank} -> ok;
		_ -> Rank = 0
	end,
	lib_player:apply_cast(RoleId, ?APPLY_CAST_STATUS, ?MODULE, do_refresh_player_child_reward, [Rank]),
	ok.

do_refresh_player_child_reward(Player, Rank) ->
	#player_status{status_child = StatusChild} = Player,
	NewStatusChild = StatusChild#status_child{
		share_reward = 0
		,yest_rank   = Rank
		,yest_reward = 0
	},
	NewPlayer = lib_child_util:save_dict_status_child(NewStatusChild, Player),
	{ok, NewPlayer}.

refresh_player_vote_log(RoleId) ->
	lib_player:apply_cast(RoleId, ?APPLY_CAST_SAVE, ?MODULE, do_refresh_player_vote_log, []).

do_refresh_player_vote_log(Player) ->
	#player_status{id = RoleId, status_child = StatusChild} = Player,
	NewStatusChild = StatusChild#status_child{
		vote_times     = 0,
		show_off_times = 0,
		be_voted_log   = [],
		vote_role_list = []
	},
	%% 刷新数据库
	lib_child_util:update_db_vote_count(RoleId, 0, 0),
	lib_child_util:save_dict_status_child(NewStatusChild, Player).

%% 修改孩子名字
change_child_name(ChildVoteState, RoleId, ChildName) ->
	#child_vote_mgr_state{rank_list = VoteRankList} = ChildVoteState,
	case lists:keyfind(RoleId, #vote_rank.role_id, VoteRankList) of
		#vote_rank{child_name = OldChildName} = VoteRank ->
			case ChildName =/= OldChildName of
				true ->
					NewVoteRank = VoteRank#vote_rank{
						child_name = ChildName
					},
					%% 存库
					lib_child_util:update_db_child_vote_rank_child_name(RoleId, ChildName),
					NewVoteRankList = lists:keystore(
						RoleId, #vote_rank.role_id, VoteRankList, NewVoteRank),
					ChildVoteState#child_vote_mgr_state{rank_list = NewVoteRankList};
				_ ->
					ChildVoteState
			end;
		_ ->
			ChildVoteState
	end.

%% 玩家登录刷新排行榜
%%login_refresh(ChildVoteState, RoleInfo, BeVotedCount, ChildName) ->
%%	#child_vote_mgr_state{rank_list = VoteRankList} = ChildVoteState,
%%	[RoleId, RoleName, RolePower] = RoleInfo,
%%	case lists:keyfind(RoleId, #vote_rank.role_id, VoteRankList) of
%%		#vote_rank{} ->
%%			ChildVoteState;
%%		_ ->
%%			VoteInfo = #vote_rank{
%%				role_id        = RoleId,
%%				role_name      = RoleName,
%%				role_power     = RolePower,
%%				child_name     = ChildName,
%%				be_voted_count = BeVotedCount
%%			},
%%			NewVoteRankList = lists:keystore(RoleId, #vote_rank.role_id, VoteRankList, VoteInfo),
%%			SortRankList = sort_rank_list(NewVoteRankList),
%%			%% TODO:更新玩家(进程中)的排名
%%			case lists:keyfind(RoleId, #vote_rank.role_id, NewVoteRankList) of
%%				#vote_rank{rank = Rank} ->
%%					lib_player:apply_cast(
%%						RoleId, ?APPLY_CAST_SAVE, ?MODULE, update_player_vote_rank_info, [[BeVotedCount, Rank]]
%%					),
%%					case Rank =< 20 of %% 前20发生变动
%%						true ->
%%							case length(SortRankList) > 20 of
%%								true ->
%%									{TopRankList, _LeftList} = lists:split(20, SortRankList);
%%								_ ->
%%									TopRankList = SortRankList
%%							end,
%%							%% 存库
%%							spawn(fun() -> batch_update_vote_rank(TopRankList) end);
%%						_ -> skip
%%					end;
%%				_ -> skip
%%			end,
%%			ChildVoteState#child_vote_mgr_state{rank_list = SortRankList}
%%	end.

%% 玩家战力更新,刷新排行榜(只需要修改内存数据)
%% 是否重新排序判断：
%% (因战力是频繁更新操作,需要做一些条件限制)
%% 1.判断点赞数是否前Len(20)名,不是则不需要重新排序
%% 2.点赞数与第Len(20)名相同,战力比第20名大,重新排序
change_player_power(ChildVoteState, RoleId, RolePower) ->
	#child_vote_mgr_state{rank_list = VoteRankList} = ChildVoteState,
	case lists:keyfind(RoleId, #vote_rank.role_id, VoteRankList) of
		#vote_rank{role_power = _OldRolePower, rank = Rank, be_voted_count = MyCount} = VoteRank ->
			NewVoteRank = VoteRank#vote_rank{role_power = RolePower},
			NewVoteRankList = lists:keystore(RoleId, #vote_rank.role_id, VoteRankList, NewVoteRank),
			case lists:keyfind(?VOTE_RANK_LENGTH, #vote_rank.rank, VoteRankList) of
				#vote_rank{be_voted_count = OtherCount, role_power = OtherPower} -> skip;
				_ -> OtherCount = 0, OtherPower = 0
			end,
			case Rank =< ?VOTE_RANK_LENGTH orelse (MyCount == OtherCount andalso RolePower > OtherPower) of
				true ->
					SortRankList = sort_rank_list(NewVoteRankList);
				_ ->
					SortRankList = NewVoteRankList
			end,
			ChildVoteState#child_vote_mgr_state{rank_list = SortRankList};
		_ ->
			ChildVoteState
	end.

make_list(RankInfos) ->
	F = fun(RankInfo, TVoteRankList) ->
		[RoleId, ChildName, BeVotedCount] = RankInfo,
		case db:get_row(io_lib:format(<<"select last_combat_power from player_state where id = ~p">>,[RoleId])) of
			[Power] -> ok;
			_ -> Power = 0
		end,
		VoteRank = #vote_rank{
			role_id        = RoleId,
			role_power     = Power,
			child_name     = ChildName,
			be_voted_count = BeVotedCount
		},
		lists:keystore(RoleId, #vote_rank.role_id, TVoteRankList, VoteRank)
	end,
	lists:foldl(F, [], RankInfos).


%% -------------------------- builtin function ---------------------------------
pack_rank_list([], PackList) -> PackList;
pack_rank_list([RankInfo|L], TPackList) ->
	#vote_rank{
		rank           = Rank,
		role_id        = RoleId,
		role_power     = RolePower,
		child_name     = ChildName,
		be_voted_count = BeVoteCount
	} = RankInfo,
	TPackList1 =
		case lib_role:get_role_show(RoleId) of
			#ets_role_show{figure = Figure} ->
				#figure{} = Figure,
				[{Rank, Figure, ChildName, RolePower, BeVoteCount}|TPackList];
			_ ->
				[{Rank, #figure{}, ChildName, RolePower, BeVoteCount}|TPackList]
		end,
	pack_rank_list(L, TPackList1).

pack_vote_log([], PackList) -> PackList;
pack_vote_log([VoteLog|L], TPackList) ->
	#child_vote_log{
		vote_id          = VoteId,
		vote_name        = VoteName,
		time             = Time,
		feed_back_status = FeedBackStatus
	} = VoteLog,
	TPackList1 = [{VoteId, VoteName, Time, FeedBackStatus}|TPackList],
	pack_vote_log(L, TPackList1).

sort_rank_list(RankList) ->
	F = fun(RankA, RankB) ->
		#vote_rank{be_voted_count = VoteCountA, role_power = PowerA} = RankA,
		#vote_rank{be_voted_count = VoteCountB, role_power = PowerB} = RankB,
		if
			VoteCountA == VoteCountB ->
				case PowerA >= PowerB of
					true -> true;
					_    -> false
				end;
			VoteCountA > VoteCountB ->
				true;
			true ->
				false
		end
	end,
	SortList = lists:sort(F, RankList),
	F1 = fun(RankInfo, {TRankList, Rank}) ->
		% RoleId = RankInfo#vote_rank.role_id,
		NewRankInfo = RankInfo#vote_rank{rank = Rank},
		RankList1 = [NewRankInfo|TRankList],
		{RankList1, Rank + 1}
	end,
	{NewRankList, _} = lists:foldl(F1, {[], 1}, SortList),
	lists:reverse(NewRankList).
	% NewRankList.


show_off_child_trigger(RoleId, Count) ->
	contract_task_api:show_off_child_trigger(RoleId, Count).