%%%-------------------------------------------------------------------
%%% @author liushl
%%% @doc
%%%     跨服据点争夺战-副本处理
%%%     之所以取名风格跟跨服沙盘其他模块不统一，其实是为了跟副本模块统一(●'◡'●)
%%% @end
%%%-------------------------------------------------------------------
-module(lib_dungeon_cross_point).
-author("liushl").

-include("server.hrl").
-include("dungeon.hrl").
-include("cross_point_fight.hrl").
-include("mon.hrl").
-include("attr.hrl").
-include("common.hrl").
%% API
-export([
    get_start_dun_args/4        %% 副本派发方法：传入初始化参数
    , get_create_mon_args/1     %% 副本派发方法：怪物创建参数
    , handle_dungeon_result/1   %% 副本派发方法：副本结算时处理
    , find_boss_info/8          %% 场景进程继续查理副本计算
    , ask_dun_point_info/1      %% 查询本次副本的据点信息
    , send_dun_point_info/2     %% 副本进程发送据点信息
]).

%% @doc 副本派发方法：传入初始化参数：跨服时间等级/BOSS剩余血量比例
get_start_dun_args(Player, _DunRole, _DunCfg, _OptionType) ->
    #player_status{
        role_cross_point = CrossPoint
    } = Player,
    case CrossPoint of
        #role_cross_point{
            dun_arg = {PointId, WorldLv, HpRatio}
        } ->
            TypicalData =
                [
                    {point_id, PointId},
                    {world_lv, WorldLv},
                    {world_ratio, data_cross_point_fight:get_point_fight_dun_ratio_lv(WorldLv)},
                    {hp_ratio, HpRatio}
                ],
            [{typical_data, TypicalData}];
        _ ->
            default()
    end.
-ifdef(DEV_SERVER).
default() ->
    [{typical_data, [{point_id, 1011}, {world_ratio, 100}, {world_lv, 500}, {hp_ratio, ?POINT_BOSS_HP_MAX_RATIO}]}].
-else.
default() ->
    [].
-endif.
%% @doc 副本派发方法：怪物创建参数，根据跨服世界等级判断碾压系数
get_create_mon_args(State) ->
    case State#dungeon_state.typical_data of
        #{
            hp_ratio := HpRatio,
            world_ratio := LvRatio,
            world_lv := WorldLv
        } ->
            WaveRatio = data_cross_point_fight:get_point_fight_dun_ratio_wave(State#dungeon_state.wave_num),
            [{dun_crush_r, LvRatio * WaveRatio}, {hp_ratio, HpRatio / ?POINT_BOSS_HP_MAX_RATIO}, {lv, WorldLv}];
        _ ->
            [{dun_crush_r, 100000000}]
    end.

%% @doc 副本派发方法：副本结算时处理
%% 1、成功杀死BOSS通关，则拿下所有积分和百分百积分
%% 2、失败超时，则拿下已通关波数积分和当前BOSS伤害积分
handle_dungeon_result(State) ->
    #dungeon_state{
        dun_id = DunId,
        role_list = [Role|_],
        result_type = ResultType,
        wave_num = WaveNum,
        scene_id = SceneId,
        scene_pool_id = PoolId,
        start_time = StartTime,
        typical_data = TypicalData
    } = State,
    #dungeon_role{
        id = RoleId
    } = Role,
    case TypicalData of
        #{
            hp_ratio := HpRatio,
            point_id := PointId
        } ->
            case data_cross_point_fight:get_point_fight_point(PointId) of
                #base_cross_point_fight_point{
                    type = Type
                } ->
                    case ResultType of
                        ?DUN_RESULT_TYPE_SUCCESS ->
                            case Type of
                                ?POINT_TYPE_SAFE ->
                                    Value = HpRatio;
                                _ ->
                                    Value = WaveNum
                            end,
                            Score = data_cross_point_fight:get_point_fight_score(DunId, Value),
                            %% 到玩法管理去判断能否为本国做贡献
                            cross_point_fight_center:finish_dun(RoleId, PointId, Score, Value, StartTime, 1);
                        _ ->
                            %% 副本失败的情形需要去判断当前BOSS的伤害比例
                            mod_scene_agent:apply_cast(SceneId, PoolId, ?MODULE, find_boss_info, [DunId, self(), RoleId, PointId, Type, WaveNum, HpRatio, StartTime])
                    end;
                _ ->
                    ok
            end;
        _ ->
            ?ERR("~p", [TypicalData])
    end,
    State.

find_boss_info(DunId, DunPid, RoleId, PointId, PointType, Wave, HpRatio, StartTime) ->
    MonInfo = lib_scene_object_agent:get_scene_object(DunPid, #scene_object.battle_attr),
    case MonInfo of
        [#battle_attr{hp = Hp, hp_lim = HpLim}|_] ->
            ok;
        _ ->
            %% 找不到BOSS，可能是还没出生
            HpLim = 100, Hp = 100
    end,
    %% 初始血量-当前血量 就是我的输出
    OriginalHp = util:ceil(HpLim * HpRatio / ?POINT_BOSS_HP_MAX_RATIO),
    MyHurt = OriginalHp - Hp,
    Score =
        case PointType of
            ?POINT_TYPE_SAFE ->
                %% 对于安全据点就是直接看输出伤害
                Value = max(0, util:ceil(?POINT_BOSS_HP_MAX_RATIO * MyHurt / HpLim)),
                data_cross_point_fight:get_point_fight_score(DunId, Value);
            _ ->
                %% 对于抢占据点，至上一波的积分+当前波的积分按输出比例折算
                Value = Wave - 1,
                CurScore = data_cross_point_fight:get_point_fight_score(DunId, Wave),
                LastScore = data_cross_point_fight:get_point_fight_score(DunId, Value),
                LastScore + util:ceil(MyHurt * (CurScore - LastScore) / HpLim )
        end,
    %% 到玩法管理去判断能否为本国做贡献
    cross_point_fight_center:finish_dun(RoleId, PointId, Score, Value, StartTime, 1).

%% 查询本次副本的据点信息
ask_dun_point_info(Player) ->
    #player_status{copy_id = DunPid} = Player,
    is_pid(DunPid) andalso
        gen_server:cast(DunPid, {apply, ?MODULE, send_dun_point_info, [Player#player_status.sid]}).

%% 副本进程发送据点信息
send_dun_point_info(State, [Sid]) ->
    #dungeon_state{
        typical_data = TypicalData
    } = State,
    case TypicalData of
        #{
            hp_ratio := HpRatio,
            point_id := PointId
        } ->
            {ok, Bin} = pt_604:write(60409, [PointId, HpRatio, ?POINT_BOSS_HP_MAX_RATIO]),
            lib_server_send:send_to_sid(Sid, Bin);
        _ ->
            ok
    end,
    ok.
