%%%-------------------------------------------------------------------
%%% @doc    宠物-API接口
%%% Module  : lib_pet.erl
%%% Created : 2019-12-09
%%% @Author : tyl
%%%-------------------------------------------------------------------
-module(lib_pet_api).

-include("common.hrl").
-include("server.hrl").
-include("pet.hrl").
-include("figure.hrl").
-include("predefine.hrl").
-include("rec_event.hrl").
-include("def_event.hrl").
-include("def_module.hrl").
-include("skill.hrl").
-include("errcode.hrl").
-include("scene.hrl").

-export([
	login/1                                     %% 登录逻辑
	,db_get_follow_pet/1                        %% role_show获取跟随的宠物
	,get_pet_skills_for_battle/1                %% 获取宠物系统的技能列表
	,get_pet_passive_skills/1                   %% 获取宠物被动技能列表
    ,check_battle_skills/2                      %% 检查是否存在指定战斗技能
	,check_pet_att/3                            %% 助战宠物释放技能
	,daily_refresh/1                            %% 0点清理宠物全服支援统计表
	,refresh_player_pet_vote_info/0             %% 修改玩家的全服投票次数 && 奖励领取数据
	,do_refresh_player/1
	,handle_event/2                             %% 事件触发(战力提升刷新排行榜)

	,pet_life_skill_about_arena_power/1                 %% 排位赛战力加成5%
	,pet_life_skill_about_convoy_re_back/1              %% 护送双倍找回
	,pet_life_skill_about_guild_order/1                 %% 拼单邀请社团助手额外增加20%收益
	,pet_life_skill_about_arena_fail_compensation/1     %% 排位赛失败不损失奖励
	,pet_life_skill_about_convoy_protect_add/1          %% 护送庇护次数+1
	,pet_life_skill_about_equip_rise_star/1             %% 装备进化成功率提升5%
	,pet_life_skill_about_beach_vote_add/1              %% 舞动温泉初始点赞次数+5
	,pet_life_skill_about_arena_quick_kill/1            %% 排位赛中直接秒杀低排位对手
	,pet_life_skill_about_child_vote_add/1              %% 宝宝每日给同一玩家点赞次数+1
	,pet_life_skill_about_glamour_fund_add/1            %% 社团赛马初始资金增加200
	,pet_life_skill_about_nucleon_wash_free/1           %% 圣物洗练每日免费一次
	,pet_life_skill_about_daily_honour_add/1            %% 每日名望券获取上限增加100
	,pet_life_skill_about_deserted_revive_free/1        %% 每日混乱星域免费复活3次
	,pet_life_skill_about_gold_exchange_double/1        %% 彩钻兑换交易券10%概率暴击，收益翻倍
	,pet_life_skill_about_exp_drop_sum_time/1           %% 冒险挂机累计时间提高到24小时
	,pet_life_skill_about_equip_strength_add/1          %% 装备强化成功率提升2%
	,pet_life_skill_about_capsule_egg_free_time/1       %% 龙神扭蛋免费次数CD减少到12小时
	,pet_life_skill_about_god_summon_free/1             %% 神座普通召唤每天免费1次
	,pet_life_skill_about_galaxy_store_refresh_free/1   %% 星辰灵市每天免费刷新1次

	,get_pet_list_with_attr/1                   %% 当前激活的宠物[{pet_id,power,figure}...]
]).

%% 排位赛战力加成5%
pet_life_skill_about_arena_power(Player) ->
	case check_if_adopt_the_pet(Player, ?PET_LIFE_SKILL_ARENA_POWER_ADD) of
		{true, Value} when is_integer(Value) -> Value;
		_ -> 0
	end.

%% 护送双倍找回
pet_life_skill_about_convoy_re_back(Player) ->
	case check_if_adopt_the_pet(Player, ?PET_LIFE_SKILL_CONVOY_RE_BACK) of
		{true, Value} when is_integer(Value) -> 1;
		_ -> 0
	end.

