%% -----------------------------------
%% desc     :新手引导boss副本
%% module   :lib_dungeon_guide_boss.erl
%% author   :hh
%% time     :21/07/06
%% -----------------------------------

-module (lib_dungeon_guide_boss).

-export ([
    handle_kill_mon_do/2
    ,get_send_reward/2
    ,push_settlement/2

    ,hp_change_handle/3
    ,create_guide_boss_dummy/2
    ,dummy_born_callback/3
    ,dummy_born_id_return/2

    ,is_in_reward_boss_dun/1
    ,get_encourage_info/2
    ,encourage_attr/2
    ,notice_mon_hurt_rank/1
    ]).

-include ("dungeon.hrl").
-include ("mon.hrl").
-include ("attr.hrl").
-include ("battle.hrl").
-include ("scene.hrl").
-include ("local_boss.hrl").
-include ("figure.hrl").
-include ("attr.hrl").
-include ("errcode.hrl").
-include ("skill.hrl").
-include ("common.hrl").
-include ("server.hrl").

-define (ROLE_TYPICAL_DATA_GUIDE_BOSS_REWARDS, guide_boss_base_rewards).
-define (ROLE_TYPICAL_DATA_ENCOURAGE_INFO, encourage_info).

%% 怪物进程回调-血量变化通知
hp_change_handle(_State, _MonAtter, [_, _, _, TriggerCount]) when TriggerCount >= 2 ->
    stop;
hp_change_handle(State, _MonAtter, [OldHp, AccLoss, TriggerLoss, TriggerCount]) ->
    #ob_act{object = Object} = State,
    #battle_attr{hp = NowHp} = Object#scene_object.battle_attr,
    #scene_object{copy_id = CopyId, config_id = MonId} = Object,
    Loss = OldHp - NowHp,
    AccLoss1 = AccLoss + Loss,
    LossUnit = AccLoss1 div TriggerLoss,
    RemLoss = AccLoss1 rem TriggerLoss,
    if 
        LossUnit > 0 ->
            TriggerCount1 = min(TriggerCount+LossUnit, 2),
            TriggerIndex = lists:seq(TriggerCount+1, TriggerCount1),
            % ?ERR("~p", [TriggerIndex]),
            gen_server:cast(CopyId, {apply, ?MODULE, create_guide_boss_dummy, [MonId, TriggerIndex]}),
            {ok, State, {?MODULE, hp_change_handle, [NowHp, RemLoss, TriggerLoss, TriggerCount1]}};
        true ->
            {ok, State, {?MODULE, hp_change_handle, [NowHp, AccLoss1, TriggerLoss, TriggerCount]}}
    end.

%% 单人引导boss的结算奖励是拿的赏金boss的奖励
get_send_reward(State, DungeonRole) ->
    #dungeon_state{result_type = ResultType} = State,
    if 
        ResultType == ?DUN_RESULT_TYPE_SUCCESS ->
            #dungeon_role{typical_data = RoleData} = DungeonRole,
            {AwardBase, ExtraGoods} = maps:get(?ROLE_TYPICAL_DATA_GUIDE_BOSS_REWARDS, RoleData, {[], []}),
            Rewards = lists:append([AwardBase, ExtraGoods]),
            Rewards;
        true ->
            []
    end.


%% 击杀boss处理
handle_kill_mon_do(State, [_Mid, _AtterId, _MonXys|_]) ->
    #dungeon_state{role_list = [#dungeon_role{typical_data = RoleData} = DungeonRole|_]} = State,
    #base_reward_boss_info{award_base = AwardBase} = RewardBossCfg = data_local_boss:get_reward_boss_info(13010001),
    ExtraGoods = reward_boss_mgr:calc_extra_reward(RewardBossCfg),
    DungeonRole1 = DungeonRole#dungeon_role{typical_data = maps:put(?ROLE_TYPICAL_DATA_GUIDE_BOSS_REWARDS, {AwardBase, ExtraGoods}, RoleData)},
    State#dungeon_state{role_list = [DungeonRole1]}.

