%%%-------------------------------------------------------------------
%%% @author liushl
%%% @doc
%%%     狂战领域接口
%%% @end
%%%-------------------------------------------------------------------
-module(madness_land_api).
-author("liushl").

-include("server.hrl").
-include("common.hrl").
-include("errcode.hrl").
-include("figure.hrl").
-include("madness_land.hrl").
-include("def_event.hrl").
-include("rec_event.hrl").
-include("battle.hrl").
-include("attr.hrl").
-include("def_act_label.hrl").
-include("scene.hrl").
-include("def_module.hrl").
-include("predefine.hrl").
-include("guild.hrl").
-include("rec_dress_up.hrl").
%% API
-export([
    is_during_madness_land/0        %% 是否狂战领域开放期间
    , is_madness_land_scene/1       %% 是否狂战领域场景
    , is_madness_land_center/1      %% 是否狂战领域跨服场景
    , get_act_type/0                %% 活动类型:1跨服/0本服
]).

-export([
    handle_event/2
    , change_scene_callback/4
    , when_mon_be_hurt/4            %% 怪物收到伤害
    , stop_mon/3                    %% 怪物被清掉
    , when_mon_die/4

    , ask_enter_madness_land/1      %% 请求进入活动场景
    , is_ok_enter/4
    , role_enter/4

    , enter_send_round/2            %% 第一轮结束，将玩家拉进第二轮场景
    , check_enter_send_round/2
    , leave_scene/1                 %% 离开活动场景
    , leave_scene_callback/2        %% 离开场景
    , ta_data_upload/2
]).

%% 是否狂战领域开放期间
is_during_madness_land() ->
    madness_land:is_during_madness_land().

%% 是否狂战领域场景
is_madness_land_scene(SceneId) ->
    SceneId =:= ?MADNESS_LAND_SCENE_ROUND_1
        orelse SceneId =:= ?MADNESS_LAND_SCENE_ROUND_2_CENTER
        orelse SceneId =:= ?MADNESS_LAND_SCENE_ROUND_2_NODE.

%% 是否狂战领域跨服场景
is_madness_land_center(SceneId) ->
    SceneId =:= ?MADNESS_LAND_SCENE_ROUND_2_CENTER.

%% 活动类型
get_act_type() ->
    case czone_api:zone_open_check() of
        {true, _} ->
            ?NODE_CENTER;
        _ ->
            ?NODE_GAME
    end.

%%% @doc 事件处理
%% 进入场景后，给前端发送一些数据
handle_event(Player, #event_callback{type_id = ?EVENT_FIN_CHANGE_SCENE}) ->
    #player_status{
        id = RoleId,
        scene = Scene,
        online = OnlineFlag
    } = Player,
    case is_madness_land_scene(Scene) of
        true  ->
            case is_madness_land_center(Scene) of
                true  ->
                    madness_land:common_cast_to_center({after_enter, RoleId, OnlineFlag});
                false ->
                    madness_land:common_cast_local({after_enter, RoleId, OnlineFlag})
            end;
        false ->
            ok
    end,
    {ok, Player};
%% 死亡后-更新自己与攻击者的连击数/攻击者加分
handle_event(Player, #event_callback{type_id = ?EVENT_PLAYER_DIE, data = #{atter := Attacker, attersign := Sign}}) ->
    #player_status{
        id = RoleId,
        scene = SceneId,
        online = DefendOnline
    } = Player,
    #battle_return_atter{
        id = AttackId,
        online = AttackOnline
    } = Attacker,
    case is_madness_land_scene(SceneId) of
        true  ->
            Sign =:= ?BATTLE_SIGN_PLAYER andalso
                case is_madness_land_center(SceneId) of
                    true  ->
                        madness_land:common_cast_to_center({kill_man, AttackId, RoleId, AttackOnline, DefendOnline});
                    false ->
                        madness_land:common_cast_local({kill_man, AttackId, RoleId, AttackOnline, DefendOnline})
                end,
            {ok, Player};
        false ->
            {ok, Player}
    end;