%% 拼单邀请社团助手额外增加20%收益
pet_life_skill_about_guild_order(Player) ->
	case check_if_adopt_the_pet(Player, ?PET_LIFE_SKILL_GUILD_ORDER_ADD) of
		{true, Value} when is_integer(Value) -> max(0, Value);
		_ -> 0
	end.

%% 排位赛失败不损失奖励
pet_life_skill_about_arena_fail_compensation(Player) ->
	case check_if_adopt_the_pet(Player, ?PET_LIFE_SKILL_ARENA_FAIL_COMPENSATION) of
		{true, _Value} -> true;
		_ -> false
	end.

%% 护送庇护次数+1
pet_life_skill_about_convoy_protect_add(Player) ->
	case check_if_adopt_the_pet(Player, ?PET_LIFE_SKILL_CONVOY_PROTECT_ADD) of
		{true, Value} when is_integer(Value) -> Value;
		_ -> 0
	end.

%% 装备进化成功率提升5%
pet_life_skill_about_equip_rise_star(Player) ->
	case check_if_adopt_the_pet(Player, ?PET_LIFE_SKILL_EQUIP_RISE_STAR_ADD) of
		{true, Value} when is_integer(Value) -> max(0, Value);
		_ -> 0
	end.

%% 舞动温泉初始点赞次数+5
pet_life_skill_about_beach_vote_add(Player) ->
	case check_if_adopt_the_pet(Player, ?PET_LIFE_SKILL_BEACH_VOTE_ADD) of
		{true, Value} when is_integer(Value) -> max(0, Value);
		_ -> 0
	end.

%% 排位赛中直接秒杀低排位对手
pet_life_skill_about_arena_quick_kill(Player) ->
	case check_if_adopt_the_pet(Player, ?PET_LIFE_SKILL_ARENA_QUICK_KILL) of
		{true, _Value} -> true;
		_ -> false
	end.

%% 宝宝每日给同一玩家点赞次数+1
pet_life_skill_about_child_vote_add(Player) ->
	case check_if_adopt_the_pet(Player, ?PET_LIFE_SKILL_CHILD_VOTE_ADD) of
		{true, Value} when is_integer(Value) -> max(0, Value);
		_ -> 0
	end.

%% 社团赛马初始资金增加200
pet_life_skill_about_glamour_fund_add(Player) ->
	case check_if_adopt_the_pet(Player, ?PET_LIFE_SKILL_GLAMOUR_FUND_ADD) of
		{true, Value} when is_integer(Value) -> max(0, Value);
		_ -> 0
	end.

%% 圣物洗练每日免费一次
pet_life_skill_about_nucleon_wash_free(Player) ->
	case check_if_adopt_the_pet(Player, ?PET_LIFE_SKILL_NUCLEON_WASH_FREE) of
		{true, Value} when is_integer(Value) -> Value;
		_ -> 0
	end.

%% 每日名望券获取上限增加100
pet_life_skill_about_daily_honour_add(Player) ->
	case check_if_adopt_the_pet(Player, ?PET_LIFE_SKILL_DAILY_HONOUR_ADD) of
		{true, Value} when is_integer(Value) -> Value;
		_ -> 0
	end.

%% 每日混乱星域免费复活3次
pet_life_skill_about_deserted_revive_free(Player) ->
	case check_if_adopt_the_pet(Player, ?PET_LIFE_SKILL_DESERTED_REVIVE_FREE) of
		{true, Value} -> max(0, Value);
		_ -> 0
	end.

%% 彩钻兑换交易券10%概率暴击，收益翻倍
pet_life_skill_about_gold_exchange_double(Player) ->
	case check_if_adopt_the_pet(Player, ?PET_LIFE_SKILL_GOLD_EXCHANGE_DOUBLE) of
		{true, Value} -> Value;
		_ -> 0
	end.

%% 冒险挂机累计时间提高到24小时
pet_life_skill_about_exp_drop_sum_time(Player) ->
	case check_if_adopt_the_pet(Player, ?PET_LIFE_SKILL_DUN_EXP_DROP_SUM_TIME) of
		{true, Value} when is_integer(Value) -> max(0, Value);
		_ -> 0
	end.