%% 延后副本结算|失败立即推送
push_settlement(State, DungeonRole) ->
    #dungeon_state{dun_id = DunId, scene_id = SceneId, wave_num = WaveNum, 
        result_type = ResultType, result_subtype = ResultSubtype} = State,
    #dungeon_role{id = RoleId} = DungeonRole,
    if 
        ResultType == ?DUN_RESULT_TYPE_SUCCESS ->
            #dungeon_role{id = RoleId, drop_reward_list = DropRewards, typical_data = RoleData} = DungeonRole,
            {_, ExtraGoods} = maps:get(?ROLE_TYPICAL_DATA_GUIDE_BOSS_REWARDS, RoleData, {[], []}),
            #mon{name = BossName} = data_mon:get(?REWARD_BOSS_DUN_MON),
            {ok, BinData} = pt_460:write(46015, [BossName, DropRewards, ExtraGoods]),
            lib_server_send:send_to_uid(RoleId, BinData),
            ok;
        true ->
            {ok, BinData} = pt_610:write(61003, [ResultType, ResultSubtype, DunId, SceneId, WaveNum, [], [], []]),
            lib_server_send:send_to_uid(RoleId, BinData),
            ok
    end.

%% 副本进程
create_guide_boss_dummy(State, [MonId, IndexList]) ->
    #dungeon_state{
        scene_id = NowSceneId, scene_pool_id = ScenePoolId,
        role_list = [DunRole|_],
        typical_data = TypicalData} = State,
    #dungeon_role{
        base_attr = BaseAttr, server_id = SvrId, server_num = SvrNum,
        figure = Figure} = DunRole,
    %% 初始化怪物技能cd
    CareerList = data_career:get_all_career(),
    [{RandCareer, RandSex}|_] = urand:list_shuffle(CareerList),
    RandFigure = Figure#figure{career = RandCareer, sex = RandSex},
    TempSkills = lib_skill_api:get_career_active_skill_ids(RandCareer, RandSex),
    SkillList  = dungeon_default:filter_anger_skill(TempSkills, []),
    % ?ERR("~p ~p", [{RandCareer, RandSex}, SkillList]),
    DummyAttr = calc_dummy_attr_based_role([], BaseAttr, 0.3),
    #attr{hp = Hp} = NewAttr = attr_conv:to_attr_record(DummyAttr),
    BattleAttr = #battle_attr{
        hp = Hp, hp_lim = Hp, hp_lim_origin = Hp, attr = NewAttr,
        pk = #pk{}, speed = ?SPEED_VALUE, group = 1 %% 假人分组和玩家及怪物都不一样
    },
    CopyId = self(),
    DummyArgs = [
        {battle_attr, BattleAttr}, {skill, SkillList}, {find_type, 1},
        {born_handler, {?MODULE, dummy_born_callback, [CopyId, MonId]}}],
    DunDummys = create_guide_boss_dummy_1(IndexList, {NowSceneId, ScenePoolId, CopyId, SvrId, SvrNum}, RandFigure, DummyArgs, []),
    OldDunDummys = maps:get(?DUN_STATE_SPECIAL_KEY_DUMMY, TypicalData, []),
    NewDunDummys = lists:append(DunDummys, OldDunDummys),
    TypicalData1 = maps:put(?DUN_STATE_SPECIAL_KEY_DUMMY, NewDunDummys, TypicalData),
    State#dungeon_state{typical_data = TypicalData1}.

create_guide_boss_dummy_1([], _, _Figure, _DummyArgs, DunDummys) ->
    DunDummys;
create_guide_boss_dummy_1([Num|Rest], {NowSceneId, ScenePoolId, CopyId, SvrId, SvrNum}, Figure, DummyArgs, DunDummys) ->
    DummyFigure = lib_dummy_api:change_figure(Figure, [rand_name, rand_fashion, create_name]),
    PhotoIds = data_profile_photo:get_photo_id_cfg([0], 0),
    PhotoId = urand:list_rand(PhotoIds),
    DummyFigure1 = DummyFigure#figure{id = Num, profile_photo_id = PhotoId},
    FinalAttrs = [{figure, DummyFigure1}, {mod_args, Num}, {tracing_distance, 300}] ++ DummyArgs,
    [X, Y] = lib_scene:get_born_xy(NowSceneId),
    lib_scene_object:async_create_object(?BATTLE_SIGN_DUMMY, 0, NowSceneId, ScenePoolId, X, Y, 1, CopyId, 1, FinalAttrs),
    DunDummy = #dungeon_dummy{
        id = Num, figure = DummyFigure1, server_id = SvrId, server_num = SvrNum
    },
    create_guide_boss_dummy_1(Rest, {NowSceneId, ScenePoolId, CopyId, SvrId, SvrNum}, Figure, DummyArgs, [DunDummy|DunDummys]).

