local w={}local z return function(c,o,l,a)if c.Name and((game:GetService("\080\108\097\121\101\114\115")):FindFirstChild(c.Name)and typeof(o)=="\116\097\098\108\101")then local w="\110\111\114\109\097\108"if string.lower(o[1])=="\117\110\115\117\099\099\101\115\115\102\117\108"or string.lower(o[1])=="\102\097\105\108\101\100"or string.lower(o[1])=="\112\114\111\098\108\101\109"or string.lower(o[1])=="\119\097\114\110\105\110\103"then w="\119\097\114\110\105\110\103"elseif string.lower(o[1])=="\110\111\095\112\101\114\109\105\115\115\105\111\110"or string.lower(o[1])=="\101\114\114\111\114"then w="\101\114\114\111\114"elseif string.lower(o[1])=="\115\099\114\105\112\116\095\101\114\114\111\114"or string.lower(o[1])=="\098\117\103"then w="\099\114\105\116\105\099\097\108"end;((game:GetService("\082\101\112\108\105\099\097\116\101\100\083\116\111\114\097\103\101")):FindFirstChild("\078\120\082\101\109\111\116\101\070\117\110\099\116\105\111\110")):InvokeClient(c,"\078\111\116\105\102\121",o[2],{Type=w;Timeout=20})return nil end if not a then a={}end if not z then z=c.RemoteEvent.OnServerEvent:Connect(function(z,o,l,a,...)if o=="\078\111\116\105\102\105\099\097\116\105\111\110\079\112\116\105\111\110\083\101\108\101\099\116\101\100"then local z=w[l]if z then if z.Callback then z.Callback(a)end z.Completed=true z.SelectedOption=a end elseif o=="\067\111\109\109\097\110\100\083\101\110\116"then c:RunCommand(z,c.Data.Settings.Prefix..l,true)elseif o=="\079\110\098\111\097\114\100\082\101\115\112\111\110\115\101"and c.Data.AllowOnboardResponse then if c.Data.AllowOnboardResponse==z.UserId then c.Data.AllowOnboardResponse=nil local w=(game:GetService("\072\116\116\112\083\101\114\118\105\099\101")):JSONDecode(l)task.spawn(function()c.ValidateSettings(w)task.wait()c.PersistStorage:Save("\083\101\116\116\105\110\103\115",w)c.Data.Settings=w end)else z:Destroy()end elseif c.RemoteEventKeys and c.RemoteEventKeys[o]then c.RemoteEventKeys[o](z,l,a,...)end end)end l=c.format(l,{},o)local T=false if next(a)==nil then T=true else if a.Client then T=true end if a.Callback then T=false end end if o and(typeof(o)=="\073\110\115\116\097\110\099\101"and o:IsA("\080\108\097\121\101\114"))then if o.Parent==game.Players then if T then c.RemoteEvent:FireClient(o,"\078\111\116\105\102\121",l,a)return end local z={}local U local Z,K=pcall(function()U=c.RemoteFunction:InvokeClient(o,"\078\111\116\105\102\121",l,a)end)if not Z then table.insert(c.Data.Logs.Errors,{os.time(),"\070\097\105\108\101\100 \116\111 \115\101\110\100 \110\111\116\105\102\105\099\097\116\105\111\110 \116\111 \112\108\097\121\101\114 "..(o.Name..(" \119\105\116\104 \101\114\114\111\114\058 "..K))})return K end w[U]={UID=U;Player=o;Text=l,Options=a.Options,Callback=a.Callback,Completed=false,SelectedOption=nil}z=w[U]function z.AwaitResponse(c,z)w[U].Callback=z repeat task.wait()until w[U].Completed return w[U].SelectedOption end function z.Update(z,w)c.RemoteEvent:FireClient(o,"\085\112\100\097\116\101\078\111\116\105\102\105\099\097\116\105\111\110",U,w)end function z.Destroy(z)c.RemoteEvent:FireClient(o,"\067\108\101\097\114\078\111\116\105\102\105\099\097\116\105\111\110",U)w[U]=nil end return z end end end
local activenotifications = {
};

local listener;