%% 装备强化成功率提升2%
pet_life_skill_about_equip_strength_add(Player) ->
	case check_if_adopt_the_pet(Player, ?PET_LIFE_SKILL_EQUIP_STRENGTH_ADD) of
		{true, Value} when is_integer(Value) -> max(0, Value);
		_ -> 0
	end.

%% 龙神扭蛋免费次数CD减少到12小时
pet_life_skill_about_capsule_egg_free_time(Player) ->
	case check_if_adopt_the_pet(Player, ?PET_LIFE_SKILL_CAPSULE_EGG_FREE_TIME) of
		{true, _Value} -> true;
		_ -> false
	end.

%% 神座限时召唤每天免费1次
pet_life_skill_about_god_summon_free(Player) ->
	case check_if_adopt_the_pet(Player, ?PET_LIFE_SKILL_GOD_SUMMON_FREE) of
		{true, Value} when is_integer(Value) -> max(0, Value);
		_ -> 0
	end.

%% 星辰灵市每天免费刷新1次
pet_life_skill_about_galaxy_store_refresh_free(Player) ->
	case check_if_adopt_the_pet(Player, ?PET_LIFE_SKILL_GALAXY_STORE_REFRESH_FREE) of
		{true, Value} when is_integer(Value) -> max(0, Value);
		_ -> 0
	end.

check_if_adopt_the_pet(Player, Id) ->
	#player_status{status_pet = StatusPet} = Player,
	#status_pet{pets = Pets} = StatusPet,
	PetIds = [PetId||#pet_info{pet_id = PetId}<- Pets],
	%% 生活技能槽位为1
	F = fun(PetId, TSkillList) ->
		case data_pet:get_pet_skill_cfg(PetId, 1) of
			#pet_skill_cfg{skill_talent_id = TalentId, skill_ratio = SkillRatio}
				when TalentId == Id ->
				[{TalentId, SkillRatio}|TSkillList];
			_ -> TSkillList
		end end,
	SkillList = lists:foldl(F, [], PetIds),
	case SkillList of
		[{_SkillId, Value}|_] -> {true, Value};
		_ -> {false, 0}
	end.

%% --------------------------------------------------------------------------
%% 登录
login(Player) ->
	#player_status{id = RoleId, figure = Figure} = Player,
	%% 宠物基础信息
	PetInfoList =
	case lib_pet_data:get_db_pets_info(RoleId) of
		[] -> [];
		InfoList ->
			lib_pet:make_list(pet, InfoList, RoleId)
	end,
	if
		PetInfoList == [] ->
			%% 没有领取宠物也可以投票
			case lib_pet_data:select_db_pet_vote_info(RoleId) of
				[VoteCount, VoteListStr, ReceiveListStr] ->
					VoteList = util:bitstring_to_term(VoteListStr),
					ReceiveList = util:bitstring_to_term(ReceiveListStr);
				_ ->
					VoteCount = 0, VoteList = [], ReceiveList = []
			end,
			StatusPet = #status_pet{
				support_times     = VoteCount
				,vote_list        = VoteList
				,receive_pet_list = ReceiveList
			},
			Player#player_status{status_pet = StatusPet};
		true ->
			%% 宠物助战
			case lib_pet_data:get_db_pet_support(RoleId) of
				[_|_] = SupportInfoList ->
					SupportList = lib_pet:trans_to_support_list(SupportInfoList, []);
				_ ->
					SupportList = []
			end,
			%% 跟随宠物 = 助战位为1宠物
			case get_follow_pet(SupportList) of
				[FollowPetId|_] -> ok;
				_ -> FollowPetId = 0
			end,
			%% 宠物技能
			PetList  = lib_pet:trans_to_pet_list(PetInfoList, []),
			PetLifeSkills    = lib_pet:get_all_pet_skill_list(PetInfoList, SupportList, ?SKILL_LIFE),    %% 生活技能
			PetPassiveSkills = lib_pet:get_all_pet_skill_list(PetInfoList, SupportList, ?SKILL_ATTR),    %% 属性(加玩家被动)技能
			%% 出战宠物才拿战斗技能
			PetBattleSkills  = lib_pet:get_all_pet_skill_list(PetInfoList, SupportList, ?SKILL_BATTLE),  %% 宠物战斗技能
			%% 宠物总星级
			SumStar = lib_pet:calc_pet_sum_star(PetList, 0),
			%% 宠物属性
			%% calc_pet_sum_attr(PetInfo)
			PetInfoList1 = lib_pet:calc_pets_attr_add_ratio(PetInfoList, SupportList),
			PetsAttrList = lib_pet:calc_all_pet_attr(PetInfoList1),
			PetsPower    = lib_pet:calc_pet_power(PetsAttrList),
			ExtraPower   = lib_pet:calc_all_pet_extra_power(PetInfoList1),
			%% 投票和领取奖励数据
			case lib_pet_data:select_db_pet_vote_info(RoleId) of
				[VoteCount, VoteListStr, ReceiveListStr] ->
					VoteList = util:bitstring_to_term(VoteListStr),
					ReceiveList = util:bitstring_to_term(ReceiveListStr);
				_ ->
					VoteCount = 0, VoteList = [], ReceiveList = []
			end,
			StatusPet = #status_pet{
				pets            = PetInfoList1
				,follow_pet     = FollowPetId
				,sum_pet_star   = SumStar
				,life_skills    = PetLifeSkills
				,passive_skills = PetPassiveSkills
				,battle_skills  = PetBattleSkills
				,attr_list      = PetsAttrList
				,power          = PetsPower
				,support_list   = SupportList
				,extra_power    = ExtraPower
				,support_times  = VoteCount
				,vote_list      = VoteList
				,receive_pet_list = ReceiveList
			},
			case FollowPetId > 0 of
				true ->
					FollowPetStar = get_follow_pet_star(PetInfoList1, FollowPetId),
					FollowPetInfo = [FollowPetId, FollowPetStar];
				_ ->
					FollowPetInfo = [0, 0]
			end,
			NewFigure = Figure#figure{follow_pet = FollowPetInfo},
			NewPlayer = Player#player_status{status_pet = StatusPet, figure = NewFigure},
			%% 已开启的槽位列表
			lib_pet:check_if_open_support_slot(NewPlayer, SumStar)
	end.