%% 假人出生回调
dummy_born_callback(init, #ob_act{object = #scene_object{id = Aid, mod_args = CreateIndex}}, [From, _MonId|_]) ->
    % case data_local_boss:get_reward_boss_info(13010001) of
    %     #base_reward_boss_info{boss_position = {X, Y}} ->
    %         {MoveX, MoveY} = umath:rand_point_in_circle(X, Y, 40, 1),
    %         mon_mgr:send_after(800, self(), Aid, {move, MoveX, MoveY}),
            mon_mgr:send_after(500, self(), Aid, rush_and_find_target),
    %     _ ->
    %         skip
    % end,
    mod_dungeon:apply(From, ?MODULE, dummy_born_id_return, [CreateIndex, Aid]),
    ok.

%% 替换新的id
dummy_born_id_return(State, [CreateIndex, DummyId]) ->
    #dungeon_state{typical_data = TypicalData} = State,
    DunDummys = maps:get(?DUN_STATE_SPECIAL_KEY_DUMMY, TypicalData, []),
    DunDummys1 =
    case lists:keytake(CreateIndex, #dungeon_dummy.id, DunDummys) of
        {value, #dungeon_dummy{figure = Figure} = OldDunDummy, LessDunDummy} ->
            OldDunDummy1 = OldDunDummy#dungeon_dummy{id = DummyId, figure = Figure#figure{id = DummyId}},
            [OldDunDummy1|LessDunDummy];
        _ ->
            DunDummys
    end,
    TypicalData1 = maps:put(?DUN_STATE_SPECIAL_KEY_DUMMY, DunDummys1, TypicalData),
    State#dungeon_state{typical_data = TypicalData1}.


%% 假人属性
calc_dummy_attr_based_role(AttrList, [], _) ->
    AttrList;
calc_dummy_attr_based_role(AttrList, [{K, V}|Rest], R) ->
    calc_dummy_attr_based_role([{K, round(V*R)}|AttrList], Rest, R).


is_in_reward_boss_dun(Player) ->
    case lib_dungeon:is_on_dungeon(Player) of
        false ->
            false;
        _ ->
            #player_status{dungeon = #status_dungeon{dun_id = DunId}} = Player,
            DunType = data_dungeon:get_dun_type(DunId),
            DunType == ?DUNGEON_TYPE_GUIDE_BOSS
    end.

get_encourage_info(State, [BossId, RoleId, Sid]) ->
    #dungeon_state{role_list = RoleList} = State,
    case lists:keyfind(RoleId, #dungeon_role.id, RoleList) of
        #dungeon_role{typical_data = RoleData} ->
            {ByGold, ByBGold} = maps:get(?ROLE_TYPICAL_DATA_ENCOURAGE_INFO, RoleData, {0, 0}),
            lib_server_send:send_to_sid(Sid, pt_460, 46019, [BossId, ByGold, ByBGold]);
        _ ->
            lib_server_send:send_to_sid(Sid, pt_460, 46019, [BossId, 0, 0])
    end,
    State.

encourage_attr(State, [RoleId, RolePid, _BossId, Type, IsUnite]) ->
    #dungeon_state{role_list = [DungeonRole|_]} = State,
    #dungeon_role{typical_data = RoleData} = DungeonRole,
    {ByGold, ByBGold} = maps:get(?ROLE_TYPICAL_DATA_ENCOURAGE_INFO, RoleData, {0, 0}),
    if  
        Type == 1 -> Had = ByGold;
        Type == 2 -> Had = ByBGold;
        true -> Had = 0
    end,
    Max = 
    case Type of
        1 -> data_local_boss:get_local_boss_kv(encourage_by_gold);
        2 -> data_local_boss:get_local_boss_kv(encourage_by_bgold)
    end,
    Res =
        if
            Had >= Max  ->
                {false, ?ERRCODE(err460_encourage_limit)};
            Type =:= 2 andalso Had =:= 0 -> %% 绑玉鼓舞免费一次
                ok;
            Type =:= 1 andalso Had =:= 0 andalso IsUnite /= false ->
                %% 钻石有buff的时候免费一次
                ok;
            true ->
                MFA = {reward_boss_mgr, cost_encourage_money, [Type, Had+1]},
                try gen_server:call(RolePid, {fast_call, MFA}, 3000) of
                    {false, Err} ->
                        {false, Err};
                    {ok, CostType} ->
                        {ok, CostType};
                    {ok} -> 
                        {ok};
                    _Err ->
                        {false, ?FAIL}
                catch Class:Reason -> %% 超时之类的
                    Error = {Class, Reason, erlang:get_stacktrace()},
                    ?ERR("~w error:~p~n", [?MODULE, Error]),
                    {false, ?FAIL}
                end
        end,
    case Res of
        {false, ErrCode} ->
            {ok, Bin} = pt_460:write(46014, [ErrCode, Type]),
            lib_server_send:send_to_uid(RoleId, Bin),
            State;
        _A ->
            % case Res of
            %     {ok} -> CostType2 = default;
            %     ok   -> CostType2 = default;
            %     {ok, CostType1} -> CostType2 = CostType1
            % end,
            case Type of
                1 ->
                    NewInfo = {ByGold+1, ByBGold};
                2 ->
                    NewInfo = {ByGold, ByBGold+1}
            end,
            lib_skill_api:add_buff(RoleId, ?SP_SKILL_BUFF_ENCOURAGE, ByGold+ByBGold+1),
            % CountType = 
            % if 
            %     Type == 1 -> ?INSPIRE_GOLD;
            %     Type == 2 andalso CostType2 == default -> ?INSPIRE_BGOLD;
            %     true -> ?INSPIRE_TICK
            % end,
            % lib_player:apply_cast(RoleId, ?APPLY_CAST_STATUS, ?MODULE, role_add_inspire_count, [CountType]),
            % State1 = State#local_reward_boss{encourage_info = lists:keystore(RoleId, 1, EncourageInfo, NewInfo)},
            NewRoleData = maps:put(?ROLE_TYPICAL_DATA_ENCOURAGE_INFO, NewInfo, RoleData),
            State1 = State#dungeon_state{role_list = [DungeonRole#dungeon_role{typical_data = NewRoleData}]},
            {ok, Bin} = pt_460:write(46014, [1, Type]),
            lib_server_send:send_to_uid(RoleId, Bin),
            State1
    end.

notice_mon_hurt_rank(State) ->
    #dungeon_state{role_list = RoleList} = State,
    PackData1 = lists:foldl(fun(DungeonRole, Acc) ->
        #dungeon_role{id = RoleId, figure = #figure{name = RoleName}, typical_data = TypicalDataX} = DungeonRole,
        MonHurtX = maps:get(?DUN_ROLE_CRUSADE_DUN_MON_HURT, TypicalDataX, 0),
        [{RoleId, 0, RoleName, MonHurtX}|Acc]
     end, [], RoleList),
    % DunDummys = maps:get(?DUN_STATE_SPECIAL_KEY_DUMMY, TypicalData, []),
    % PackData2 = lists:foldl(fun(DunDummy, Acc1) -> 
    %     #dungeon_dummy{id = DummyId, figure = #figure{name = RoleName1}, hurt_calc = DummyHurtX1} = DunDummy,
    %     [{DummyId, 0, RoleName1, DummyHurtX1}|Acc1]      
    % end, PackData1, DunDummys),
    #mon{hp_lim = HpLim} = data_mon:get(?REWARD_BOSS_DUN_MON),
    {ok, BinData} = pt_460:write(46007, [?REWARD_BOSS_DUN_MON, HpLim, PackData1]),
    % ?ERR("~p ~p ~p", [?REWARD_BOSS_DUN_MON, HpLim, PackData2]),
    dungeon_logic:notice_dun_role_info(RoleList, BinData).