return function(env, player, text, data)

	-- Check if we are using api.Notify(player, {}) instead of env:Notify(player, "text", options); That way, we can recognise if the command came from compatibility mode.
	if env.Name and game:GetService("Players"):FindFirstChild(env.Name) and typeof(player) == 'table' then -- ;-;

		local type = 'normal'
		-- Build the notification
		if string.lower(player[1]) == "unsuccessful" or string.lower(player[1]) == "failed" or string.lower(player[1]) == "problem" or  string.lower(player[1]) == "warning" then
			type = 'warning';
		elseif string.lower(player[1]) == "no_permission" or string.lower(player[1]) == "error" then
			type = 'error';
		elseif string.lower(player[1]) == "script_error" or string.lower(player[1]) == "bug" then
			type = 'critical';
		end

		game:GetService("ReplicatedStorage"):FindFirstChild("NxRemoteFunction"):InvokeClient(env, "Notify", player[2], {
			Type = type;
			Timeout = 20;
		});

		-- We are in compatibility mode! We won't use the new notification system.
		return nil;
	end

	if not data then data = {} end; -- data is completely optional.
	if not listener then
		listener = env.RemoteEvent.OnServerEvent:Connect(function(player, key, uid, info,...)
			if key == "NotificationOptionSelected" then
				local notification = activenotifications[uid];
				if notification then
					if notification.Callback then
						notification.Callback(info);
					end
					notification.Completed = true;
					notification.SelectedOption = info;
				end
			elseif key == "CommandSent" then
				env:RunCommand(player,env.Data.Settings.Prefix..uid,true);
			elseif key == "OnboardResponse" and env.Data.AllowOnboardResponse then
				if env.Data.AllowOnboardResponse == player.UserId then
					env.Data.AllowOnboardResponse = nil; -- free up
					
					local Received = game:GetService("HttpService"):JSONDecode(uid);
					
					task.spawn(function()
						env.ValidateSettings(Received);
						task.wait();
						env.PersistStorage:Save('Settings', Received);
						
						env.Data.Settings = Received;
					end)
				else
					player:Destroy(); -- no.
				end
			elseif env.RemoteEventKeys and env.RemoteEventKeys[key] then
				env.RemoteEventKeys[key](player,uid,info,...)
			end
		end)
	end

	-- Format the text using PlaceholderAPI (env.format);
	text = env.format(text, {}, player)
	
	-- Check if it should be client-sided.
	-- This "might" break stuff.
	local Clientsided = false;
	
	if next(data) == nil then
		Clientsided = true;
	else
		if data.Client then
			Clientsided = true;
		end;
		
		if data.Callback then
			Clientsided = false;
		end;
	end;
	

	-- Check if the provided player is a player instance.
	if player and typeof(player) == "Instance" and player:IsA("Player") then
		-- Check if the player is in the game.
		if player.Parent == game.Players then
			-- Fully clientsided, nothing else needed.
			if Clientsided then
				env.RemoteEvent:FireClient(player, "Notify", text, data);
				return;
			end;
			
			-- Otherwise, create a notification instance
			local notification = {};

			local UID;
			
			local success, fail = pcall(function()
				UID = env.RemoteFunction:InvokeClient(player, "Notify", text, data);
			end)
			if not success then
				table.insert(env.Data.Logs.Errors, {
					os.time(),
					"Failed to send notification to player " .. player.Name .. " with error: " .. fail
				});
				return fail;
			end

			activenotifications[UID] = {
				UID = UID; -- repetitive?
				Player = player,
				Text = text,
				Options = data.Options,
				Callback = data.Callback,
				Completed = false,
				SelectedOption = nil,
			};

			notification = activenotifications[UID];

			function notification:AwaitResponse(callback)
				-- Wait for the player to respond to the notification.
				activenotifications[UID].Callback = callback;

				repeat task.wait() until activenotifications[UID].Completed;
				return activenotifications[UID].SelectedOption;
			end

			function notification:Update(options)
				env.RemoteEvent:FireClient(player, "UpdateNotification", UID, options);
			end

			function notification:Destroy()
				-- Send a signal to the player to destroy the notification on their end.
				env.RemoteEvent:FireClient(player, "ClearNotification", UID);
				activenotifications[UID] = nil;
			end

			return notification;
		end
	end
end