%% role_show获取跟随的宠物
db_get_follow_pet(RoleId) ->
	Sql = io_lib:format(<<"select `pet_id` from pet_support_info where role_id = ~p and `slot_id`=1 limit 1">>, [RoleId]),
	case db:get_row(Sql) of
		[PetId] ->
			Sql1 = io_lib:format(<<"select `pet_star` from role_pet where role_id = ~p and `pet_id`=~p">>, [RoleId, PetId]),
			case db:get_row(Sql1) of
				[PetStar] -> [PetId, PetStar];
				_ -> []
			end;
		_ -> []
	end.

%% 当前激活的宠物属性信息
get_pet_list_with_attr(#player_status{status_pet = StatusPet}) ->
	#status_pet{pets = PetList} = StatusPet,
	F = fun(#pet_info{pet_id = PetId, pet_lv = PetLv, pet_star = PetStar,
		pet_attr = PetAttr}, TList) ->
				%% 如果配置的血量为0,则拿怪物的基础血量
				PetAttr1 =
				case lists:keyfind(2, 1, PetAttr) of
					{_, 0} ->
						MonId = data_dungeon_pet:get_dun_pet_kv_cfg(pet_id),
						case data_mon:get(MonId) of
							#mon{hp_lim = HpLim} ->
								lists:keystore(2, 1, PetAttr, {2, HpLim});
							_ -> PetAttr
						end;
					_ -> PetAttr
				end,
				case data_pet:get_pet_cfg(PetId, PetStar) of
					#pet_cfg{pet_name = PetName, figure_id = FigureId} -> ok;
					_ -> PetName = "", FigureId = 0
				end,
				Figure = #figure{name = PetName, lv = PetLv, body = FigureId},
				[{PetId, PetAttr1, Figure}|TList];
			(_, TList) ->
				TList
	end,
	List = lists:foldl(F, [], PetList),
	List.