%% 角色改名
handle_event(Player, #event_callback{type_id = ?EVENT_RENAME, data = Name}) ->
    madness_land:update_role_info(Player#player_status.id, name, Name),
    {ok, Player};
%% 角色VIP升级
handle_event(Player, #event_callback{type_id = ?EVENT_VIP}) ->
    #player_status{id = RoleId, figure = #figure{vip = Vip}} = Player,
    madness_land:update_role_info(RoleId, vip, Vip),
    {ok, Player};
%% 角色至尊VIP变化
handle_event(Player, #event_callback{type_id = ?EVENT_SUP_VIP_CHANGE}) ->
    #player_status{id = RoleId, figure = #figure{sup_vip = SupVip}} = Player,
    madness_land:update_role_info(RoleId, sup_vip, SupVip),
    {ok, Player};
%% 加入公会
handle_event(Player, #event_callback{type_id = ?EVENT_JOIN_GUILD}) ->
    #player_status{id = RoleId, figure = #figure{guild_id = GuildId, guild_name = GuildName}} = Player,
    madness_land:update_role_info(RoleId, guild, {GuildId, GuildName}),
    {ok, Player};
%% 头像
handle_event(Player, #event_callback{type_id = ?EVENT_PICTURE_CHANGE}) ->
    #player_status{id = RoleId, figure = #figure{profile_photo_id = ProfilePhotoId}} = Player,
    madness_land:update_role_info(RoleId, photo, ProfilePhotoId),
    {ok, Player};
%% 头像框
handle_event(Player, #event_callback{type_id = ?EVENT_DRESS_UP_CHANGE, data = ChangeList}) ->
    #player_status{id = RoleId, figure = Figure} = Player,
    lists:keymember(?DRESS_UP_FRAME, 2, ChangeList) andalso
        madness_land:update_role_info(RoleId, photo_dress, lib_dress_up:get_role_frame_dress(Figure)),
    {ok, Player};
%% 离线
handle_event(Player, #event_callback{type_id = ?EVENT_DISCONNECT}) ->
    #player_status{id = RoleId, scene = Scene} = Player,
    case is_madness_land_center(Scene) of
        true  ->
            madness_land:common_cast_to_center({leave_scene, RoleId});
        false ->
            case is_madness_land_scene(Scene) of
                true  ->
                    madness_land:common_cast_local({leave_scene, RoleId});
                false ->
                    ignore
            end
    end,
    {ok, Player};
handle_event(Player, _) ->
    {ok, Player}.

%% 切换场景时回调
change_scene_callback(Player, _OldSceneInfo, OldSceneData, NewSceneData) ->
    case is_madness_land_scene(OldSceneData#ets_scene.id) of
        true  ->
            case is_madness_land_scene(NewSceneData#ets_scene.id) of
                true  ->
                    Player1 = Player;
                false ->
                    Player1 = lib_player:break_action_lock(Player, ?ERRCODE(err415_in_madness_land))
            end,
            case is_madness_land_center(OldSceneData#ets_scene.id) of
                true  ->
                    madness_land:common_cast_to_center({leave_scene, Player#player_status.id});
                false ->
                    madness_land:common_cast_local({leave_scene, Player#player_status.id})
            end,
            Player2 = Player1#player_status{act_label = []},  %% act_label直接置空，目前来看是唯一的
            {ok, Player2};
        false ->
            {ok, Player}
    end.

%% 怪物收到伤害
when_mon_be_hurt(Mon, MonAtter, Hurt, IsFirstAttack) ->
    #scene_object{
        scene = SceneId,
        config_id = MonId,
        id = Id
    }= Mon,
    #battle_return_atter{
        id = RoleId,
        server_id = ServerId,
        online = Online
    } = MonAtter,
    case Hurt > 0 andalso is_madness_land_scene(SceneId) of
        true  ->
            IsBoss = is_boss(MonId),
            if
                IsBoss andalso IsFirstAttack ->
                    case is_madness_land_center(SceneId) of
                        true  ->
                            ZoneId = czone_api:server_zone(ServerId),
                            madness_land:common_cast_center(ZoneId, {attck_mon, RoleId, MonId});
                        false ->
                            madness_land:common_cast_local({attck_mon, RoleId, MonId})
                    end;
                true ->
                    %% 平常攻击 每X刀加Y分
                    {X, Y} =
                    case IsBoss of
                        true  -> ?MADNESS_LAND_BOSS_ATTACK_SCORE;
                        false -> ?MADNESS_LAND_MONS_ATTACK_SCORE
                    end,
                    CountInfo = get_attack_count(Id),
                    Count = maps:get(RoleId, CountInfo, 0),
                    case Count >= X of
                        true  ->
                            case is_madness_land_center(SceneId) of
                                true  ->
                                    ZoneId = czone_api:server_zone(ServerId),
                                    madness_land:common_cast_center(ZoneId, {add_score, RoleId, Y, attack_mon, Online});
                                false ->
                                    madness_land:common_cast_local({add_score, RoleId, Y, attack_mon, Online})
                            end,
                            set_attack_count(Id, RoleId, 0, CountInfo);
                        false ->
                            set_attack_count(Id, RoleId, Count + 1, CountInfo)
                    end
            end;
        false ->
            ok
    end.

get_attack_count(Id) ->
    case get({madness_attack_count, Id}) of
        Maps when is_map(Maps) ->
            Maps;
        _ ->
            #{}
    end.

set_attack_count(Id, RoleId, Count, Maps) ->
    put({madness_attack_count, Id}, Maps#{RoleId => Count}).

clean_attack_count(Id) ->
    erase({madness_attack_count, Id}).

%% 怪物被清掉
stop_mon(SceneId, PoolId, AutoId) ->
    when_mon_die(SceneId, PoolId, AutoId, stop).

when_mon_die(Scene, ScenePoolId, AutoId, Timing) ->
    case is_madness_land_scene(Scene) of
        true  ->
            clean_attack_count(AutoId),
            case is_madness_land_center(Scene) of
                true  ->
                    ZoneId = scene_mgr:get_pool_zone(ScenePoolId),
                    madness_land:common_cast_center(ZoneId, {mon_die, ScenePoolId, Timing});
                false ->
                    madness_land:common_cast_local({mon_die, ScenePoolId, Timing})
            end;
        false ->
            ignore
    end.

%%%-------------------------------------------------------------------
%%% @doc 玩家协议处理
%%%-------------------------------------------------------------------
%% @doc 请求进入
ask_enter_madness_land(Player) ->
    #player_status{
        figure = #figure{lv = Lv},
        id = RoleId
    } = Player,
    case lib_scene:is_transferable(Player) of
        {false, Error} -> {false, Error};
        {true, 1} ->
            NeedLv = lib_module:get_open_lv(?MOD_MADNESS_LAND),
            if
                Lv < NeedLv -> {false, ?ERRCODE(err415_level_limit)};
                true ->
                    madness_land:apply_info({ask_enter, RoleId, false})
            end
    end.

%% 可以进入活动
is_ok_enter(RoleId, TargetScene, Arg, IsForce) ->
    lib_player:apply_cast(RoleId, ?APPLY_CAST_STATUS, ?MODULE, role_enter, [TargetScene, Arg, IsForce]).
role_enter(Player, TargetScene, Arg, IsForce) ->
    case lib_scene:is_transferable(Player) of
        {false, Error} when not IsForce ->
            {ok, Bin} = pt_415:write(41501, [Error]),
            lib_server_send:send_to_sid(Player#player_status.sid, Bin),
            Player;
        _ ->
            #player_status{
                id = RoleId,
                server_id = ServerId,
                server_num = ServerNum,
                figure = Figure,
                guild = Guild
            } = Player,
            RoleInfo = #madness_land_role{
                role_id     = RoleId
                , picture   = lib_player:trans_to_picture(Figure)
                , server_id = ServerId     %% 服务器id
                , server_num = ServerNum
                , node = node()
                , zone_id = czone_api:env_get_zone_id()
                , guild_id = Figure#figure.guild_id
                , guild_name = Figure#figure.guild_name
            },
            #status_guild{flag = GuildFlag} = Guild,
            case is_madness_land_center(TargetScene) of
                true  ->
                    madness_land:common_cast_to_center({enter_scene, RoleInfo, GuildFlag});
                false ->
                    madness_land:common_cast_local({enter_scene, RoleInfo, GuildFlag})
            end,
            Player1 = lib_scene:change_scene(Player, TargetScene, 0, 0, Arg),
            Player2 = offline_hosting_madness_land:enter_scene(Player1),
            Player3 = lib_activity_reserve:enter_act(Player2, ?MOD_MADNESS_LAND),
            Player3
    end.

%% 第一轮结束，将玩家拉进第二轮场景
enter_send_round(RoleId, TargetScene) ->
    lib_player:apply_cast(RoleId, ?APPLY_CAST_STATUS, ?MODULE, check_enter_send_round, [TargetScene]).
check_enter_send_round(Player, TargetScene) ->
    case Player#player_status.scene =:= ?MADNESS_LAND_SCENE_ROUND_1 of
        true  ->
            role_enter(Player, TargetScene, [], true);
        false ->
            Player
    end.

%% @doc 离开活动场景
leave_scene(Player) ->
    case is_madness_land_scene(Player#player_status.scene) of
        true  ->
            lib_scene:change_scene(Player, 0, 0, 0, 0, 0, []);
        false ->
            Player
    end.

ta_data_upload(Stage, Roles) ->
    Now = utime:unixtime(),
    dict:fold(
        fun(_Key, Role, _) ->
            case Role#madness_land_role.leave of
                false ->
                    lib_player:apply_cast(Role#madness_land_role.role_id, ?APPLY_CAST_STATUS, ?MODULE, leave_scene_callback,
                        [{Stage, Role#madness_land_role.score, Now - Role#madness_land_role.enter_time, Role#madness_land_role.die_count}]);
                true  ->
                    ignore
            end
        end, [], Roles
    ).

%% 系统阶段切换踢人的时候会批量处理
leave_scene_callback(Player, {FamStage, Score, Interval, DieCount}) ->
    Player#player_status.online =/= ?ONLINE_OFF_HOSTING andalso
        ta_agent_fire:madness_land(Player, [FamStage, Score, DieCount, Interval]),
    Player.
%%%===================================================================
%%% Internal functions
%%%===================================================================
is_boss(BossId) ->
    BossId =:= ?MADNESS_LAND_ROUND_1_BOSS
        orelse BossId =:= ?MADNESS_LAND_ROUND_2_BOSS.