%% 获取跟随宠物
get_follow_pet(SupportList) ->
	[PetId||#pet_support_slot{pet_id = PetId, slot_id = SlotId} <- SupportList, SlotId =:= 1].

%% 获取跟随宠物的阶级
get_follow_pet_star(PetInfoList, FollowPetId) ->
	case lists:keyfind(FollowPetId, #pet_info.pet_id, PetInfoList) of
		#pet_info{pet_star = PetStar} -> skip;
		_ -> PetStar = 0
	end,
	PetStar.

%% 获取出战宠物的(战斗)技能列表
get_pet_skills_for_battle(Player) ->
	#player_status{status_pet = StatusPet} = Player,
	#status_pet{battle_skills = BattleSkills} = StatusPet,
	[{SkillId, 1} || SkillId <- BattleSkills].

%% 获取宠物被动技能列表
get_pet_passive_skills(Player) ->
	#player_status{status_pet = StatusPet} = Player,
	#status_pet{passive_skills = PassiveSkills, battle_skills = BattleSkills} = StatusPet,
	[{SkillId, 1} || SkillId <- PassiveSkills ++ BattleSkills].

%% 检查是否在战斗技能中，有上阵即普攻（出手判断）
check_battle_skills(PS, SkillId) ->
    #player_status{status_pet = #status_pet{follow_pet = FollowPetId}} = PS,
	case SkillId =:= 121000 of
		true when FollowPetId > 0 -> true;
		_ -> false
	end.

%% 助战宠物释放技能范围广播
check_pet_att(EtsAer, SkillId, SkillLv) ->
	case data_skill:get(SkillId, SkillLv) of
		#skill{career = Career} when Career == ?SKILL_CAREER_PET ->
			#ets_scene_user{id = AttId, support_pet_list = SupportPetList} = EtsAer,
			case data_pet:get_skill_pet(SkillId) of
				PetId when is_integer(PetId) ->
					case lists:keyfind(PetId, 1, SupportPetList) of
						{_, PetStar, _IsAwaken, IsTop} ->
							{ok, BinData}  = pt_163:write(16317, [AttId, PetId, PetStar, IsTop, SkillId]),
							lib_battle:send_to_scene_area(EtsAer, 0, BinData);
						_ ->
							ignore
					end;
				_ ->
					%% 判断觉醒技能
					AllSkillList = data_pet:get_all_awaken_skill(),
					F = fun(TSkillList, {Ack, TList}) ->
							case lists:member(SkillId, TSkillList) of
								true -> {true, TSkillList};
								_ -> {Ack, TList}
							end end,
					{IsAwakenSkill, SkillList} = lists:foldl(F, {false, []}, AllSkillList),
					case IsAwakenSkill of
						true ->
							case data_pet:get_awaken_skill_pet(SkillList) of
								PetId when is_integer(PetId) ->
									case lists:keyfind(PetId, 1, SupportPetList) of
										{_, PetStar, 1, IsTop} ->
											{ok, BinData}  = pt_163:write(16317, [AttId, PetId, PetStar, IsTop, SkillId]),
											lib_battle:send_to_scene_area(EtsAer, 0, BinData);
										_ -> ignore
									end;
								_ -> ignore
							end;
						_ -> ignore
					end
			end;
		_ -> ignore
	end,
	ok.

%% 0点清理宠物全服支援统计表
daily_refresh(_DelaySec) -> %% todo:打日志
	spawn(fun() ->
		timer:sleep(1000),
		%% 清空玩家投票数据
		Sql = io_lib:format(?SQL_DELETE_PET_VOTE_INFO, []),
		db:execute(Sql),
		%% 刷新榜单数据
		mod_pet_support_mgr:daily_refresh(),
		%% 修改玩家的全服投票次数 && 奖励领取数据
		util:rand_time_to_delay(1000, ?MODULE, refresh_player_pet_vote_info, [])
	end).

refresh_player_pet_vote_info() ->
	Pids = lib_player:get_online_pids(),
	[refresh_player_pet_vote_info(Pid) || Pid <- Pids].

refresh_player_pet_vote_info(Pid) ->
	lib_player:apply_cast(Pid, ?APPLY_CAST_SAVE, ?MODULE, do_refresh_player, []).

do_refresh_player(Player) ->
	#player_status{status_pet = StatusPet, id = RoleId, sid = Sid} = Player,
	NewStatusPet = StatusPet#status_pet{support_times = 0, vote_list = [], receive_pet_list = []},
	%% 推送给前端
	NewPlayer = lib_pet_data:save_dict_status_pet(Player, NewStatusPet),
	lib_pet_data:save_db_pet_vote_info(RoleId, 0, [], []),
	PackInfo = [],
	lib_server_send:send_to_sid(Sid, pt_163, 16310, [PackInfo]),
	{ok, NewPlayer}.

%% 完成任务解锁
handle_event(Player = #player_status{}, #event_callback{type_id = ?EVENT_FINISH_TASK, data = TaskId}) ->
	#player_status{figure = Figure} = Player,
	PreTaskId = data_module:get_pre_task_id(?MOD_PET),
	case TaskId =:= PreTaskId of
		true  ->
			case Figure#figure.lv >= ?PetOpenLv of
				true ->
					case active_pet_module(Player) of
						{ok, Player1} ->
							{ok, Player1};
						_ ->
							{ok, Player}
					end;
				false ->
					{ok, Player}
			end;
		false ->
			{ok, Player}
	end;
%% 战力刷新检查排行榜更新(已废弃)
handle_event(Player, #event_callback{type_id = ?EVENT_COMBAT_POWER}) when is_record(Player, player_status) ->
	#player_status{id = RoleId, figure = Figure, combat_power = RolePower, status_pet = StatusPet} = Player,
	#status_pet{vote_list = PetList, pets = PetInfoList} = StatusPet,
	RoleInfo = {RoleId, Figure#figure.name, RolePower},
	case PetList of
		[] -> skip;
		_  ->
			%% 领养信息
			F = fun(PetId, TList) ->
				case lists:keyfind(PetId, #pet_info.pet_id, PetInfoList) of
					#pet_info{} -> [{PetId, 1}|TList];
					_ -> [{PetId, 0}|TList]
				end end,
			PetList1 = lists:foldl(F, [], PetList),
			mod_pet_support_mgr:player_power_refresh(RoleInfo, PetList1)
	end,
	{ok, Player};
%% 登录之后更新助战宠物 & 被动技能
handle_event(Player, #event_callback{type_id = ?EVENT_CLIENT_LOGIN_SUCCESS}) when is_record(Player, player_status) ->
	#player_status{status_pet = StatusPet} = Player,
	#status_pet{pets = PetInfoList, support_list = SupportList, passive_skills = PassiveSkills
		,battle_skills = BattleSkills
	} = StatusPet,
	InfoFun = fun(#pet_support_slot{pet_id = TPetId, slot_id = TSlotId}, TList) when TPetId > 0 ->
		case lists:keyfind(TPetId, #pet_info.pet_id, PetInfoList) of
			#pet_info{pet_star = TPetStar, is_awaken = IsAwaken} ->
				case TSlotId == 1 of
					true -> [{TPetId, TPetStar, IsAwaken, 1}|TList];
					_ -> [{TPetId, TPetStar, IsAwaken, 0}|TList]
				end;
			_ -> TList
		end;
		(_, TList) -> TList
	          end,
	PetList = lists:foldl(InfoFun, [], SupportList),
	mod_scene_agent:update(Player, [{support_pet_list, PetList}]),
	Passive = [{SkillId, 1} || SkillId <- PassiveSkills++BattleSkills],
	Passive =/= [] andalso mod_scene_agent:update(Player, [{passive_skill, Passive}]),
	{ok, Player};
handle_event(Player, _) ->
	{ok, Player}.

%% 激活宠物系统
active_pet_module(Player) ->
	NewPlayer = Player#player_status{status_pet = #status_pet{}},
	{ok, NewPlayer}.
