Decompiled source of OBSControl v1.1.2

Mods/OBSControl.dll

Decompiled a month ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BoneLib;
using BoneLib.BoneMenu;
using BoneLib.Notifications;
using MelonLoader;
using MelonLoader.Preferences;
using MelonLoader.Utils;
using Microsoft.CodeAnalysis;
using OBSWebsocketDotNet;
using OBSWebsocketDotNet.Types;
using OBSWebsocketDotNet.Types.Events;
using UnityEngine;
using UnityEngine.Diagnostics;
using WeatherElectric.OBSControl;
using WeatherElectric.OBSControl.Handlers;
using WeatherElectric.OBSControl.Melon;
using WeatherElectric.OBSControl.Menu;
using WeatherElectric.OBSControl.OBS;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Control OBS from within BONELAB.")]
[assembly: AssemblyDescription("Control OBS from within BONELAB.")]
[assembly: AssemblyCompany("Weather Electric")]
[assembly: AssemblyProduct("OBSControl")]
[assembly: AssemblyCopyright("Developed by SoulWithMae")]
[assembly: AssemblyTrademark("Weather Electric")]
[assembly: AssemblyFileVersion("1.1.2")]
[assembly: MelonInfo(typeof(Main), "OBSControl", "1.1.2", "SoulWithMae", "https://thunderstore.io/c/bonelab/p/SoulWithMae/OBSControl/")]
[assembly: MelonColor(255, 0, 0, 255)]
[assembly: MelonGame("Stress Level Zero", "BONELAB")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyVersion("1.1.2.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace WeatherElectric.OBSControl
{
	internal static class ControlHandler
	{
		private static bool _isFirstTap;

		private static float _doubleTapTimer;

		public static void Update()
		{
			switch (Preferences.ReplayControlHand.Value)
			{
			case ControlHand.Left:
				HandleLeft();
				break;
			case ControlHand.Right:
				HandleRight();
				break;
			case ControlHand.Both:
				HandleBoth();
				break;
			default:
				throw new ArgumentOutOfRangeException();
			}
			if (_isFirstTap)
			{
				_doubleTapTimer += Time.deltaTime;
				if (_doubleTapTimer > Preferences.DoubleTapTime.Value)
				{
					_isFirstTap = false;
				}
			}
			static void HandleBoth()
			{
				if (Player.RightController._menuTap || Player.LeftController._menuTap)
				{
					if (!_isFirstTap)
					{
						_isFirstTap = true;
						_doubleTapTimer = 0f;
					}
					else if (_doubleTapTimer < Preferences.DoubleTapTime.Value)
					{
						ObsBridge.SaveReplayBuffer();
						NotificationHandler.SendNotif(NotificationHandler.ReplaySaved);
						_isFirstTap = false;
					}
				}
			}
			static void HandleLeft()
			{
				if (Player.LeftController._menuTap)
				{
					if (!_isFirstTap)
					{
						_isFirstTap = true;
						_doubleTapTimer = 0f;
					}
					else if (_doubleTapTimer < Preferences.DoubleTapTime.Value)
					{
						ObsBridge.SaveReplayBuffer();
						NotificationHandler.SendNotif(NotificationHandler.ReplaySaved);
						_isFirstTap = false;
					}
				}
			}
			static void HandleRight()
			{
				if (Player.RightController._menuTap)
				{
					if (!_isFirstTap)
					{
						_isFirstTap = true;
						_doubleTapTimer = 0f;
					}
					else if (_doubleTapTimer < Preferences.DoubleTapTime.Value)
					{
						ObsBridge.SaveReplayBuffer();
						NotificationHandler.SendNotif(NotificationHandler.ReplaySaved);
						_isFirstTap = false;
					}
				}
			}
		}
	}
	public class Main : MelonMod
	{
		internal const string Name = "OBSControl";

		internal const string Description = "Control OBS from within BONELAB.";

		internal const string Author = "SoulWithMae";

		internal const string Company = "Weather Electric";

		internal const string Version = "1.1.2";

		internal const string DownloadLink = "https://thunderstore.io/c/bonelab/p/SoulWithMae/OBSControl/";

		private static bool _rigExists;

		public override void OnInitializeMelon()
		{
			ModConsole.Setup(((MelonBase)this).LoggerInstance);
			Preferences.Setup();
			Hooking.OnUIRigCreated += OnUIRigCreated;
			Hooking.OnLevelUnloaded += OnLevelUnloaded;
			BoneMenu.SetupBaseMenu();
		}

		public override void OnApplicationQuit()
		{
			ObsBridge.Disconnect();
		}

		public override void OnUpdate()
		{
			if (_rigExists && ObsBridge.IsConnected())
			{
				ControlHandler.Update();
			}
		}

		private static void OnUIRigCreated()
		{
			_rigExists = true;
			if (!ObsBridge.IsConnected())
			{
				ObsBridge.Connect();
				ObsBridge.InitHooks();
			}
		}

		private static void OnLevelUnloaded()
		{
			_rigExists = false;
		}
	}
}
namespace WeatherElectric.OBSControl.OBS
{
	public static class ObsBridge
	{
		private static readonly OBSWebsocket Obs = new OBSWebsocket();

		public static Action<object, RecordStateChangedEventArgs> OnRecordStateChanged;

		public static Action<object, ReplayBufferSavedEventArgs> OnReplayBufferSaved;

		public static Action<object, ReplayBufferStateChangedEventArgs> OnReplayBufferStateChanged;

		public static Action<object, StreamStateChangedEventArgs> OnStreamStateChanged;

		public static Action<object, ProgramSceneChangedEventArgs> OnSceneChanged;

		public static Action<object, SceneCreatedEventArgs> OnSceneCreated;

		public static Action<object, VirtualcamStateChangedEventArgs> OnVirtualCamStateChanged;

		public static Action<object, SceneRemovedEventArgs> OnSceneRemoved;

		private static void RecordStateChanged(object sender, RecordStateChangedEventArgs e)
		{
			OnRecordStateChanged?.Invoke(sender, e);
		}

		private static void ReplaySaved(object sender, ReplayBufferSavedEventArgs e)
		{
			OnReplayBufferSaved?.Invoke(sender, e);
		}

		private static void ReplayStateChanged(object sender, ReplayBufferStateChangedEventArgs e)
		{
			OnReplayBufferStateChanged?.Invoke(sender, e);
		}

		private static void StreamStateChanged(object sender, StreamStateChangedEventArgs e)
		{
			OnStreamStateChanged?.Invoke(sender, e);
		}

		private static void SceneChanged(object sender, ProgramSceneChangedEventArgs e)
		{
			OnSceneChanged?.Invoke(sender, e);
		}

		private static void VirtualCamStateChanged(object sender, VirtualcamStateChangedEventArgs e)
		{
			OnVirtualCamStateChanged?.Invoke(sender, e);
		}

		private static void SceneCreated(object sender, SceneCreatedEventArgs e)
		{
			OnSceneCreated?.Invoke(sender, e);
		}

		private static void SceneRemoved(object sender, SceneRemovedEventArgs e)
		{
		}

		internal static void Connect()
		{
			//IL_003a: Expected O, but got Unknown
			ModConsole.Msg("Attempting to connect to OBS...", 1);
			try
			{
				Obs.ConnectAsync(Preferences.WebsocketURL.Value, Preferences.WebsocketPassword.Value);
			}
			catch (AuthFailureException)
			{
				ModConsole.Error("Failed to authenticate with OBS. Check your password.");
			}
			catch (ErrorResponseException val2)
			{
				ErrorResponseException val3 = val2;
				ModConsole.Error("Failed to connect to OBS. Error: " + ((Exception)(object)val3).Message);
			}
			catch (Exception ex)
			{
				ModConsole.Error("Failed to connect to OBS. Error: " + ex.Message);
			}
			ModConsole.Msg("If you still aren't connected, it's likely the wrong password.", 1);
		}

		internal static void Disconnect()
		{
			ModConsole.Msg("Disconnecting from OBS...", 1);
			Obs.Disconnect();
		}

		internal static void InitHooks()
		{
			Obs.RecordStateChanged += RecordStateChanged;
			Obs.ReplayBufferSaved += ReplaySaved;
			Obs.ReplayBufferStateChanged += ReplayStateChanged;
			Obs.StreamStateChanged += StreamStateChanged;
			Obs.CurrentProgramSceneChanged += SceneChanged;
			Obs.VirtualcamStateChanged += VirtualCamStateChanged;
			Obs.SceneCreated += SceneCreated;
			Obs.SceneRemoved += SceneRemoved;
			Obs.Connected += ObsConnected;
		}

		private static void ObsConnected(object sender, EventArgs e)
		{
			ModConsole.Msg("OBS connected!", 1);
			BoneMenu.SetupObsControls();
		}

		public static List<SceneBasicInfo> GetScenes()
		{
			return Obs.GetSceneList().Scenes;
		}

		public static void SetScene(string sceneName)
		{
			Obs.SetCurrentProgramScene(sceneName);
		}

		public static bool IsConnected()
		{
			return Obs.IsConnected;
		}

		public static bool IsRecording()
		{
			return Obs.GetRecordStatus().IsRecording;
		}

		public static bool IsRecordingPaused()
		{
			return Obs.GetRecordStatus().IsRecordingPaused;
		}

		public static bool IsStreaming()
		{
			return Obs.GetStreamStatus().IsActive;
		}

		public static bool IsReplayBufferActive()
		{
			return Obs.GetReplayBufferStatus();
		}

		public static bool IsVirtualCamActive()
		{
			return Obs.GetVirtualCamStatus().IsActive;
		}

		public static void StartRecording()
		{
			//IL_0020: Expected O, but got Unknown
			if (IsRecording())
			{
				return;
			}
			ModConsole.Msg("Starting recording...", 1);
			try
			{
				Obs.StartRecord();
			}
			catch (ErrorResponseException val)
			{
				ErrorResponseException val2 = val;
				ModConsole.Error("Failed to start recording. Error: " + ((Exception)(object)val2).Message);
			}
			catch (Exception ex)
			{
				ModConsole.Error("Failed to start recording. Error: " + ex.Message);
			}
		}

		public static void PauseRecording()
		{
			//IL_0020: Expected O, but got Unknown
			if (IsRecordingPaused())
			{
				return;
			}
			ModConsole.Msg("Pausing recording...", 1);
			try
			{
				Obs.PauseRecord();
			}
			catch (ErrorResponseException val)
			{
				ErrorResponseException val2 = val;
				ModConsole.Error("Failed to pause recording. Error: " + ((Exception)(object)val2).Message);
			}
			catch (Exception ex)
			{
				ModConsole.Error("Failed to pause recording. Error: " + ex.Message);
			}
		}

		public static void ResumeRecording()
		{
			//IL_0020: Expected O, but got Unknown
			if (!IsRecordingPaused())
			{
				return;
			}
			ModConsole.Msg("Resuming recording...", 1);
			try
			{
				Obs.ResumeRecord();
			}
			catch (ErrorResponseException val)
			{
				ErrorResponseException val2 = val;
				ModConsole.Error("Failed to resume recording. Error: " + ((Exception)(object)val2).Message);
			}
			catch (Exception ex)
			{
				ModConsole.Error("Failed to resume recording. Error: " + ex.Message);
			}
		}

		public static void StopRecording()
		{
			//IL_0021: Expected O, but got Unknown
			if (!IsRecording())
			{
				return;
			}
			ModConsole.Msg("Stopping recording...", 1);
			try
			{
				Obs.StopRecord();
			}
			catch (ErrorResponseException val)
			{
				ErrorResponseException val2 = val;
				ModConsole.Error("Failed to stop recording. Error: " + ((Exception)(object)val2).Message);
			}
			catch (Exception ex)
			{
				ModConsole.Error("Failed to stop recording. Error: " + ex.Message);
			}
		}

		public static void StartStreaming()
		{
			//IL_0020: Expected O, but got Unknown
			if (IsStreaming())
			{
				return;
			}
			ModConsole.Msg("Starting stream...", 1);
			try
			{
				Obs.StartStream();
			}
			catch (ErrorResponseException val)
			{
				ErrorResponseException val2 = val;
				ModConsole.Error("Failed to start streaming. Error: " + ((Exception)(object)val2).Message);
			}
			catch (Exception ex)
			{
				ModConsole.Error("Failed to start streaming. Error: " + ex.Message);
			}
		}

		public static void StopStreaming()
		{
			//IL_0020: Expected O, but got Unknown
			if (!IsStreaming())
			{
				return;
			}
			ModConsole.Msg("Stopping stream...", 1);
			try
			{
				Obs.StopStream();
			}
			catch (ErrorResponseException val)
			{
				ErrorResponseException val2 = val;
				ModConsole.Error("Failed to stop streaming. Error: " + ((Exception)(object)val2).Message);
			}
			catch (Exception ex)
			{
				ModConsole.Error("Failed to stop streaming. Error: " + ex.Message);
			}
		}

		public static void StartReplayBuffer()
		{
			//IL_0020: Expected O, but got Unknown
			if (IsReplayBufferActive())
			{
				return;
			}
			ModConsole.Msg("Starting replay buffer...", 1);
			try
			{
				Obs.StartReplayBuffer();
			}
			catch (ErrorResponseException val)
			{
				ErrorResponseException val2 = val;
				ModConsole.Error("Failed to start replay buffer. Error: " + ((Exception)(object)val2).Message);
			}
			catch (Exception ex)
			{
				ModConsole.Error("Failed to start replay buffer. Error: " + ex.Message);
			}
		}

		public static void StopReplayBuffer()
		{
			//IL_0020: Expected O, but got Unknown
			if (!IsReplayBufferActive())
			{
				return;
			}
			ModConsole.Msg("Stopping replay buffer...", 1);
			try
			{
				Obs.StopReplayBuffer();
			}
			catch (ErrorResponseException val)
			{
				ErrorResponseException val2 = val;
				ModConsole.Error("Failed to stop replay buffer. Error: " + ((Exception)(object)val2).Message);
			}
			catch (Exception ex)
			{
				ModConsole.Error("Failed to stop replay buffer. Error: " + ex.Message);
			}
		}

		public static void SaveReplayBuffer()
		{
			//IL_0020: Expected O, but got Unknown
			if (!IsReplayBufferActive())
			{
				return;
			}
			ModConsole.Msg("Saving replay buffer...", 1);
			try
			{
				Obs.SaveReplayBuffer();
			}
			catch (ErrorResponseException val)
			{
				ErrorResponseException val2 = val;
				ModConsole.Error("Failed to save replay buffer. Error: " + ((Exception)(object)val2).Message);
			}
			catch (Exception ex)
			{
				ModConsole.Error("Failed to save replay buffer. Error: " + ex.Message);
			}
		}
	}
}
namespace WeatherElectric.OBSControl.Melon
{
	internal static class ModConsole
	{
		private static Instance _logger;

		public static void Setup(Instance loggerInstance)
		{
			_logger = loggerInstance;
		}

		public static void Msg(object obj, int loggingMode = 0)
		{
			string text = ((loggingMode == 1) ? $"[DEBUG] {obj}" : obj.ToString());
			ConsoleColor consoleColor = ((loggingMode == 1) ? ConsoleColor.Yellow : ConsoleColor.Gray);
			if (Preferences.LoggingMode.Value >= loggingMode)
			{
				_logger.Msg(consoleColor, text);
			}
		}

		public static void Msg(string txt, int loggingMode = 0)
		{
			string text = ((loggingMode == 1) ? ("[DEBUG] " + txt) : txt);
			ConsoleColor consoleColor = ((loggingMode == 1) ? ConsoleColor.Yellow : ConsoleColor.Gray);
			if (Preferences.LoggingMode.Value >= loggingMode)
			{
				_logger.Msg(consoleColor, text);
			}
		}

		public static void Msg(ConsoleColor txtcolor, object obj, int loggingMode = 0)
		{
			string text = ((loggingMode == 1) ? $"[DEBUG] {obj}" : obj.ToString());
			if (Preferences.LoggingMode.Value >= loggingMode)
			{
				_logger.Msg(txtcolor, text);
			}
		}

		public static void Msg(ConsoleColor txtcolor, string txt, int loggingMode = 0)
		{
			string text = ((loggingMode == 1) ? ("[DEBUG] " + txt) : txt);
			if (Preferences.LoggingMode.Value >= loggingMode)
			{
				_logger.Msg(txtcolor, text);
			}
		}

		public static void Msg(string txt, int loggingMode = 0, params object[] args)
		{
			string text = ((loggingMode == 1) ? ("[DEBUG] " + txt) : txt);
			ConsoleColor consoleColor = ((loggingMode == 1) ? ConsoleColor.Yellow : ConsoleColor.Gray);
			if (Preferences.LoggingMode.Value >= loggingMode)
			{
				_logger.Msg(consoleColor, text, args);
			}
		}

		public static void Msg(ConsoleColor txtcolor, string txt, int loggingMode = 0, params object[] args)
		{
			string text = ((loggingMode == 1) ? ("[DEBUG] " + txt) : txt);
			if (Preferences.LoggingMode.Value >= loggingMode)
			{
				_logger.Msg(txtcolor, text, args);
			}
		}

		public static void Error(object obj, int loggingMode = 0)
		{
			string text = ((loggingMode == 1) ? $"[DEBUG] {obj}" : obj.ToString());
			if (Preferences.LoggingMode.Value >= loggingMode)
			{
				_logger.Error(text);
			}
		}

		public static void Error(string txt, int loggingMode = 0)
		{
			string text = ((loggingMode == 1) ? ("[DEBUG] " + txt) : txt);
			if (Preferences.LoggingMode.Value >= loggingMode)
			{
				_logger.Error(text);
			}
		}

		public static void Error(string txt, int loggingMode = 0, params object[] args)
		{
			string text = ((loggingMode == 1) ? ("[DEBUG] " + txt) : txt);
			if (Preferences.LoggingMode.Value >= loggingMode)
			{
				_logger.Error(text, args);
			}
		}

		public static void Warning(object obj, int loggingMode = 0)
		{
			string text = ((loggingMode == 1) ? $"[DEBUG] {obj}" : obj.ToString());
			if (Preferences.LoggingMode.Value >= loggingMode)
			{
				_logger.Warning(text);
			}
		}

		public static void Warning(string txt, int loggingMode = 0)
		{
			string text = ((loggingMode == 1) ? ("[DEBUG] " + txt) : txt);
			if (Preferences.LoggingMode.Value >= loggingMode)
			{
				_logger.Warning(text);
			}
		}

		public static void Warning(string txt, int loggingMode = 0, params object[] args)
		{
			string text = ((loggingMode == 1) ? ("[DEBUG] " + txt) : txt);
			if (Preferences.LoggingMode.Value >= loggingMode)
			{
				_logger.Warning(text, args);
			}
		}
	}
	internal static class Preferences
	{
		public static readonly MelonPreferences_Category GlobalCategory = MelonPreferences.CreateCategory("Global");

		public static readonly MelonPreferences_Category OwnCategory = MelonPreferences.CreateCategory("OBSControl");

		public static MelonPreferences_Entry<int> LoggingMode { get; set; }

		public static MelonPreferences_Entry<bool> ShowNotifications { get; set; }

		public static MelonPreferences_Entry<string> WebsocketURL { get; set; }

		public static MelonPreferences_Entry<string> WebsocketPassword { get; set; }

		public static MelonPreferences_Entry<ControlHand> ReplayControlHand { get; set; }

		public static MelonPreferences_Entry<float> DoubleTapTime { get; set; }

		public static void Setup()
		{
			LoggingMode = GlobalCategory.GetEntry<int>("LoggingMode") ?? GlobalCategory.CreateEntry<int>("LoggingMode", 0, "Logging Mode", "The level of logging to use. 0 = Important Only, 1 = All", false, false, (ValueValidator)null, (string)null);
			GlobalCategory.SetFilePath(MelonEnvironment.UserDataDirectory + "/WeatherElectric.cfg");
			GlobalCategory.SaveToFile(false);
			ShowNotifications = OwnCategory.CreateEntry<bool>("ShowNotifications", true, "Show Notifications", "Whether to show notifications when OBS events occur.", false, false, (ValueValidator)null, (string)null);
			WebsocketURL = OwnCategory.CreateEntry<string>("WebsocketURL", "ws://127.0.0.1:4455", "Websocket URL", "The URL to use for the websocket connection. Usually don't have to change this.", false, false, (ValueValidator)null, (string)null);
			WebsocketPassword = OwnCategory.CreateEntry<string>("WebsocketPassword", "REPLACEME", "Websocket Password", "The password to use for the websocket connection. Change this to the password you set in OBS.", false, false, (ValueValidator)null, (string)null);
			ReplayControlHand = OwnCategory.CreateEntry<ControlHand>("ReplayControlHand", ControlHand.Right, "Replay Control Hand", "The hand to use for saving replays. Left = Left hand, Right = Right hand, Both = Both hands.", false, false, (ValueValidator)null, (string)null);
			DoubleTapTime = OwnCategory.CreateEntry<float>("DoubleTapTime", 0.3f, "Double Tap Time", "The time to wait between taps to trigger saving a replay.", false, false, (ValueValidator)null, (string)null);
			OwnCategory.SetFilePath(MelonEnvironment.UserDataDirectory + "/WeatherElectric.cfg");
			OwnCategory.SaveToFile(false);
			ModConsole.Msg("Finished preferences setup for OBSControl", 1);
		}
	}
	internal enum ControlHand
	{
		Left,
		Right,
		Both
	}
}
namespace WeatherElectric.OBSControl.Handlers
{
	internal static class NotificationHandler
	{
		public static Notification SceneChanged { get; } = new Notification
		{
			Title = NotificationText.op_Implicit("Scene Changed"),
			Message = NotificationText.op_Implicit("Scene has been changed."),
			Type = (NotificationType)0,
			PopupLength = 1f,
			ShowTitleOnPopup = true
		};


		public static Notification RecordingStarted { get; } = new Notification
		{
			Title = NotificationText.op_Implicit("Recording Started"),
			Message = NotificationText.op_Implicit("Recording has started."),
			Type = (NotificationType)0,
			PopupLength = 1f,
			ShowTitleOnPopup = true
		};


		public static Notification RecordingStopped { get; } = new Notification
		{
			Title = NotificationText.op_Implicit("Recording Stopped"),
			Message = NotificationText.op_Implicit("Recording has stopped."),
			Type = (NotificationType)0,
			PopupLength = 1f,
			ShowTitleOnPopup = true
		};


		public static Notification RecordingPaused { get; } = new Notification
		{
			Title = NotificationText.op_Implicit("Recording Paused"),
			Message = NotificationText.op_Implicit("Recording has been paused."),
			Type = (NotificationType)0,
			PopupLength = 1f,
			ShowTitleOnPopup = true
		};


		public static Notification RecordingResumed { get; } = new Notification
		{
			Title = NotificationText.op_Implicit("Recording Resumed"),
			Message = NotificationText.op_Implicit("Recording has been resumed."),
			Type = (NotificationType)0,
			PopupLength = 1f,
			ShowTitleOnPopup = true
		};


		public static Notification StreamStarted { get; } = new Notification
		{
			Title = NotificationText.op_Implicit("Stream Started"),
			Message = NotificationText.op_Implicit("Stream has started."),
			Type = (NotificationType)0,
			PopupLength = 1f,
			ShowTitleOnPopup = true
		};


		public static Notification StreamStopped { get; } = new Notification
		{
			Title = NotificationText.op_Implicit("Stream Stopped"),
			Message = NotificationText.op_Implicit("Stream has stopped."),
			Type = (NotificationType)0,
			PopupLength = 1f,
			ShowTitleOnPopup = true
		};


		public static Notification ReplayBufferStarted { get; } = new Notification
		{
			Title = NotificationText.op_Implicit("Replay Buffer Started"),
			Message = NotificationText.op_Implicit("Replay buffer has started."),
			Type = (NotificationType)0,
			PopupLength = 1f,
			ShowTitleOnPopup = true
		};


		public static Notification ReplayBufferStopped { get; } = new Notification
		{
			Title = NotificationText.op_Implicit("Replay Buffer Stopped"),
			Message = NotificationText.op_Implicit("Replay buffer has stopped."),
			Type = (NotificationType)0,
			PopupLength = 1f,
			ShowTitleOnPopup = true
		};


		public static Notification ReplaySaved { get; } = new Notification
		{
			Title = NotificationText.op_Implicit("Replay Saved"),
			Message = NotificationText.op_Implicit("Replay has been saved."),
			Type = (NotificationType)0,
			PopupLength = 1f,
			ShowTitleOnPopup = true
		};


		public static void SendNotif(Notification notification)
		{
			if (Preferences.ShowNotifications.Value)
			{
				Notifier.Send(notification);
			}
		}
	}
}
namespace WeatherElectric.OBSControl.Menu
{
	internal static class BoneMenu
	{
		private static Page _subCat;

		private static FunctionElement _recordButton;

		private static FunctionElement _pauseButton;

		private static FunctionElement _streamButton;

		private static FunctionElement _replayButton;

		private static FunctionElement _connectButton;

		private static Page _scenesPanel;

		private static readonly List<FunctionElement> SceneButtons = new List<FunctionElement>();

		public static void SetupBaseMenu()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			_subCat = Page.Root.CreatePage("<color=#6FBDFF>Weather Electric</color>", Color.cyan, 0, true).CreatePage("<color=#284cb8>OBSControl</color>", Color.white, 0, true);
			_connectButton = _subCat.CreateFunction("If you see this, it failed to connect.", Color.red, (Action)delegate
			{
				Utils.ForceCrash((ForcedCrashCategory)0);
			});
		}

		public static void SetupObsControls()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Unknown result type (might be due to invalid IL or missing references)
			//IL_023e: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0298: Unknown result type (might be due to invalid IL or missing references)
			_subCat.Remove((Element)(object)_connectButton);
			Page obj = _subCat.CreatePage("Record", Color.green, 0, true);
			_recordButton = obj.CreateFunction("Record Button", Color.green, (Action)delegate
			{
				if (ObsBridge.IsRecording())
				{
					ObsBridge.StopRecording();
					NotificationHandler.SendNotif(NotificationHandler.RecordingStopped);
				}
				else
				{
					ObsBridge.StartRecording();
					NotificationHandler.SendNotif(NotificationHandler.RecordingStarted);
				}
			});
			SetRecordButton(ObsBridge.IsRecording());
			_pauseButton = obj.CreateFunction("Pause Button", Color.yellow, (Action)delegate
			{
				if (ObsBridge.IsRecordingPaused())
				{
					ObsBridge.ResumeRecording();
					NotificationHandler.SendNotif(NotificationHandler.RecordingResumed);
				}
				else
				{
					ObsBridge.PauseRecording();
					NotificationHandler.SendNotif(NotificationHandler.RecordingPaused);
				}
			});
			SetPauseButton(ObsBridge.IsRecordingPaused());
			_streamButton = _subCat.CreatePage("Stream", Color.blue, 0, true).CreateFunction("Stream Button", Color.blue, (Action)delegate
			{
				if (ObsBridge.IsStreaming())
				{
					ObsBridge.StopStreaming();
					NotificationHandler.SendNotif(NotificationHandler.StreamStopped);
				}
				else
				{
					ObsBridge.StartStreaming();
					NotificationHandler.SendNotif(NotificationHandler.StreamStarted);
				}
			});
			SetStreamButton(ObsBridge.IsStreaming());
			Page obj2 = _subCat.CreatePage("Replay", Color.yellow, 0, true);
			_replayButton = obj2.CreateFunction("Replay Button", Color.blue, (Action)delegate
			{
				if (ObsBridge.IsReplayBufferActive())
				{
					ObsBridge.StopReplayBuffer();
					NotificationHandler.SendNotif(NotificationHandler.ReplayBufferStopped);
				}
				else
				{
					ObsBridge.StartReplayBuffer();
					NotificationHandler.SendNotif(NotificationHandler.ReplayBufferStarted);
				}
			});
			SetReplayButton(ObsBridge.IsReplayBufferActive());
			obj2.CreateFunction("Save Replay", Color.blue, (Action)delegate
			{
				ObsBridge.SaveReplayBuffer();
				NotificationHandler.SendNotif(NotificationHandler.ReplaySaved);
			});
			_scenesPanel = _subCat.CreatePage("Scenes", Color.red, 0, true);
			List<SceneBasicInfo> scenes = ObsBridge.GetScenes();
			ModConsole.Msg("Finding scenes", 1);
			foreach (SceneBasicInfo scene in scenes)
			{
				ModConsole.Msg("Found scene: " + scene.Name, 1);
				FunctionElement item = _scenesPanel.CreateFunction(scene.Name, Color.white, (Action)delegate
				{
					//IL_002a: Unknown result type (might be due to invalid IL or missing references)
					//IL_002f: Unknown result type (might be due to invalid IL or missing references)
					ObsBridge.SetScene(scene.Name);
					NotificationHandler.SceneChanged.Message = NotificationText.op_Implicit("Scene changed to " + scene.Name);
					NotificationHandler.SendNotif(NotificationHandler.SceneChanged);
				});
				SceneButtons.Add(item);
			}
			Page obj3 = _subCat.CreatePage("Settings", Color.gray, 0, true);
			obj3.CreateBoolPreference("Show Notifications", Color.white, Preferences.ShowNotifications, Preferences.OwnCategory);
			obj3.CreateEnum("Replay Control Hand", Color.white, (Enum)Preferences.ReplayControlHand.Value, (Action<Enum>)delegate(Enum v)
			{
				Preferences.ReplayControlHand.Value = (ControlHand)(object)v;
				Preferences.OwnCategory.SaveToFile(false);
			});
			obj3.CreateFloatPreference("Double Tap Time", Color.white, 0.1f, 0.1f, 1f, Preferences.DoubleTapTime, Preferences.OwnCategory);
			ConnectHooks();
		}

		private static void ConnectHooks()
		{
			ObsBridge.OnRecordStateChanged = (Action<object, RecordStateChangedEventArgs>)Delegate.Combine(ObsBridge.OnRecordStateChanged, new Action<object, RecordStateChangedEventArgs>(RecordStatusChanged));
			ObsBridge.OnStreamStateChanged = (Action<object, StreamStateChangedEventArgs>)Delegate.Combine(ObsBridge.OnStreamStateChanged, new Action<object, StreamStateChangedEventArgs>(StreamStatusChanged));
			ObsBridge.OnReplayBufferStateChanged = (Action<object, ReplayBufferStateChangedEventArgs>)Delegate.Combine(ObsBridge.OnReplayBufferStateChanged, new Action<object, ReplayBufferStateChangedEventArgs>(ReplayStatusChanged));
			ObsBridge.OnSceneCreated = (Action<object, SceneCreatedEventArgs>)Delegate.Combine(ObsBridge.OnSceneCreated, new Action<object, SceneCreatedEventArgs>(SceneCreated));
			ObsBridge.OnSceneRemoved = (Action<object, SceneRemovedEventArgs>)Delegate.Combine(ObsBridge.OnSceneRemoved, new Action<object, SceneRemovedEventArgs>(SceneDeleted));
		}

		private static void RecordStatusChanged(object sender, RecordStateChangedEventArgs e)
		{
			SetRecordButton(((OutputStateChanged)e.OutputState).IsActive);
		}

		private static void StreamStatusChanged(object sender, StreamStateChangedEventArgs e)
		{
			SetStreamButton(e.OutputState.IsActive);
		}

		private static void ReplayStatusChanged(object sender, ReplayBufferStateChangedEventArgs e)
		{
			SetReplayButton(e.OutputState.IsActive);
		}

		private static void SceneCreated(object sender, SceneCreatedEventArgs e)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			ModConsole.Msg("Scene created: " + e.SceneName, 1);
			FunctionElement item = _scenesPanel.CreateFunction(e.SceneName, Color.white, (Action)delegate
			{
				ObsBridge.SetScene(e.SceneName);
			});
			SceneButtons.Add(item);
		}

		private static void SceneDeleted(object sender, SceneRemovedEventArgs e)
		{
			ModConsole.Msg("Scene deleted: " + e.SceneName, 1);
			using IEnumerator<FunctionElement> enumerator = SceneButtons.Where((FunctionElement button) => ((Element)button).ElementName == e.SceneName).GetEnumerator();
			if (enumerator.MoveNext())
			{
				FunctionElement current = enumerator.Current;
				_scenesPanel.Remove((Element)(object)current);
				SceneButtons.Remove(current);
			}
		}

		private static void SetRecordButton(bool isRecording)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			if (isRecording)
			{
				((Element)_recordButton).ElementColor = Color.red;
				((Element)_recordButton).ElementName = "Stop Recording";
			}
			else
			{
				((Element)_recordButton).ElementColor = Color.green;
				((Element)_recordButton).ElementName = "Start Recording";
			}
		}

		private static void SetPauseButton(bool isPaused)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			if (isPaused)
			{
				((Element)_pauseButton).ElementColor = Color.white;
				((Element)_pauseButton).ElementName = "Resume Recording";
			}
			else
			{
				((Element)_pauseButton).ElementColor = Color.yellow;
				((Element)_pauseButton).ElementName = "Pause Recording";
			}
		}

		private static void SetStreamButton(bool isStreaming)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			if (isStreaming)
			{
				((Element)_streamButton).ElementColor = Color.red;
				((Element)_streamButton).ElementName = "Stop Streaming";
			}
			else
			{
				((Element)_streamButton).ElementColor = Color.green;
				((Element)_streamButton).ElementName = "Start Streaming";
			}
		}

		private static void SetReplayButton(bool isReplayActive)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			if (isReplayActive)
			{
				((Element)_replayButton).ElementColor = Color.red;
				((Element)_replayButton).ElementName = "Stop Replay Buffer";
			}
			else
			{
				((Element)_replayButton).ElementColor = Color.green;
				((Element)_replayButton).ElementName = "Start Replay Buffer";
			}
		}
	}
	internal static class BoneMenuExtensions
	{
		public static BoolElement CreateBoolPreference(this Page category, string name, Color color, MelonPreferences_Entry<bool> pref, MelonPreferences_Category prefCategory, bool autoSave = true)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			return category.CreateBool(name, color, pref.Value, (Action<bool>)delegate(bool v)
			{
				pref.Value = v;
				if (autoSave)
				{
					prefCategory.SaveToFile(false);
				}
			});
		}

		public static FloatElement CreateFloatPreference(this Page category, string name, Color color, float increment, float min, float max, MelonPreferences_Entry<float> pref, MelonPreferences_Category prefCategory, bool autoSave = true)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			return category.CreateFloat(name, color, pref.Value, increment, min, max, (Action<float>)delegate(float v)
			{
				pref.Value = v;
				if (autoSave)
				{
					prefCategory.SaveToFile(false);
				}
			});
		}

		public static IntElement CreateIntPreference(this Page category, string name, Color color, int increment, int min, int max, MelonPreferences_Entry<int> pref, MelonPreferences_Category prefCategory, bool autoSave = true)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			return category.CreateInt(name, color, pref.Value, increment, min, max, (Action<int>)delegate(int v)
			{
				pref.Value = v;
				if (autoSave)
				{
					prefCategory.SaveToFile(false);
				}
			});
		}

		public static EnumElement CreateEnumPreference(this Page category, string name, Color color, Enum pref, MelonPreferences_Category prefCategory, bool autoSave = true)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			return category.CreateEnum(name, color, pref, (Action<Enum>)delegate(Enum v)
			{
				pref = v;
				if (autoSave)
				{
					prefCategory.SaveToFile(false);
				}
			});
		}
	}
}

UserLibs/obs-websocket-dotnet.dll

Decompiled a month ago
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net.WebSockets;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using OBSWebsocketDotNet.Communication;
using OBSWebsocketDotNet.Types;
using OBSWebsocketDotNet.Types.Events;
using Websocket.Client;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("BarRaider")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright © BarRaider 2022")]
[assembly: AssemblyDescription("Official obs-websocket .NET library. Written in C#. Supports .NET Standard")]
[assembly: AssemblyFileVersion("5.0.0.3")]
[assembly: AssemblyInformationalVersion("5.0.0.3")]
[assembly: AssemblyProduct("obs-websocket-dotnet")]
[assembly: AssemblyTitle("obs-websocket-dotnet")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/BarRaider/obs-websocket-dotnet")]
[assembly: AssemblyVersion("5.0.0.3")]
namespace OBSWebsocketDotNet
{
	public class OBSWebsocket : IOBSWebsocket
	{
		private delegate void RequestCallback(OBSWebsocket sender, JObject body);

		private const string WEBSOCKET_URL_PREFIX = "ws://";

		private const int SUPPORTED_RPC_VERSION = 1;

		private TimeSpan wsTimeout = TimeSpan.FromSeconds(10.0);

		private string connectionPassword;

		private WebsocketClient wsConnection;

		private readonly ConcurrentDictionary<string, TaskCompletionSource<JObject>> responseHandlers;

		private static readonly Random random = new Random();

		private const string REQUEST_FIELD_VOLUME_DB = "inputVolumeDb";

		private const string REQUEST_FIELD_VOLUME_MUL = "inputVolumeMul";

		private const string RESPONSE_FIELD_IMAGE_DATA = "imageData";

		public TimeSpan WSTimeout
		{
			get
			{
				WebsocketClient obj = wsConnection;
				return ((obj != null) ? obj.ReconnectTimeout : null) ?? wsTimeout;
			}
			set
			{
				wsTimeout = value;
				if (wsConnection != null)
				{
					wsConnection.ReconnectTimeout = wsTimeout;
				}
			}
		}

		public bool IsConnected
		{
			get
			{
				if (wsConnection != null)
				{
					return wsConnection.IsRunning;
				}
				return false;
			}
		}

		public event EventHandler<ProgramSceneChangedEventArgs> CurrentProgramSceneChanged;

		public event EventHandler<SceneListChangedEventArgs> SceneListChanged;

		public event EventHandler<SceneItemListReindexedEventArgs> SceneItemListReindexed;

		public event EventHandler<SceneItemCreatedEventArgs> SceneItemCreated;

		public event EventHandler<SceneItemRemovedEventArgs> SceneItemRemoved;

		public event EventHandler<SceneItemEnableStateChangedEventArgs> SceneItemEnableStateChanged;

		public event EventHandler<SceneItemLockStateChangedEventArgs> SceneItemLockStateChanged;

		public event EventHandler<CurrentSceneCollectionChangedEventArgs> CurrentSceneCollectionChanged;

		public event EventHandler<SceneCollectionListChangedEventArgs> SceneCollectionListChanged;

		public event EventHandler<CurrentSceneTransitionChangedEventArgs> CurrentSceneTransitionChanged;

		public event EventHandler<CurrentSceneTransitionDurationChangedEventArgs> CurrentSceneTransitionDurationChanged;

		public event EventHandler<SceneTransitionStartedEventArgs> SceneTransitionStarted;

		public event EventHandler<SceneTransitionEndedEventArgs> SceneTransitionEnded;

		public event EventHandler<SceneTransitionVideoEndedEventArgs> SceneTransitionVideoEnded;

		public event EventHandler<CurrentProfileChangedEventArgs> CurrentProfileChanged;

		public event EventHandler<ProfileListChangedEventArgs> ProfileListChanged;

		public event EventHandler<StreamStateChangedEventArgs> StreamStateChanged;

		public event EventHandler<RecordStateChangedEventArgs> RecordStateChanged;

		public event EventHandler<ReplayBufferStateChangedEventArgs> ReplayBufferStateChanged;

		public event EventHandler<CurrentPreviewSceneChangedEventArgs> CurrentPreviewSceneChanged;

		public event EventHandler<StudioModeStateChangedEventArgs> StudioModeStateChanged;

		public event EventHandler ExitStarted;

		public event EventHandler Connected;

		public event EventHandler<ObsDisconnectionInfo> Disconnected;

		public event EventHandler<SceneItemSelectedEventArgs> SceneItemSelected;

		public event EventHandler<SceneItemTransformEventArgs> SceneItemTransformChanged;

		public event EventHandler<InputAudioSyncOffsetChangedEventArgs> InputAudioSyncOffsetChanged;

		public event EventHandler<SourceFilterCreatedEventArgs> SourceFilterCreated;

		public event EventHandler<SourceFilterRemovedEventArgs> SourceFilterRemoved;

		public event EventHandler<SourceFilterListReindexedEventArgs> SourceFilterListReindexed;

		public event EventHandler<SourceFilterEnableStateChangedEventArgs> SourceFilterEnableStateChanged;

		public event EventHandler<InputMuteStateChangedEventArgs> InputMuteStateChanged;

		public event EventHandler<InputVolumeChangedEventArgs> InputVolumeChanged;

		public event EventHandler<VendorEventArgs> VendorEvent;

		public event EventHandler<MediaInputPlaybackEndedEventArgs> MediaInputPlaybackEnded;

		public event EventHandler<MediaInputPlaybackStartedEventArgs> MediaInputPlaybackStarted;

		public event EventHandler<MediaInputActionTriggeredEventArgs> MediaInputActionTriggered;

		public event EventHandler<VirtualcamStateChangedEventArgs> VirtualcamStateChanged;

		public event EventHandler<CurrentSceneCollectionChangingEventArgs> CurrentSceneCollectionChanging;

		public event EventHandler<CurrentProfileChangingEventArgs> CurrentProfileChanging;

		public event EventHandler<SourceFilterNameChangedEventArgs> SourceFilterNameChanged;

		public event EventHandler<InputCreatedEventArgs> InputCreated;

		public event EventHandler<InputRemovedEventArgs> InputRemoved;

		public event EventHandler<InputNameChangedEventArgs> InputNameChanged;

		public event EventHandler<InputActiveStateChangedEventArgs> InputActiveStateChanged;

		public event EventHandler<InputShowStateChangedEventArgs> InputShowStateChanged;

		public event EventHandler<InputAudioBalanceChangedEventArgs> InputAudioBalanceChanged;

		public event EventHandler<InputAudioTracksChangedEventArgs> InputAudioTracksChanged;

		public event EventHandler<InputAudioMonitorTypeChangedEventArgs> InputAudioMonitorTypeChanged;

		public event EventHandler<InputVolumeMetersEventArgs> InputVolumeMeters;

		public event EventHandler<ReplayBufferSavedEventArgs> ReplayBufferSaved;

		public event EventHandler<SceneCreatedEventArgs> SceneCreated;

		public event EventHandler<SceneRemovedEventArgs> SceneRemoved;

		public event EventHandler<SceneNameChangedEventArgs> SceneNameChanged;

		protected void ProcessEventType(string eventType, JObject body)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			//IL_10d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_10db: Expected O, but got Unknown
			//IL_0ce3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0cf3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0cfd: Expected O, but got Unknown
			//IL_0cfd: Expected O, but got Unknown
			//IL_0f86: Unknown result type (might be due to invalid IL or missing references)
			//IL_0f96: Unknown result type (might be due to invalid IL or missing references)
			//IL_0fa0: Expected O, but got Unknown
			//IL_0fa0: Expected O, but got Unknown
			//IL_0bec: Unknown result type (might be due to invalid IL or missing references)
			//IL_0bf6: Expected O, but got Unknown
			body = (JObject)body["eventData"];
			switch (eventType)
			{
			case "CurrentProgramSceneChanged":
				this.CurrentProgramSceneChanged?.Invoke(this, new ProgramSceneChangedEventArgs((string)body["sceneName"]));
				break;
			case "SceneListChanged":
				this.SceneListChanged?.Invoke(this, new SceneListChangedEventArgs(JsonConvert.DeserializeObject<List<JObject>>((string)body["scenes"])));
				break;
			case "SceneItemListReindexed":
				this.SceneItemListReindexed?.Invoke(this, new SceneItemListReindexedEventArgs((string)body["sceneName"], JsonConvert.DeserializeObject<List<JObject>>((string)body["sceneItems"])));
				break;
			case "SceneItemCreated":
				this.SceneItemCreated?.Invoke(this, new SceneItemCreatedEventArgs((string)body["sceneName"], (string)body["sourceName"], (int)body["sceneItemId"], (int)body["sceneItemIndex"]));
				break;
			case "SceneItemRemoved":
				this.SceneItemRemoved?.Invoke(this, new SceneItemRemovedEventArgs((string)body["sceneName"], (string)body["sourceName"], (int)body["sceneItemId"]));
				break;
			case "SceneItemEnableStateChanged":
				this.SceneItemEnableStateChanged?.Invoke(this, new SceneItemEnableStateChangedEventArgs((string)body["sceneName"], (int)body["sceneItemId"], (bool)body["sceneItemEnabled"]));
				break;
			case "SceneItemLockStateChanged":
				this.SceneItemLockStateChanged?.Invoke(this, new SceneItemLockStateChangedEventArgs((string)body["sceneName"], (int)body["sceneItemId"], (bool)body["sceneItemLocked"]));
				break;
			case "CurrentSceneCollectionChanged":
				this.CurrentSceneCollectionChanged?.Invoke(this, new CurrentSceneCollectionChangedEventArgs((string)body["sceneCollectionName"]));
				break;
			case "SceneCollectionListChanged":
				this.SceneCollectionListChanged?.Invoke(this, new SceneCollectionListChangedEventArgs(JsonConvert.DeserializeObject<List<string>>((string)body["sceneCollections"])));
				break;
			case "CurrentSceneTransitionChanged":
				this.CurrentSceneTransitionChanged?.Invoke(this, new CurrentSceneTransitionChangedEventArgs((string)body["transitionName"]));
				break;
			case "CurrentSceneTransitionDurationChanged":
				this.CurrentSceneTransitionDurationChanged?.Invoke(this, new CurrentSceneTransitionDurationChangedEventArgs((int)body["transitionDuration"]));
				break;
			case "SceneTransitionStarted":
				this.SceneTransitionStarted?.Invoke(this, new SceneTransitionStartedEventArgs((string)body["transitionName"]));
				break;
			case "SceneTransitionEnded":
				this.SceneTransitionEnded?.Invoke(this, new SceneTransitionEndedEventArgs((string)body["transitionName"]));
				break;
			case "SceneTransitionVideoEnded":
				this.SceneTransitionVideoEnded?.Invoke(this, new SceneTransitionVideoEndedEventArgs((string)body["transitionName"]));
				break;
			case "CurrentProfileChanged":
				this.CurrentProfileChanged?.Invoke(this, new CurrentProfileChangedEventArgs((string)body["profileName"]));
				break;
			case "ProfileListChanged":
				this.ProfileListChanged?.Invoke(this, new ProfileListChangedEventArgs(JsonConvert.DeserializeObject<List<string>>((string)body["profiles"])));
				break;
			case "StreamStateChanged":
				this.StreamStateChanged?.Invoke(this, new StreamStateChangedEventArgs(new OutputStateChanged(body)));
				break;
			case "RecordStateChanged":
				this.RecordStateChanged?.Invoke(this, new RecordStateChangedEventArgs(new RecordStateChanged(body)));
				break;
			case "CurrentPreviewSceneChanged":
				this.CurrentPreviewSceneChanged?.Invoke(this, new CurrentPreviewSceneChangedEventArgs((string)body["sceneName"]));
				break;
			case "StudioModeStateChanged":
				this.StudioModeStateChanged?.Invoke(this, new StudioModeStateChangedEventArgs((bool)body["studioModeEnabled"]));
				break;
			case "ReplayBufferStateChanged":
				this.ReplayBufferStateChanged?.Invoke(this, new ReplayBufferStateChangedEventArgs(new OutputStateChanged(body)));
				break;
			case "ExitStarted":
				this.ExitStarted?.Invoke(this, EventArgs.Empty);
				break;
			case "SceneItemSelected":
				this.SceneItemSelected?.Invoke(this, new SceneItemSelectedEventArgs((string)body["sceneName"], (string)body["sceneItemId"]));
				break;
			case "SceneItemTransformChanged":
				this.SceneItemTransformChanged?.Invoke(this, new SceneItemTransformEventArgs((string)body["sceneName"], (string)body["sceneItemId"], new SceneItemTransformInfo((JObject)body["sceneItemTransform"])));
				break;
			case "InputAudioSyncOffsetChanged":
				this.InputAudioSyncOffsetChanged?.Invoke(this, new InputAudioSyncOffsetChangedEventArgs((string)body["inputName"], (int)body["inputAudioSyncOffset"]));
				break;
			case "InputMuteStateChanged":
				this.InputMuteStateChanged?.Invoke(this, new InputMuteStateChangedEventArgs((string)body["inputName"], (bool)body["inputMuted"]));
				break;
			case "InputVolumeChanged":
				this.InputVolumeChanged?.Invoke(this, new InputVolumeChangedEventArgs(new InputVolume(body)));
				break;
			case "SourceFilterCreated":
				this.SourceFilterCreated?.Invoke(this, new SourceFilterCreatedEventArgs((string)body["sourceName"], (string)body["filterName"], (string)body["filterKind"], (int)body["filterIndex"], (JObject)body["filterSettings"], (JObject)body["defaultFilterSettings"]));
				break;
			case "SourceFilterRemoved":
				this.SourceFilterRemoved?.Invoke(this, new SourceFilterRemovedEventArgs((string)body["sourceName"], (string)body["filterName"]));
				break;
			case "SourceFilterListReindexed":
				if (this.SourceFilterListReindexed != null)
				{
					List<FilterReorderItem> list = new List<FilterReorderItem>();
					JsonConvert.PopulateObject(((object)body["filters"]).ToString(), (object)list);
					this.SourceFilterListReindexed?.Invoke(this, new SourceFilterListReindexedEventArgs((string)body["sourceName"], list));
				}
				break;
			case "SourceFilterEnableStateChanged":
				this.SourceFilterEnableStateChanged?.Invoke(this, new SourceFilterEnableStateChangedEventArgs((string)body["sourceName"], (string)body["filterName"], (bool)body["filterEnabled"]));
				break;
			case "VendorEvent":
				this.VendorEvent?.Invoke(this, new VendorEventArgs((string)body["vendorName"], (string)body["eventType"], body));
				break;
			case "MediaInputPlaybackEnded":
				this.MediaInputPlaybackEnded?.Invoke(this, new MediaInputPlaybackEndedEventArgs((string)body["inputName"]));
				break;
			case "MediaInputPlaybackStarted":
				this.MediaInputPlaybackStarted?.Invoke(this, new MediaInputPlaybackStartedEventArgs((string)body["sourceName"]));
				break;
			case "MediaInputActionTriggered":
				this.MediaInputActionTriggered?.Invoke(this, new MediaInputActionTriggeredEventArgs((string)body["inputName"], (string)body["mediaAction"]));
				break;
			case "VirtualcamStateChanged":
				this.VirtualcamStateChanged?.Invoke(this, new VirtualcamStateChangedEventArgs(new OutputStateChanged(body)));
				break;
			case "CurrentSceneCollectionChanging":
				this.CurrentSceneCollectionChanging?.Invoke(this, new CurrentSceneCollectionChangingEventArgs((string)body["sceneCollectionName"]));
				break;
			case "CurrentProfileChanging":
				this.CurrentProfileChanging?.Invoke(this, new CurrentProfileChangingEventArgs((string)body["profileName"]));
				break;
			case "SourceFilterNameChanged":
				this.SourceFilterNameChanged?.Invoke(this, new SourceFilterNameChangedEventArgs((string)body["sourceName"], (string)body["oldFilterName"], (string)body["filterName"]));
				break;
			case "InputCreated":
				this.InputCreated?.Invoke(this, new InputCreatedEventArgs((string)body["inputName"], (string)body["inputKind"], (string)body["unversionedInputKind"], (JObject)body["inputSettings"], (JObject)body["defaultInputSettings"]));
				break;
			case "InputRemoved":
				this.InputRemoved?.Invoke(this, new InputRemovedEventArgs((string)body["inputName"]));
				break;
			case "InputNameChanged":
				this.InputNameChanged?.Invoke(this, new InputNameChangedEventArgs((string)body["oldInputName"], (string)body["inputName"]));
				break;
			case "InputActiveStateChanged":
				this.InputActiveStateChanged?.Invoke(this, new InputActiveStateChangedEventArgs((string)body["inputName"], (bool)body["videoActive"]));
				break;
			case "InputShowStateChanged":
				this.InputShowStateChanged?.Invoke(this, new InputShowStateChangedEventArgs((string)body["inputName"], (bool)body["videoShowing"]));
				break;
			case "InputAudioBalanceChanged":
				this.InputAudioBalanceChanged?.Invoke(this, new InputAudioBalanceChangedEventArgs((string)body["inputName"], (double)body["inputAudioBalance"]));
				break;
			case "InputAudioTracksChanged":
				this.InputAudioTracksChanged?.Invoke(this, new InputAudioTracksChangedEventArgs((string)body["inputName"], (JObject)body["inputAudioTracks"]));
				break;
			case "InputAudioMonitorTypeChanged":
				this.InputAudioMonitorTypeChanged?.Invoke(this, new InputAudioMonitorTypeChangedEventArgs((string)body["inputName"], (string)body["monitorType"]));
				break;
			case "InputVolumeMeters":
				this.InputVolumeMeters?.Invoke(this, new InputVolumeMetersEventArgs(JsonConvert.DeserializeObject<List<JObject>>((string)body["inputs"])));
				break;
			case "ReplayBufferSaved":
				this.ReplayBufferSaved?.Invoke(this, new ReplayBufferSavedEventArgs((string)body["savedReplayPath"]));
				break;
			case "SceneCreated":
				this.SceneCreated?.Invoke(this, new SceneCreatedEventArgs((string)body["sceneName"], (bool)body["isGroup"]));
				break;
			case "SceneRemoved":
				this.SceneRemoved?.Invoke(this, new SceneRemovedEventArgs((string)body["sceneName"], (bool)body["isGroup"]));
				break;
			case "SceneNameChanged":
				this.SceneNameChanged?.Invoke(this, new SceneNameChangedEventArgs((string)body["oldSceneName"], (string)body["sceneName"]));
				break;
			default:
				Console.WriteLine($"Unsupported Event: {eventType}\n{body}");
				break;
			}
		}

		public OBSWebsocket()
		{
			responseHandlers = new ConcurrentDictionary<string, TaskCompletionSource<JObject>>();
		}

		[Obsolete("Please use ConnectAsync, this function will be removed in the next version")]
		public void Connect(string url, string password)
		{
			ConnectAsync(url, password);
		}

		public void ConnectAsync(string url, string password)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			if (!url.ToLower().StartsWith("ws://"))
			{
				throw new ArgumentException("Invalid url, must start with 'ws://'");
			}
			if (wsConnection != null && wsConnection.IsRunning)
			{
				Disconnect();
			}
			wsConnection = new WebsocketClient(new Uri(url), (Func<ClientWebSocket>)null);
			wsConnection.IsReconnectionEnabled = false;
			wsConnection.ReconnectTimeout = null;
			wsConnection.ErrorReconnectTimeout = null;
			ObservableExtensions.Subscribe<ResponseMessage>(wsConnection.MessageReceived, (Action<ResponseMessage>)delegate(ResponseMessage m)
			{
				Task.Run(delegate
				{
					WebsocketMessageHandler(this, m);
				});
			});
			ObservableExtensions.Subscribe<DisconnectionInfo>(wsConnection.DisconnectionHappened, (Action<DisconnectionInfo>)delegate(DisconnectionInfo d)
			{
				Task.Run(delegate
				{
					OnWebsocketDisconnect(this, d);
				});
			});
			connectionPassword = password;
			wsConnection.StartOrFail();
		}

		public void Disconnect()
		{
			connectionPassword = null;
			if (wsConnection != null)
			{
				try
				{
					wsConnection.Stop(WebSocketCloseStatus.NormalClosure, "User requested disconnect");
					((IDisposable)wsConnection).Dispose();
				}
				catch
				{
				}
				wsConnection = null;
			}
			KeyValuePair<string, TaskCompletionSource<JObject>>[] array = responseHandlers.ToArray();
			responseHandlers.Clear();
			KeyValuePair<string, TaskCompletionSource<JObject>>[] array2 = array;
			foreach (KeyValuePair<string, TaskCompletionSource<JObject>> keyValuePair in array2)
			{
				keyValuePair.Value.TrySetCanceled();
			}
		}

		private void OnWebsocketDisconnect(object sender, DisconnectionInfo d)
		{
			if (d == null || !d.CloseStatus.HasValue)
			{
				this.Disconnected?.Invoke(sender, new ObsDisconnectionInfo(ObsCloseCodes.UnknownReason, null, d));
			}
			else
			{
				this.Disconnected?.Invoke(sender, new ObsDisconnectionInfo((ObsCloseCodes)d.CloseStatus.Value, d.CloseStatusDescription, d));
			}
		}

		private void WebsocketMessageHandler(object sender, ResponseMessage e)
		{
			if (e.MessageType != 0)
			{
				return;
			}
			ServerMessage serverMessage = JsonConvert.DeserializeObject<ServerMessage>(e.Text);
			JObject body = serverMessage.Data;
			switch (serverMessage.OperationCode)
			{
			case MessageTypes.Hello:
				HandleHello(body);
				break;
			case MessageTypes.Identified:
				Task.Run(delegate
				{
					this.Connected?.Invoke(this, EventArgs.Empty);
				});
				break;
			case MessageTypes.RequestResponse:
			case MessageTypes.RequestBatchResponse:
				if (body.ContainsKey("requestId"))
				{
					string key = (string)body["requestId"];
					if (responseHandlers.TryRemove(key, out var value))
					{
						value.SetResult(body);
					}
				}
				break;
			case MessageTypes.Event:
			{
				string eventType = ((object)body["eventType"]).ToString();
				Task.Run(delegate
				{
					ProcessEventType(eventType, body);
				});
				break;
			}
			}
		}

		public JObject SendRequest(string requestType, JObject additionalFields = null)
		{
			return SendRequest(MessageTypes.Request, requestType, additionalFields);
		}

		internal JObject SendRequest(MessageTypes operationCode, string requestType, JObject additionalFields = null, bool waitForReply = true)
		{
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Expected O, but got Unknown
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Expected O, but got Unknown
			if (wsConnection == null)
			{
				throw new NullReferenceException("Websocket is not initialized");
			}
			TaskCompletionSource<JObject> taskCompletionSource = new TaskCompletionSource<JObject>();
			JObject val = null;
			string messageId;
			do
			{
				val = MessageFactory.BuildMessage(operationCode, requestType, additionalFields, out messageId);
			}
			while (waitForReply && !responseHandlers.TryAdd(messageId, taskCompletionSource));
			wsConnection.Send(((object)val).ToString());
			if (!waitForReply)
			{
				return null;
			}
			taskCompletionSource.Task.Wait(wsTimeout.Milliseconds);
			if (taskCompletionSource.Task.IsCanceled)
			{
				throw new ErrorResponseException("Request canceled", 0);
			}
			JObject result = taskCompletionSource.Task.Result;
			if (!(bool)result["requestStatus"][(object)"result"])
			{
				JObject val2 = (JObject)result["requestStatus"];
				throw new ErrorResponseException(string.Format("ErrorCode: {0}{1}", val2["code"], val2.ContainsKey("comment") ? string.Format(", Comment: {0}", val2["comment"]) : ""), (int)val2["code"]);
			}
			if (result.ContainsKey("responseData"))
			{
				return result["responseData"].ToObject<JObject>();
			}
			return new JObject();
		}

		public OBSAuthInfo GetAuthInfo()
		{
			return new OBSAuthInfo(SendRequest("GetAuthRequired"));
		}

		protected void SendIdentify(string password, OBSAuthInfo authInfo = null)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("rpcVersion", JToken.op_Implicit(1));
			JObject val2 = val;
			if (authInfo != null)
			{
				string text = HashEncode(password + authInfo.PasswordSalt);
				string text2 = HashEncode(text + authInfo.Challenge);
				val2.Add("authentication", JToken.op_Implicit(text2));
			}
			SendRequest(MessageTypes.Identify, null, val2, waitForReply: false);
		}

		protected string HashEncode(string input)
		{
			using SHA256Managed sHA256Managed = new SHA256Managed();
			byte[] bytes = Encoding.ASCII.GetBytes(input);
			return Convert.ToBase64String(sHA256Managed.ComputeHash(bytes));
		}

		protected string NewMessageID(int length = 16)
		{
			string text = "";
			for (int i = 0; i < length; i++)
			{
				int index = random.Next(0, "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".Length - 1);
				text += "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[index];
			}
			return text;
		}

		private void HandleHello(JObject payload)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			if (wsConnection.IsStarted)
			{
				OBSAuthInfo authInfo = null;
				if (payload.ContainsKey("authentication"))
				{
					authInfo = new OBSAuthInfo((JObject)payload["authentication"]);
				}
				SendIdentify(connectionPassword, authInfo);
				connectionPassword = null;
			}
		}

		public ObsVideoSettings GetVideoSettings()
		{
			return JsonConvert.DeserializeObject<ObsVideoSettings>(((object)SendRequest("GetVideoSettings")).ToString());
		}

		public string SaveSourceScreenshot(string sourceName, string imageFormat, string imageFilePath, int imageWidth = -1, int imageHeight = -1, int imageCompressionQuality = -1)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("sourceName", JToken.op_Implicit(sourceName));
			val.Add("imageFormat", JToken.op_Implicit(imageFormat));
			val.Add("imageFilePath", JToken.op_Implicit(imageFilePath));
			JObject val2 = val;
			if (imageWidth > -1)
			{
				val2.Add("imageWidth", JToken.op_Implicit(imageWidth));
			}
			if (imageHeight > -1)
			{
				val2.Add("imageHeight", JToken.op_Implicit(imageHeight));
			}
			if (imageCompressionQuality > -1)
			{
				val2.Add("imageCompressionQuality", JToken.op_Implicit(imageCompressionQuality));
			}
			return (string)SendRequest("SaveSourceScreenshot", val2)["imageData"];
		}

		public string SaveSourceScreenshot(string sourceName, string imageFormat, string imageFilePath)
		{
			return SaveSourceScreenshot(sourceName, imageFormat, imageFilePath, -1, -1, -1);
		}

		public void TriggerHotkeyByName(string hotkeyName)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("hotkeyName", JToken.op_Implicit(hotkeyName));
			JObject additionalFields = val;
			SendRequest("TriggerHotkeyByName", additionalFields);
		}

		public void TriggerHotkeyByKeySequence(OBSHotkey keyId, KeyModifier keyModifier = KeyModifier.None)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Expected O, but got Unknown
			//IL_008b: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("keyId", JToken.op_Implicit(keyId.ToString()));
			JObject val2 = new JObject();
			val2.Add("shift", JToken.op_Implicit((keyModifier & KeyModifier.Shift) == KeyModifier.Shift));
			val2.Add("alt", JToken.op_Implicit((keyModifier & KeyModifier.Alt) == KeyModifier.Alt));
			val2.Add("control", JToken.op_Implicit((keyModifier & KeyModifier.Control) == KeyModifier.Control));
			val2.Add("command", JToken.op_Implicit((keyModifier & KeyModifier.Command) == KeyModifier.Command));
			val.Add("keyModifiers", (JToken)val2);
			JObject additionalFields = val;
			SendRequest("TriggerHotkeyByKeySequence", additionalFields);
		}

		public string GetCurrentProgramScene()
		{
			return (string)SendRequest("GetCurrentProgramScene")["currentProgramSceneName"];
		}

		public void SetCurrentProgramScene(string sceneName)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("sceneName", JToken.op_Implicit(sceneName));
			JObject additionalFields = val;
			SendRequest("SetCurrentProgramScene", additionalFields);
		}

		public ObsStats GetStats()
		{
			return JsonConvert.DeserializeObject<ObsStats>(((object)SendRequest("GetStats")).ToString());
		}

		public List<SceneBasicInfo> ListScenes()
		{
			return GetSceneList().Scenes;
		}

		public GetSceneListInfo GetSceneList()
		{
			return JsonConvert.DeserializeObject<GetSceneListInfo>(((object)SendRequest("GetSceneList")).ToString());
		}

		public TransitionOverrideInfo GetSceneSceneTransitionOverride(string sceneName)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("sceneName", JToken.op_Implicit(sceneName));
			JObject additionalFields = val;
			return ((JToken)SendRequest("GetSceneSceneTransitionOverride", additionalFields)).ToObject<TransitionOverrideInfo>();
		}

		public void SetSceneSceneTransitionOverride(string sceneName, string transitionName, int transitionDuration = -1)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("sceneName", JToken.op_Implicit(sceneName));
			val.Add("transitionName", JToken.op_Implicit(transitionName));
			JObject val2 = val;
			if (transitionDuration >= 0)
			{
				val2.Add("transitionDuration", JToken.op_Implicit(transitionDuration));
			}
			SendRequest("SetSceneSceneTransitionOverride", val2);
		}

		public void SetTBarPosition(double position, bool release = true)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Expected O, but got Unknown
			if (position < 0.0 || position > 1.0)
			{
				throw new ArgumentOutOfRangeException("position");
			}
			JObject val = new JObject();
			val.Add("position", JToken.op_Implicit(position));
			val.Add("release", JToken.op_Implicit(release));
			JObject additionalFields = val;
			SendRequest("SetTBarPosition", additionalFields);
		}

		public void SetSourceFilterSettings(string sourceName, string filterName, JObject filterSettings, bool overlay = false)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("sourceName", JToken.op_Implicit(sourceName));
			val.Add("filterName", JToken.op_Implicit(filterName));
			val.Add("filterSettings", (JToken)(object)filterSettings);
			val.Add("overlay", JToken.op_Implicit(overlay));
			JObject additionalFields = val;
			SendRequest("SetSourceFilterSettings", additionalFields);
		}

		public void SetSourceFilterSettings(string sourceName, string filterName, FilterSettings filterSettings, bool overlay = false)
		{
			SetSourceFilterSettings(sourceName, filterName, JObject.FromObject((object)filterSettings), overlay);
		}

		public void SetSourceFilterEnabled(string sourceName, string filterName, bool filterEnabled)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("sourceName", JToken.op_Implicit(sourceName));
			val.Add("filterName", JToken.op_Implicit(filterName));
			val.Add("filterEnabled", JToken.op_Implicit(filterEnabled));
			JObject additionalFields = val;
			SendRequest("SetSourceFilterEnabled", additionalFields);
		}

		public List<FilterSettings> GetSourceFilterList(string sourceName)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("sourceName", JToken.op_Implicit(sourceName));
			JObject additionalFields = val;
			JObject val2 = SendRequest("GetSourceFilterList", additionalFields);
			if (!((JToken)val2).HasValues)
			{
				return new List<FilterSettings>();
			}
			return JsonConvert.DeserializeObject<List<FilterSettings>>(((object)val2["filters"]).ToString());
		}

		public FilterSettings GetSourceFilter(string sourceName, string filterName)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("sourceName", JToken.op_Implicit(sourceName));
			val.Add("filterName", JToken.op_Implicit(filterName));
			JObject additionalFields = val;
			return JsonConvert.DeserializeObject<FilterSettings>(((object)SendRequest("GetSourceFilter", additionalFields)).ToString());
		}

		public bool RemoveSourceFilter(string sourceName, string filterName)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("sourceName", JToken.op_Implicit(sourceName));
			val.Add("filterName", JToken.op_Implicit(filterName));
			JObject additionalFields = val;
			try
			{
				SendRequest("RemoveSourceFilter", additionalFields);
				return true;
			}
			catch (Exception ex)
			{
				Console.WriteLine(ex.Message);
			}
			return false;
		}

		public void CreateSourceFilter(string sourceName, string filterName, string filterKind, JObject filterSettings)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("sourceName", JToken.op_Implicit(sourceName));
			val.Add("filterName", JToken.op_Implicit(filterName));
			val.Add("filterKind", JToken.op_Implicit(filterKind));
			val.Add("filterSettings", (JToken)(object)filterSettings);
			JObject additionalFields = val;
			SendRequest("CreateSourceFilter", additionalFields);
		}

		public void CreateSourceFilter(string sourceName, string filterName, string filterKind, FilterSettings filterSettings)
		{
			CreateSourceFilter(sourceName, filterName, filterKind, JObject.FromObject((object)filterSettings));
		}

		public bool ToggleStream()
		{
			return (bool)SendRequest("ToggleStream")["outputActive"];
		}

		public void ToggleRecord()
		{
			SendRequest("ToggleRecord");
		}

		public OutputStatus GetStreamStatus()
		{
			return new OutputStatus(SendRequest("GetStreamStatus"));
		}

		public TransitionSettings GetCurrentSceneTransition()
		{
			return new TransitionSettings(SendRequest("GetCurrentSceneTransition"));
		}

		public void SetCurrentSceneTransition(string transitionName)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("transitionName", JToken.op_Implicit(transitionName));
			JObject additionalFields = val;
			SendRequest("SetCurrentSceneTransition", additionalFields);
		}

		public void SetCurrentSceneTransitionDuration(int transitionDuration)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("transitionDuration", JToken.op_Implicit(transitionDuration));
			JObject additionalFields = val;
			SendRequest("SetCurrentSceneTransitionDuration", additionalFields);
		}

		public void SetCurrentSceneTransitionSettings(JObject transitionSettings, bool overlay)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("transitionSettings", JToken.FromObject((object)transitionSettings));
			val.Add("overlay", JToken.op_Implicit(overlay));
			JObject additionalFields = val;
			SendRequest("SetCurrentSceneTransitionSettings", additionalFields);
		}

		public void SetInputVolume(string inputName, float inputVolume, bool inputVolumeDb = false)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("inputName", JToken.op_Implicit(inputName));
			JObject val2 = val;
			if (inputVolumeDb)
			{
				val2.Add("inputVolumeDb", JToken.op_Implicit(inputVolume));
			}
			else
			{
				val2.Add("inputVolumeMul", JToken.op_Implicit(inputVolume));
			}
			SendRequest("SetInputVolume", val2);
		}

		public VolumeInfo GetInputVolume(string inputName)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("inputName", JToken.op_Implicit(inputName));
			JObject additionalFields = val;
			return new VolumeInfo(SendRequest("GetInputVolume", additionalFields));
		}

		public bool GetInputMute(string inputName)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("inputName", JToken.op_Implicit(inputName));
			JObject additionalFields = val;
			return (bool)SendRequest("GetInputMute", additionalFields)["inputMuted"];
		}

		public void SetInputMute(string inputName, bool inputMuted)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("inputName", JToken.op_Implicit(inputName));
			val.Add("inputMuted", JToken.op_Implicit(inputMuted));
			JObject additionalFields = val;
			SendRequest("SetInputMute", additionalFields);
		}

		public void ToggleInputMute(string inputName)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("inputName", JToken.op_Implicit(inputName));
			JObject additionalFields = val;
			SendRequest("ToggleInputMute", additionalFields);
		}

		public void SetSceneItemTransform(string sceneName, int sceneItemId, JObject sceneItemTransform)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("sceneName", JToken.op_Implicit(sceneName));
			val.Add("sceneItemId", JToken.op_Implicit(sceneItemId));
			val.Add("sceneItemTransform", (JToken)(object)sceneItemTransform);
			JObject additionalFields = val;
			SendRequest("SetSceneItemTransform", additionalFields);
		}

		public void SetSceneItemTransform(string sceneName, int sceneItemId, SceneItemTransformInfo sceneItemTransform)
		{
			SetSceneItemTransform(sceneName, sceneItemId, JObject.FromObject((object)sceneItemTransform));
		}

		public void SetCurrentSceneCollection(string sceneCollectionName)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("sceneCollectionName", JToken.op_Implicit(sceneCollectionName));
			JObject additionalFields = val;
			SendRequest("SetCurrentSceneCollection", additionalFields);
		}

		public string GetCurrentSceneCollection()
		{
			return (string)SendRequest("GetSceneCollectionList")["currentSceneCollectionName"];
		}

		public List<string> GetSceneCollectionList()
		{
			return JsonConvert.DeserializeObject<List<string>>(((object)SendRequest("GetSceneCollectionList")["sceneCollections"]).ToString());
		}

		public void SetCurrentProfile(string profileName)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("profileName", JToken.op_Implicit(profileName));
			JObject additionalFields = val;
			SendRequest("SetCurrentProfile", additionalFields);
		}

		public GetProfileListInfo GetProfileList()
		{
			return JsonConvert.DeserializeObject<GetProfileListInfo>(((object)SendRequest("GetProfileList")).ToString());
		}

		public void StartStream()
		{
			SendRequest("StartStream");
		}

		public void StopStream()
		{
			SendRequest("StopStream");
		}

		public void StartRecord()
		{
			SendRequest("StartRecord");
		}

		public string StopRecord()
		{
			return (string)SendRequest("StopRecord")["outputPath"];
		}

		public void PauseRecord()
		{
			SendRequest("PauseRecord");
		}

		public void ResumeRecord()
		{
			SendRequest("ResumeRecord");
		}

		public string GetRecordDirectory()
		{
			return (string)SendRequest("GetRecordDirectory")["recordDirectory"];
		}

		public RecordingStatus GetRecordStatus()
		{
			return JsonConvert.DeserializeObject<RecordingStatus>(((object)SendRequest("GetRecordStatus")).ToString());
		}

		public bool GetReplayBufferStatus()
		{
			return (bool)SendRequest("GetReplayBufferStatus")["outputActive"];
		}

		public GetTransitionListInfo GetSceneTransitionList()
		{
			return JsonConvert.DeserializeObject<GetTransitionListInfo>(((object)SendRequest("GetSceneTransitionList")).ToString());
		}

		public bool GetStudioModeEnabled()
		{
			return (bool)SendRequest("GetStudioModeEnabled")["studioModeEnabled"];
		}

		public void SetStudioModeEnabled(bool studioModeEnabled)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("studioModeEnabled", JToken.op_Implicit(studioModeEnabled));
			JObject additionalFields = val;
			SendRequest("SetStudioModeEnabled", additionalFields);
		}

		public string GetCurrentPreviewScene()
		{
			return (string)SendRequest("GetCurrentPreviewScene")["currentPreviewSceneName"];
		}

		public void SetCurrentPreviewScene(string sceneName)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("sceneName", JToken.op_Implicit(sceneName));
			JObject additionalFields = val;
			SendRequest("SetCurrentPreviewScene", additionalFields);
		}

		public void SetCurrentPreviewScene(ObsScene previewScene)
		{
			SetCurrentPreviewScene(previewScene.Name);
		}

		public void TriggerStudioModeTransition()
		{
			SendRequest("TriggerStudioModeTransition");
		}

		public void ToggleReplayBuffer()
		{
			SendRequest("ToggleReplayBuffer");
		}

		public void StartReplayBuffer()
		{
			SendRequest("StartReplayBuffer");
		}

		public void StopReplayBuffer()
		{
			SendRequest("StopReplayBuffer");
		}

		public void SaveReplayBuffer()
		{
			SendRequest("SaveReplayBuffer");
		}

		public void SetInputAudioSyncOffset(string inputName, int inputAudioSyncOffset)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("inputName", JToken.op_Implicit(inputName));
			val.Add("inputAudioSyncOffset", JToken.op_Implicit(inputAudioSyncOffset));
			JObject additionalFields = val;
			SendRequest("SetInputAudioSyncOffset", additionalFields);
		}

		public int GetInputAudioSyncOffset(string inputName)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("inputName", JToken.op_Implicit(inputName));
			JObject additionalFields = val;
			return (int)SendRequest("GetInputAudioSyncOffset", additionalFields)["inputAudioSyncOffset"];
		}

		public void RemoveSceneItem(string sceneName, int sceneItemId)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("sceneName", JToken.op_Implicit(sceneName));
			val.Add("sceneItemId", JToken.op_Implicit(sceneItemId));
			JObject additionalFields = val;
			SendRequest("RemoveSceneItem", additionalFields);
		}

		public void SendStreamCaption(string captionText)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("captionText", JToken.op_Implicit(captionText));
			JObject additionalFields = val;
			SendRequest("SendStreamCaption", additionalFields);
		}

		public void DuplicateSceneItem(string sceneName, int sceneItemId, string destinationSceneName = null)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("sceneName", JToken.op_Implicit(sceneName));
			val.Add("sceneItemId", JToken.op_Implicit(sceneItemId));
			JObject val2 = val;
			if (!string.IsNullOrEmpty(destinationSceneName))
			{
				val2.Add("destinationSceneName", JToken.op_Implicit(destinationSceneName));
			}
			SendRequest("DuplicateSceneItem", val2);
		}

		public Dictionary<string, string> GetSpecialInputs()
		{
			JObject obj = SendRequest("GetSpecialInputs");
			Dictionary<string, string> dictionary = new Dictionary<string, string>();
			foreach (KeyValuePair<string, JToken> item in obj)
			{
				string key = item.Key;
				string value = (string)item.Value;
				if (key != "requestType")
				{
					dictionary.Add(key, value);
				}
			}
			return dictionary;
		}

		public void SetStreamServiceSettings(StreamingService service)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("streamServiceType", JToken.op_Implicit(service.Type));
			val.Add("streamServiceSettings", JToken.FromObject((object)service.Settings));
			JObject additionalFields = val;
			SendRequest("SetStreamServiceSettings", additionalFields);
		}

		public StreamingService GetStreamServiceSettings()
		{
			return JsonConvert.DeserializeObject<StreamingService>(((object)SendRequest("GetStreamServiceSettings")).ToString());
		}

		public string GetInputAudioMonitorType(string inputName)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("inputName", JToken.op_Implicit(inputName));
			JObject additionalFields = val;
			return (string)SendRequest("GetInputAudioMonitorType", additionalFields)["monitorType"];
		}

		public void SetInputAudioMonitorType(string inputName, string monitorType)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("inputName", JToken.op_Implicit(inputName));
			val.Add("monitorType", JToken.op_Implicit(monitorType));
			JObject additionalFields = val;
			SendRequest("SetInputAudioMonitorType", additionalFields);
		}

		public void BroadcastCustomEvent(JObject eventData)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("eventData", (JToken)(object)eventData);
			JObject additionalFields = val;
			SendRequest("BroadcastCustomEvent", additionalFields);
		}

		public void SetMediaInputCursor(string inputName, int mediaCursor)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("inputName", JToken.op_Implicit(inputName));
			val.Add("mediaCursor", JToken.op_Implicit(mediaCursor));
			JObject additionalFields = val;
			SendRequest("SetMediaInputCursor", additionalFields);
		}

		public void OffsetMediaInputCursor(string inputName, int mediaCursorOffset)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("inputName", JToken.op_Implicit(inputName));
			val.Add("mediaCursorOffset", JToken.op_Implicit(mediaCursorOffset));
			JObject additionalFields = val;
			SendRequest("OffsetMediaInputCursor", additionalFields);
		}

		public int CreateInput(string sceneName, string inputName, string inputKind, JObject inputSettings, bool? sceneItemEnabled)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("sceneName", JToken.op_Implicit(sceneName));
			val.Add("inputName", JToken.op_Implicit(inputName));
			val.Add("inputKind", JToken.op_Implicit(inputKind));
			JObject val2 = val;
			if (inputSettings != null)
			{
				val2.Add("inputSettings", (JToken)(object)inputSettings);
			}
			if (sceneItemEnabled.HasValue)
			{
				val2.Add("sceneItemEnabled", JToken.op_Implicit(sceneItemEnabled.Value));
			}
			return (int)SendRequest("CreateInput", val2)["sceneItemId"];
		}

		public JObject GetInputDefaultSettings(string inputKind)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("inputKind", JToken.op_Implicit(inputKind));
			JObject additionalFields = val;
			return (JObject)SendRequest("GetInputDefaultSettings", additionalFields)["defaultInputSettings"];
		}

		public List<SceneItemDetails> GetSceneItemList(string sceneName)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			JObject additionalFields = null;
			if (!string.IsNullOrEmpty(sceneName))
			{
				JObject val = new JObject();
				val.Add("sceneName", JToken.op_Implicit(sceneName));
				additionalFields = val;
			}
			return ((IEnumerable<JToken>)SendRequest("GetSceneItemList", additionalFields)["sceneItems"]).Select((JToken m) => new SceneItemDetails((JObject)m)).ToList();
		}

		public int CreateSceneItem(string sceneName, string sourceName, bool sceneItemEnabled = true)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("sceneName", JToken.op_Implicit(sceneName));
			val.Add("sourceName", JToken.op_Implicit(sourceName));
			val.Add("sceneItemEnabled", JToken.op_Implicit(sceneItemEnabled));
			JObject additionalFields = val;
			return (int)SendRequest("CreateSceneItem", additionalFields)["sceneItemId"];
		}

		public void CreateScene(string sceneName)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("sceneName", JToken.op_Implicit(sceneName));
			JObject additionalFields = val;
			SendRequest("CreateScene", additionalFields);
		}

		public SourceTracks GetInputAudioTracks(string inputName)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("inputName", JToken.op_Implicit(inputName));
			JObject additionalFields = val;
			return new SourceTracks(SendRequest("GetInputAudioTracks", additionalFields));
		}

		public void SetInputAudioTracks(string inputName, JObject inputAudioTracks)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("inputName", JToken.op_Implicit(inputName));
			val.Add("inputAudioTracks", (JToken)(object)inputAudioTracks);
			JObject additionalFields = val;
			SendRequest("SetInputAudioTracks", additionalFields);
		}

		public void SetInputAudioTracks(string inputName, SourceTracks inputAudioTracks)
		{
			SetInputAudioTracks(inputName, JObject.FromObject((object)inputAudioTracks));
		}

		public SourceActiveInfo GetSourceActive(string sourceName)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("sourceName", JToken.op_Implicit(sourceName));
			JObject additionalFields = val;
			return new SourceActiveInfo(SendRequest("GetSourceActive", additionalFields));
		}

		public VirtualCamStatus GetVirtualCamStatus()
		{
			return new VirtualCamStatus(SendRequest("GetVirtualCamStatus"));
		}

		public void StartVirtualCam()
		{
			SendRequest("StartVirtualCam");
		}

		public void StopVirtualCam()
		{
			SendRequest("StopVirtualCam");
		}

		public VirtualCamStatus ToggleVirtualCam()
		{
			return new VirtualCamStatus(SendRequest("ToggleVirtualCam"));
		}

		public JObject GetPersistentData(string realm, string slotName)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("realm", JToken.op_Implicit(realm));
			val.Add("slotName", JToken.op_Implicit(slotName));
			JObject additionalFields = val;
			return SendRequest("GetPersistentData", additionalFields);
		}

		public void SetPersistentData(string realm, string slotName, JObject slotValue)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("realm", JToken.op_Implicit(realm));
			val.Add("slotName", JToken.op_Implicit(slotName));
			val.Add("slotValue", (JToken)(object)slotValue);
			JObject additionalFields = val;
			SendRequest("SetPersistentData", additionalFields);
		}

		public void CreateSceneCollection(string sceneCollectionName)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("sceneCollectionName", JToken.op_Implicit(sceneCollectionName));
			JObject additionalFields = val;
			SendRequest("CreateSceneCollection", additionalFields);
		}

		public void CreateProfile(string profileName)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("profileName", JToken.op_Implicit(profileName));
			JObject additionalFields = val;
			SendRequest("CreateProfile", additionalFields);
		}

		public void RemoveProfile(string profileName)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("profileName", JToken.op_Implicit(profileName));
			JObject additionalFields = val;
			SendRequest("RemoveProfile", additionalFields);
		}

		public JObject GetProfileParameter(string parameterCategory, string parameterName)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("parameterCategory", JToken.op_Implicit(parameterCategory));
			val.Add("parameterName", JToken.op_Implicit(parameterName));
			JObject additionalFields = val;
			return SendRequest("GetProfileParameter", additionalFields);
		}

		public void SetProfileParameter(string parameterCategory, string parameterName, string parameterValue)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("parameterCategory", JToken.op_Implicit(parameterCategory));
			val.Add("parameterName", JToken.op_Implicit(parameterName));
			val.Add("parameterValue", JToken.op_Implicit(parameterValue));
			JObject additionalFields = val;
			SendRequest("SetProfileParameter", additionalFields);
		}

		public void SetVideoSettings(ObsVideoSettings obsVideoSettings)
		{
			SendRequest("SetVideoSettings", JObject.FromObject((object)obsVideoSettings));
		}

		public JObject GetSourceFilterDefaultSettings(string filterKind)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("filterKind", JToken.op_Implicit(filterKind));
			JObject additionalFields = val;
			return SendRequest("GetSourceFilterDefaultSettings", additionalFields);
		}

		public void SetSourceFilterName(string sourceName, string filterName, string newFilterName)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("sourceName", JToken.op_Implicit(sourceName));
			val.Add("filterName", JToken.op_Implicit(filterName));
			val.Add("newFilterName", JToken.op_Implicit(newFilterName));
			JObject additionalFields = val;
			SendRequest("SetSourceFilterName", additionalFields);
		}

		public void SetSourceFilterIndex(string sourceName, string filterName, int filterIndex)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("sourceName", JToken.op_Implicit(sourceName));
			val.Add("filterName", JToken.op_Implicit(filterName));
			val.Add("filterIndex", JToken.op_Implicit(filterIndex));
			JObject additionalFields = val;
			SendRequest("SetSourceFilterIndex", additionalFields);
		}

		public ObsVersion GetVersion()
		{
			return new ObsVersion(SendRequest("GetVersion"));
		}

		public JObject CallVendorRequest(string vendorName, string requestType, JObject requestData = null)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("vendorName", JToken.op_Implicit(vendorName));
			val.Add("requestType", JToken.op_Implicit(requestType));
			val.Add("requestData", (JToken)(object)requestData);
			JObject additionalFields = val;
			return SendRequest("CallVendorRequest", additionalFields);
		}

		public List<string> GetHotkeyList()
		{
			return JsonConvert.DeserializeObject<List<string>>(((object)SendRequest("GetHotkeyList")["hotkeys"]).ToString());
		}

		public void Sleep(int sleepMillis, int sleepFrames)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("sleepMillis", JToken.op_Implicit(sleepMillis));
			val.Add("sleepFrames", JToken.op_Implicit(sleepFrames));
			JObject additionalFields = val;
			SendRequest("Sleep", additionalFields);
		}

		public List<InputBasicInfo> GetInputList(string inputKind = null)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("inputKind", JToken.op_Implicit(inputKind));
			JObject additionalFields = val;
			JObject obj = ((inputKind == null) ? SendRequest("GetInputList") : SendRequest("GetInputList", additionalFields));
			List<InputBasicInfo> list = new List<InputBasicInfo>();
			foreach (JToken item in (IEnumerable<JToken>)obj["inputs"])
			{
				list.Add(new InputBasicInfo((JObject)(object)((item is JObject) ? item : null)));
			}
			return list;
		}

		public List<string> GetInputKindList(bool unversioned = false)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("unversioned", JToken.op_Implicit(unversioned));
			JObject additionalFields = val;
			return JsonConvert.DeserializeObject<List<string>>(((object)((!unversioned) ? SendRequest("GetInputKindList") : SendRequest("GetInputKindList", additionalFields))["inputKinds"]).ToString());
		}

		public void RemoveInput(string inputName)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("inputName", JToken.op_Implicit(inputName));
			JObject additionalFields = val;
			SendRequest("RemoveInput", additionalFields);
		}

		public void SetInputName(string inputName, string newInputName)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("inputName", JToken.op_Implicit(inputName));
			val.Add("newInputName", JToken.op_Implicit(newInputName));
			JObject additionalFields = val;
			SendRequest("SetInputName", additionalFields);
		}

		public InputSettings GetInputSettings(string inputName)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("inputName", JToken.op_Implicit(inputName));
			JObject val2 = val;
			JObject obj = SendRequest("GetInputSettings", val2);
			((JContainer)obj).Merge((object)val2);
			return new InputSettings(obj);
		}

		public void SetInputSettings(InputSettings inputSettings, bool overlay = true)
		{
			SetInputSettings(inputSettings.InputName, inputSettings.Settings, overlay);
		}

		public void SetInputSettings(string inputName, JObject inputSettings, bool overlay = true)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("inputName", JToken.op_Implicit(inputName));
			val.Add("inputSettings", (JToken)(object)inputSettings);
			val.Add("overlay", JToken.op_Implicit(overlay));
			JObject additionalFields = val;
			SendRequest("SetInputSettings", additionalFields);
		}

		public double GetInputAudioBalance(string inputName)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("inputName", JToken.op_Implicit(inputName));
			JObject additionalFields = val;
			return (double)SendRequest("GetInputAudioBalance", additionalFields)["inputAudioBalance"];
		}

		public void SetInputAudioBalance(string inputName, double inputAudioBalance)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("inputName", JToken.op_Implicit(inputName));
			val.Add("inputAudioBalance", JToken.op_Implicit(inputAudioBalance));
			JObject additionalFields = val;
			SendRequest("SetInputAudioBalance", additionalFields);
		}

		public List<JObject> GetInputPropertiesListPropertyItems(string inputName, string propertyName)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("inputName", JToken.op_Implicit(inputName));
			val.Add("propertyName", JToken.op_Implicit(propertyName));
			JObject additionalFields = val;
			return Extensions.Value<List<JObject>>((IEnumerable<JToken>)SendRequest("GetInputPropertiesListPropertyItems", additionalFields)["propertyItems"]);
		}

		public void PressInputPropertiesButton(string inputName, string propertyName)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("inputName", JToken.op_Implicit(inputName));
			val.Add("propertyName", JToken.op_Implicit(propertyName));
			JObject additionalFields = val;
			SendRequest("PressInputPropertiesButton", additionalFields);
		}

		public MediaInputStatus GetMediaInputStatus(string inputName)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("inputName", JToken.op_Implicit(inputName));
			JObject additionalFields = val;
			return new MediaInputStatus(SendRequest("GetMediaInputStatus", additionalFields));
		}

		public void TriggerMediaInputAction(string inputName, string mediaAction)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("inputName", JToken.op_Implicit(inputName));
			val.Add("mediaAction", JToken.op_Implicit(mediaAction));
			JObject additionalFields = val;
			SendRequest("TriggerMediaInputAction", additionalFields);
		}

		public string GetLastReplayBufferReplay()
		{
			return (string)SendRequest("GetLastReplayBufferReplay")["savedReplayPath"];
		}

		public void ToggleRecordPause()
		{
			SendRequest("ToggleRecordPause");
		}

		public List<JObject> GetGroupSceneItemList(string sceneName)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("sceneName", JToken.op_Implicit(sceneName));
			JObject additionalFields = val;
			return JsonConvert.DeserializeObject<List<JObject>>((string)SendRequest("GetGroupSceneItemList", additionalFields)["sceneItems"]);
		}

		public int GetSceneItemId(string sceneName, string sourceName, int searchOffset)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("sceneName", JToken.op_Implicit(sceneName));
			val.Add("sourceName", JToken.op_Implicit(sourceName));
			val.Add("searchOffset", JToken.op_Implicit(searchOffset));
			JObject additionalFields = val;
			return (int)SendRequest("GetSceneItemId", additionalFields)["sceneItemId"];
		}

		public SceneItemTransformInfo GetSceneItemTransform(string sceneName, int sceneItemId)
		{
			return JsonConvert.DeserializeObject<SceneItemTransformInfo>(((object)GetSceneItemTransformRaw(sceneName, sceneItemId)["sceneItemTransform"]).ToString());
		}

		public JObject GetSceneItemTransformRaw(string sceneName, int sceneItemId)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("sceneName", JToken.op_Implicit(sceneName));
			val.Add("sceneItemId", JToken.op_Implicit(sceneItemId));
			JObject additionalFields = val;
			return SendRequest("GetSceneItemTransform", additionalFields);
		}

		public bool GetSceneItemEnabled(string sceneName, int sceneItemId)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("sceneName", JToken.op_Implicit(sceneName));
			val.Add("sceneItemId", JToken.op_Implicit(sceneItemId));
			JObject additionalFields = val;
			return (bool)SendRequest("GetSceneItemEnabled", additionalFields)["sceneItemEnabled"];
		}

		public void SetSceneItemEnabled(string sceneName, int sceneItemId, bool sceneItemEnabled)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("sceneName", JToken.op_Implicit(sceneName));
			val.Add("sceneItemId", JToken.op_Implicit(sceneItemId));
			val.Add("sceneItemEnabled", JToken.op_Implicit(sceneItemEnabled));
			JObject additionalFields = val;
			SendRequest("SetSceneItemEnabled", additionalFields);
		}

		public bool GetSceneItemLocked(string sceneName, int sceneItemId)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("sceneName", JToken.op_Implicit(sceneName));
			val.Add("sceneItemId", JToken.op_Implicit(sceneItemId));
			JObject additionalFields = val;
			return (bool)SendRequest("GetSceneItemLocked", additionalFields)["sceneItemLocked"];
		}

		public void SetSceneItemLocked(string sceneName, int sceneItemId, bool sceneItemLocked)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("sceneName", JToken.op_Implicit(sceneName));
			val.Add("sceneItemId", JToken.op_Implicit(sceneItemId));
			val.Add("sceneItemLocked", JToken.op_Implicit(sceneItemLocked));
			JObject additionalFields = val;
			SendRequest("SetSceneItemLocked", additionalFields);
		}

		public int GetSceneItemIndex(string sceneName, int sceneItemId)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("sceneName", JToken.op_Implicit(sceneName));
			val.Add("sceneItemId", JToken.op_Implicit(sceneItemId));
			JObject additionalFields = val;
			return (int)SendRequest("GetSceneItemIndex", additionalFields)["sceneItemIndex"];
		}

		public void SetSceneItemIndex(string sceneName, int sceneItemId, int sceneItemIndex)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("sceneName", JToken.op_Implicit(sceneName));
			val.Add("sceneItemId", JToken.op_Implicit(sceneItemId));
			val.Add("sceneItemIndex", JToken.op_Implicit(sceneItemIndex));
			JObject additionalFields = val;
			SendRequest("SetSceneItemIndex", additionalFields);
		}

		public string GetSceneItemBlendMode(string sceneName, int sceneItemId)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("sceneName", JToken.op_Implicit(sceneName));
			val.Add("sceneItemId", JToken.op_Implicit(sceneItemId));
			JObject additionalFields = val;
			return (string)SendRequest("GetSceneItemBlendMode", additionalFields)["sceneItemBlendMode"];
		}

		public void SetSceneItemBlendMode(string sceneName, int sceneItemId, string sceneItemBlendMode)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("sceneName", JToken.op_Implicit(sceneName));
			val.Add("sceneItemId", JToken.op_Implicit(sceneItemId));
			val.Add("sceneItemBlendMode", JToken.op_Implicit(sceneItemBlendMode));
			JObject additionalFields = val;
			SendRequest("SetSceneItemBlendMode", additionalFields);
		}

		public List<string> GetGroupList()
		{
			return JsonConvert.DeserializeObject<List<string>>(((object)SendRequest("GetGroupList")["groups"]).ToString());
		}

		public void RemoveScene(string sceneName)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("sceneName", JToken.op_Implicit(sceneName));
			JObject additionalFields = val;
			SendRequest("RemoveScene", additionalFields);
		}

		public void SetSceneName(string sceneName, string newSceneName)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("sceneName", JToken.op_Implicit(sceneName));
			val.Add("newSceneName", JToken.op_Implicit(newSceneName));
			JObject additionalFields = val;
			SendRequest("SetSceneName", additionalFields);
		}

		public string GetSourceScreenshot(string sourceName, string imageFormat, int imageWidth = -1, int imageHeight = -1, int imageCompressionQuality = -1)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("sourceName", JToken.op_Implicit(sourceName));
			val.Add("imageFormat", JToken.op_Implicit(imageFormat));
			JObject val2 = val;
			if (imageWidth > -1)
			{
				val2.Add("imageWidth", JToken.op_Implicit(imageWidth));
			}
			if (imageHeight > -1)
			{
				val2.Add("imageHeight", JToken.op_Implicit(imageHeight));
			}
			if (imageCompressionQuality > -1)
			{
				val2.Add("imageCompressionQuality", JToken.op_Implicit(imageCompressionQuality));
			}
			return (string)SendRequest("GetSourceScreenshot", val2)["imageData"];
		}

		public List<string> GetTransitionKindList()
		{
			return JsonConvert.DeserializeObject<List<string>>(((object)SendRequest("GetTransitionKindList")["transitionKinds"]).ToString());
		}

		public double GetCurrentSceneTransitionCursor()
		{
			return (double)SendRequest("GetCurrentSceneTransitionCursor")["transitionCursor"];
		}

		public void OpenInputPropertiesDialog(string inputName)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("inputName", JToken.op_Implicit(inputName));
			JObject additionalFields = val;
			SendRequest("OpenInputPropertiesDialog", additionalFields);
		}

		public void OpenInputFiltersDialog(string inputName)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("inputName", JToken.op_Implicit(inputName));
			JObject additionalFields = val;
			SendRequest("OpenInputFiltersDialog", additionalFields);
		}

		public void OpenInputInteractDialog(string inputName)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("inputName", JToken.op_Implicit(inputName));
			JObject additionalFields = val;
			SendRequest("OpenInputInteractDialog", additionalFields);
		}

		public List<Monitor> GetMonitorList()
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			JObject obj = SendRequest("GetMonitorList");
			List<Monitor> list = new List<Monitor>();
			foreach (JToken item in (IEnumerable<JToken>)obj["monitors"])
			{
				list.Add(new Monitor((JObject)item));
			}
			return list;
		}

		public void OpenSourceProjector(string sourceName, string projectorGeometry, int monitorIndex = -1)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("sourceName", JToken.op_Implicit(sourceName));
			val.Add("projectorGeometry", JToken.op_Implicit(projectorGeometry));
			val.Add("monitorIndex", JToken.op_Implicit(monitorIndex));
			JObject additionalFields = val;
			SendRequest("OpenSourceProjector", additionalFields);
		}

		public void OpenVideoMixProjector(string videoMixType, string projectorGeometry, int monitorIndex = -1)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			JObject val = new JObject();
			val.Add("videoMixType", JToken.op_Implicit(videoMixType));
			val.Add("projectorGeometry", JToken.op_Implicit(projectorGeometry));
			val.Add("monitorIndex", JToken.op_Implicit(monitorIndex));
			JObject additionalFields = val;
			SendRequest("OpenVideoMixProjector", additionalFields);
		}
	}
	public class AuthFailureException : Exception
	{
	}
	public class ErrorResponseException : Exception
	{
		public int ErrorCode { get; set; }

		public ErrorResponseException(string message, int errorCode)
			: base(message)
		{
			ErrorCode = errorCode;
		}
	}
	public interface IOBSWebsocket
	{
		TimeSpan WSTimeout { get; set; }

		bool IsConnected { get; }

		event EventHandler<ProgramSceneChangedEventArgs> CurrentProgramSceneChanged;

		event EventHandler<SceneListChangedEventArgs> SceneListChanged;

		event EventHandler<SceneItemListReindexedEventArgs> SceneItemListReindexed;

		event EventHandler<SceneItemCreatedEventArgs> SceneItemCreated;

		event EventHandler<SceneItemRemovedEventArgs> SceneItemRemoved;

		event EventHandler<SceneItemEnableStateChangedEventArgs> SceneItemEnableStateChanged;

		event EventHandler<SceneItemLockStateChangedEventArgs> SceneItemLockStateChanged;

		event EventHandler<CurrentSceneCollectionChangedEventArgs> CurrentSceneCollectionChanged;

		event EventHandler<SceneCollectionListChangedEventArgs> SceneCollectionListChanged;

		event EventHandler<CurrentSceneTransitionChangedEventArgs> CurrentSceneTransitionChanged;

		event EventHandler<CurrentSceneTransitionDurationChangedEventArgs> CurrentSceneTransitionDurationChanged;

		event EventHandler<SceneTransitionStartedEventArgs> SceneTransitionStarted;

		event EventHandler<SceneTransitionEndedEventArgs> SceneTransitionEnded;

		event EventHandler<SceneTransitionVideoEndedEventArgs> SceneTransitionVideoEnded;

		event EventHandler<CurrentProfileChangedEventArgs> CurrentProfileChanged;

		event EventHandler<ProfileListChangedEventArgs> ProfileListChanged;

		event EventHandler<StreamStateChangedEventArgs> StreamStateChanged;

		event EventHandler<RecordStateChangedEventArgs> RecordStateChanged;

		event EventHandler<ReplayBufferStateChangedEventArgs> ReplayBufferStateChanged;

		event EventHandler<CurrentPreviewSceneChangedEventArgs> CurrentPreviewSceneChanged;

		event EventHandler<StudioModeStateChangedEventArgs> StudioModeStateChanged;

		event EventHandler ExitStarted;

		event EventHandler Connected;

		event EventHandler<ObsDisconnectionInfo> Disconnected;

		event EventHandler<SceneItemSelectedEventArgs> SceneItemSelected;

		event EventHandler<SceneItemTransformEventArgs> SceneItemTransformChanged;

		event EventHandler<InputAudioSyncOffsetChangedEventArgs> InputAudioSyncOffsetChanged;

		event EventHandler<SourceFilterCreatedEventArgs> SourceFilterCreated;

		event EventHandler<SourceFilterRemovedEventArgs> SourceFilterRemoved;

		event EventHandler<SourceFilterListReindexedEventArgs> SourceFilterListReindexed;

		event EventHandler<SourceFilterEnableStateChangedEventArgs> SourceFilterEnableStateChanged;

		event EventHandler<InputMuteStateChangedEventArgs> InputMuteStateChanged;

		event EventHandler<InputVolumeChangedEventArgs> InputVolumeChanged;

		event EventHandler<VendorEventArgs> VendorEvent;

		event EventHandler<MediaInputPlaybackEndedEventArgs> MediaInputPlaybackEnded;

		event EventHandler<MediaInputPlaybackStartedEventArgs> MediaInputPlaybackStarted;

		event EventHandler<MediaInputActionTriggeredEventArgs> MediaInputActionTriggered;

		event EventHandler<VirtualcamStateChangedEventArgs> VirtualcamStateChanged;

		event EventHandler<CurrentSceneCollectionChangingEventArgs> CurrentSceneCollectionChanging;

		event EventHandler<CurrentProfileChangingEventArgs> CurrentProfileChanging;

		event EventHandler<SourceFilterNameChangedEventArgs> SourceFilterNameChanged;

		event EventHandler<InputCreatedEventArgs> InputCreated;

		event EventHandler<InputRemovedEventArgs> InputRemoved;

		event EventHandler<InputNameChangedEventArgs> InputNameChanged;

		event EventHandler<InputActiveStateChangedEventArgs> InputActiveStateChanged;

		event EventHandler<InputShowStateChangedEventArgs> InputShowStateChanged;

		event EventHandler<InputAudioBalanceChangedEventArgs> InputAudioBalanceChanged;

		event EventHandler<InputAudioTracksChangedEventArgs> InputAudioTracksChanged;

		event EventHandler<InputAudioMonitorTypeChangedEventArgs> InputAudioMonitorTypeChanged;

		event EventHandler<InputVolumeMetersEventArgs> InputVolumeMeters;

		event EventHandler<ReplayBufferSavedEventArgs> ReplayBufferSaved;

		event EventHandler<SceneCreatedEventArgs> SceneCreated;

		event EventHandler<SceneRemovedEventArgs> SceneRemoved;

		event EventHandler<SceneNameChangedEventArgs> SceneNameChanged;

		ObsVideoSettings GetVideoSettings();

		string SaveSourceScreenshot(string sourceName, string imageFormat, string imageFilePath, int imageWidth = -1, int imageHeight = -1, int imageCompressionQuality = -1);

		string SaveSourceScreenshot(string sourceName, string imageFormat, string imageFilePath);

		void TriggerHotkeyByName(string hotkeyName);

		void TriggerHotkeyByKeySequence(OBSHotkey keyId, KeyModifier keyModifier = KeyModifier.None);

		string GetCurrentProgramScene();

		void SetCurrentProgramScene(string sceneName);

		ObsStats GetStats();

		List<SceneBasicInfo> ListScenes();

		GetSceneListInfo GetSceneList();

		TransitionOverrideInfo GetSceneSceneTransitionOverride(string sceneName);

		void SetSceneSceneTransitionOverride(string sceneName, string transitionName, int transitionDuration = -1);

		void SetTBarPosition(double position, bool release = true);

		void SetSourceFilterSettings(string sourceName, string filterName, JObject filterSettings, bool overlay = false);

		void SetSourceFilterSettings(string sourceName, string filterName, FilterSettings filterSettings, bool overlay = false);

		void SetSourceFilterEnabled(string sourceName, string filterName, bool filterEnabled);

		List<FilterSettings> GetSourceFilterList(string sourceName);

		FilterSettings GetSourceFilter(string sourceName, string filterName);

		bool RemoveSourceFilter(string sourceName, string filterName);

		void CreateSourceFilter(string sourceName, string filterName, string filterKind, JObject filterSettings);

		void CreateSourceFilter(string sourceName, string filterName, string filterKind, FilterSettings filterSettings);

		bool ToggleStream();

		void ToggleRecord();

		OutputStatus GetStreamStatus();

		TransitionSettings GetCurrentSceneTransition();

		void SetCurrentSceneTransition(string transitionName);

		void SetCurrentSceneTransitionDuration(int transitionDuration);

		void SetCurrentSceneTransitionSettings(JObject transitionSettings, bool overlay);

		void SetInputVolume(string inputName, float inputVolume, bool inputVolumeDb = false);

		VolumeInfo GetInputVolume(string inputName);

		bool GetInputMute(string inputName);

		void SetInputMute(string inputName, bool inputMuted);

		void ToggleInputMute(string inputName);

		void SetSceneItemTransform(string sceneName, int sceneItemId, JObject sceneItemTransform);

		void SetSceneItemTransform(string sceneName, int sceneItemId, SceneItemTransformInfo sceneItemTransform);

		void SetCurrentSceneCollection(string sceneCollectionName);

		string GetCurrentSceneCollection();

		List<string> GetSceneCollectionList();

		void SetCurrentProfile(string profileName);

		GetProfileListInfo GetProfileList();

		void StartStream();

		void StopStream();

		void StartRecord();

		string StopRecord();

		void PauseRecord();

		void ResumeRecord();

		string GetRecordDirectory();

		RecordingStatus GetRecordStatus();

		bool GetReplayBufferStatus();

		GetTransitionListInfo GetSceneTransitionList();

		bool GetStudioModeEnabled();

		void SetStudioModeEnabled(bool studioModeEnabled);

		string GetCurrentPreviewScene();

		void SetCurrentPreviewScene(string sceneName);

		void SetCurrentPreviewScene(ObsScene previewScene);

		void TriggerStudioModeTransition();

		void ToggleReplayBuffer();

		void StartReplayBuffer();

		void StopReplayBuffer();

		void SaveReplayBuffer();

		void SetInputAudioSyncOffset(string inputName, int inputAudioSyncOffset);

		int GetInputAudioSyncOffset(string inputName);

		void RemoveSceneItem(string sceneName, int sceneItemId);

		void SendStreamCaption(string captionText);

		void DuplicateSceneItem(string sceneName, int sceneItemId, string destinationSceneName = null);

		Dictionary<string, string> GetSpecialInputs();

		void SetStreamServiceSettings(StreamingService service);

		StreamingService GetStreamServiceSettings();

		string GetInputAudioMonitorType(string inputName);

		void SetInputAudioMonitorType(string inputName, string monitorType);

		void BroadcastCustomEvent(JObject eventData);

		void SetMediaInputCursor(string inputName, int mediaCursor);

		void OffsetMediaInputCursor(string inputName, int mediaCursorOffset);

		int CreateInput(string sceneName, string inputName, string inputKind, JObject inputSettings, bool? sceneItemEnabled);

		JObject GetInputDefaultSettings(string inputKind);

		List<SceneItemDetails> GetSceneItemList(string sceneName);

		int CreateSceneItem(string sceneName, string sourceName, bool sceneItemEnabled = true);

		void CreateScene(string sceneName);

		SourceTracks GetInputAudioTracks(string inputName);

		void SetInputAudioTracks(string inputName, JObject inputAudioTracks);

		void SetInputAudioTracks(string inputName, SourceTracks inputAudioTracks);

		SourceActiveInfo GetSourceActive(string sourceName);

		VirtualCamStatus GetVirtualCamStatus();

		void StartVirtualCam();

		void StopVirtualCam();

		VirtualCamStatus ToggleVirtualCam();

		JObject GetPersistentData(string realm, string slotName);

		void SetPersistentData(string realm, string slotName, JObject slotValue);

		void CreateSceneCollection(string sceneCollectionName);

		void CreateProfile(string profileName);

		void RemoveProfile(string profileName);

		JObject GetProfileParameter(string parameterCategory, string parameterName);

		void SetProfileParameter(string parameterCategory, string parameterName, string parameterValue);

		void SetVideoSettings(ObsVideoSettings obsVideoSettings);

		JObject GetSourceFilterDefaultSettings(string filterKind);

		void SetSourceFilterName(string sourceName, string filterName, string newFilterName);

		void SetSourceFilterIndex(string sourceName, string filterName, int filterIndex);

		ObsVersion GetVersion();

		JObject CallVendorRequest(string vendorName, string requestType, JObject requestData = null);

		List<string> GetHotkeyList();

		void Sleep(int sleepMillis, int sleepFrames);

		List<InputBasicInfo> GetInputList(string inputKind = null);

		List<string> GetInputKindList(bool unversioned = false);

		void RemoveInput(string inputName);

		void SetInputName(string inputName, string newInputName);

		InputSettings GetInputSettings(string inputName);

		void SetInputSettings(InputSettings inputSettings, bool overlay = true);

		void SetInputSettings(string inputName, JObject inputSettings, bool overlay = true);

		double GetInputAudioBalance(string inputName);

		void SetInputAudioBalance(string inputName, double inputAudioBalance);

		List<JObject> GetInputPropertiesListPropertyItems(string inputName, string propertyName);

		void PressInputPropertiesButton(string inputName, string propertyName);

		MediaInputStatus GetMediaInputStatus(string inputName);

		void TriggerMediaInputAction(string inputName, string mediaAction);

		string GetLastReplayBufferReplay();

		void ToggleRecordPause();

		List<JObject> GetGroupSceneItemList(string sceneName);

		int GetSceneItemId(string sceneName, string sourceName, int searchOffset);

		SceneItemTransformInfo GetSceneItemTransform(string sceneName, int sceneItemId);

		JObject GetSceneItemTransformRaw(string sceneName, int sceneItemId);

		bool GetSceneItemEnabled(string sceneName, int sceneItemId);

		void SetSceneItemEnabled(string sceneName, int sceneItemId, bool sceneItemEnabled);

		bool GetSceneItemLocked(string sceneName, int sceneItemId);

		void SetSceneItemLocked(string sceneName, int sceneItemId, bool sceneItemLocked);

		int GetSceneItemIndex(string sceneName, int sceneItemId);

		void SetSceneItemIndex(string sceneName, int sceneItemId, int sceneItemIndex);

		string GetSceneItemBlendMode(string sceneName, int sceneItemId);

		void SetSceneItemBlendMode(string sceneName, int sceneItemId, string sceneItemBlendMode);

		List<string> GetGroupList();

		void RemoveScene(string sceneName);

		void SetSceneName(string sceneName, string newSceneName);

		string GetSourceScreenshot(string sourceName, string imageFormat, int imageWidth = -1, int imageHeight = -1, int imageCompressionQuality = -1);

		List<string> GetTransitionKindList();

		double GetCurrentSceneTransitionCursor();

		void OpenInputPropertiesDialog(string inputName);

		void OpenInputFiltersDialog(string inputName);

		void OpenInputInteractDialog(string inputName);

		List<Monitor> GetMonitorList();

		[Obsolete("Please use ConnectAsync, this function will be removed in the next version")]
		void Connect(string url, string password);

		void ConnectAsync(string url, string password);

		void Disconnect();

		JObject SendRequest(string requestType, JObject additionalFields = null);

		OBSAuthInfo GetAuthInfo();
	}
}
namespace OBSWebsocketDotNet.Types
{
	public class FilterReorderItem
	{
		[JsonProper

UserLibs/System.Reactive.dll

Decompiled a month ago
#define TRACE
using System;
using System.CodeDom.Compiler;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq;
using System.Linq.Expressions;
using System.Reactive;
using System.Reactive.Concurrency;
using System.Reactive.Disposables;
using System.Reactive.Joins;
using System.Reactive.Linq;
using System.Reactive.Linq.ObservableImpl;
using System.Reactive.PlatformServices;
using System.Reactive.Subjects;
using System.Reactive.Threading.Tasks;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.ExceptionServices;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Runtime.Versioning;
using System.Security;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyFileVersion("4.3.2.55399")]
[assembly: AssemblyInformationalVersion("4.3.2+67d891dfbf")]
[assembly: InternalsVisibleTo("Tests.System.Reactive, PublicKey=00240000048000009400000006020000002400005253413100040000010001008f5cff058631087031f8350f30a36fa078027e5df2316b564352dc9eb7af7ce856016d3c5e9d058036fe73bb5c83987bd3fc0793fbe25d633cc4f37c2bd5f1d717cd2a81661bec08f0971dc6078e17bde372b89005e7738a0ebd501b896ca3e8315270ff64df7809dd912c372df61785a5085b3553b7872e39b1b1cc0ff5a6bc")]
[assembly: InternalsVisibleTo("Tests.System.Reactive.Uwp.DeviceRunner, PublicKey=00240000048000009400000006020000002400005253413100040000010001008f5cff058631087031f8350f30a36fa078027e5df2316b564352dc9eb7af7ce856016d3c5e9d058036fe73bb5c83987bd3fc0793fbe25d633cc4f37c2bd5f1d717cd2a81661bec08f0971dc6078e17bde372b89005e7738a0ebd501b896ca3e8315270ff64df7809dd912c372df61785a5085b3553b7872e39b1b1cc0ff5a6bc")]
[assembly: ComVisible(false)]
[assembly: CLSCompliant(true)]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = "")]
[assembly: AssemblyMetadata("CommitHash", "67d891dfbf7263781dceedaa62548c1baaa33163")]
[assembly: AssemblyCompany(".NET Foundation and Contributors")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright (c) .NET Foundation and Contributors.")]
[assembly: AssemblyDescription("Reactive Extensions (Rx) for .NET")]
[assembly: AssemblyProduct("System.Reactive (netstandard2.0)")]
[assembly: AssemblyTitle("System.Reactive")]
[assembly: AssemblyVersion("4.3.0.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class IsReadOnlyAttribute : Attribute
	{
	}
}
[GeneratedCode("Nerdbank.GitVersioning.Tasks", "3.0.28.11123")]
internal static class ThisAssembly
{
	internal const string AssemblyVersion = "4.3.0.0";

	internal const string AssemblyFileVersion = "4.3.2.55399";

	internal const string AssemblyInformationalVersion = "4.3.2+67d891dfbf";

	internal const string AssemblyName = "System.Reactive";

	internal const string AssemblyTitle = "System.Reactive";

	internal const string AssemblyConfiguration = "Release";

	internal const string GitCommitId = "67d891dfbf7263781dceedaa62548c1baaa33163";

	internal const string PublicKey = "00240000048000009400000006020000002400005253413100040000010001008f5cff058631087031f8350f30a36fa078027e5df2316b564352dc9eb7af7ce856016d3c5e9d058036fe73bb5c83987bd3fc0793fbe25d633cc4f37c2bd5f1d717cd2a81661bec08f0971dc6078e17bde372b89005e7738a0ebd501b896ca3e8315270ff64df7809dd912c372df61785a5085b3553b7872e39b1b1cc0ff5a6bc";

	internal const string PublicKeyToken = "94bc3704cddfc263";

	internal static readonly DateTime GitCommitDate = new DateTime(637127137800000000L, DateTimeKind.Utc);

	internal const string RootNamespace = "System.Reactive";
}
namespace System
{
	public static class ObservableExtensions
	{
		public static IDisposable Subscribe<T>(this IObservable<T> source)
		{
			if (source == null)
			{
				throw new ArgumentNullException("source");
			}
			return source.Subscribe(new AnonymousObserver<T>(Stubs<T>.Ignore, Stubs.Throw, Stubs.Nop));
		}

		public static IDisposable Subscribe<T>(this IObservable<T> source, Action<T> onNext)
		{
			if (source == null)
			{
				throw new ArgumentNullException("source");
			}
			if (onNext == null)
			{
				throw new ArgumentNullException("onNext");
			}
			return source.Subscribe(new AnonymousObserver<T>(onNext, Stubs.Throw, Stubs.Nop));
		}

		public static IDisposable Subscribe<T>(this IObservable<T> source, Action<T> onNext, Action<Exception> onError)
		{
			if (source == null)
			{
				throw new ArgumentNullException("source");
			}
			if (onNext == null)
			{
				throw new ArgumentNullException("onNext");
			}
			if (onError == null)
			{
				throw new ArgumentNullException("onError");
			}
			return source.Subscribe(new AnonymousObserver<T>(onNext, onError, Stubs.Nop));
		}

		public static IDisposable Subscribe<T>(this IObservable<T> source, Action<T> onNext, Action onCompleted)
		{
			if (source == null)
			{
				throw new ArgumentNullException("source");
			}
			if (onNext == null)
			{
				throw new ArgumentNullException("onNext");
			}
			if (onCompleted == null)
			{
				throw new ArgumentNullException("onCompleted");
			}
			return source.Subscribe(new AnonymousObserver<T>(onNext, Stubs.Throw, onCompleted));
		}

		public static IDisposable Subscribe<T>(this IObservable<T> source, Action<T> onNext, Action<Exception> onError, Action onCompleted)
		{
			if (source == null)
			{
				throw new ArgumentNullException("source");
			}
			if (onNext == null)
			{
				throw new ArgumentNullException("onNext");
			}
			if (onError == null)
			{
				throw new ArgumentNullException("onError");
			}
			if (onCompleted == null)
			{
				throw new ArgumentNullException("onCompleted");
			}
			return source.Subscribe(new AnonymousObserver<T>(onNext, onError, onCompleted));
		}

		public static void Subscribe<T>(this IObservable<T> source, IObserver<T> observer, CancellationToken token)
		{
			if (source == null)
			{
				throw new ArgumentNullException("source");
			}
			if (observer == null)
			{
				throw new ArgumentNullException("observer");
			}
			source.Subscribe_(observer, token);
		}

		public static void Subscribe<T>(this IObservable<T> source, CancellationToken token)
		{
			if (source == null)
			{
				throw new ArgumentNullException("source");
			}
			source.Subscribe_(new AnonymousObserver<T>(Stubs<T>.Ignore, Stubs.Throw, Stubs.Nop), token);
		}

		public static void Subscribe<T>(this IObservable<T> source, Action<T> onNext, CancellationToken token)
		{
			if (source == null)
			{
				throw new ArgumentNullException("source");
			}
			if (onNext == null)
			{
				throw new ArgumentNullException("onNext");
			}
			source.Subscribe_(new AnonymousObserver<T>(onNext, Stubs.Throw, Stubs.Nop), token);
		}

		public static void Subscribe<T>(this IObservable<T> source, Action<T> onNext, Action<Exception> onError, CancellationToken token)
		{
			if (source == null)
			{
				throw new ArgumentNullException("source");
			}
			if (onNext == null)
			{
				throw new ArgumentNullException("onNext");
			}
			if (onError == null)
			{
				throw new ArgumentNullException("onError");
			}
			source.Subscribe_(new AnonymousObserver<T>(onNext, onError, Stubs.Nop), token);
		}

		public static void Subscribe<T>(this IObservable<T> source, Action<T> onNext, Action onCompleted, CancellationToken token)
		{
			if (source == null)
			{
				throw new ArgumentNullException("source");
			}
			if (onNext == null)
			{
				throw new ArgumentNullException("onNext");
			}
			if (onCompleted == null)
			{
				throw new ArgumentNullException("onCompleted");
			}
			source.Subscribe_(new AnonymousObserver<T>(onNext, Stubs.Throw, onCompleted), token);
		}

		public static void Subscribe<T>(this IObservable<T> source, Action<T> onNext, Action<Exception> onError, Action onCompleted, CancellationToken token)
		{
			if (source == null)
			{
				throw new ArgumentNullException("source");
			}
			if (onNext == null)
			{
				throw new ArgumentNullException("onNext");
			}
			if (onError == null)
			{
				throw new ArgumentNullException("onError");
			}
			if (onCompleted == null)
			{
				throw new ArgumentNullException("onCompleted");
			}
			source.Subscribe_(new AnonymousObserver<T>(onNext, onError, onCompleted), token);
		}

		private static void Subscribe_<T>(this IObservable<T> source, IObserver<T> observer, CancellationToken token)
		{
			if (token.CanBeCanceled)
			{
				if (!token.IsCancellationRequested)
				{
					ISafeObserver<T> safeObserver = SafeObserver<T>.Wrap(observer);
					IDisposable state2 = source.Subscribe(safeObserver);
					safeObserver.SetResource(token.Register(delegate(object state)
					{
						((IDisposable)state).Dispose();
					}, state2));
				}
			}
			else
			{
				source.Subscribe(observer);
			}
		}

		[EditorBrowsable(EditorBrowsableState.Advanced)]
		public static IDisposable SubscribeSafe<T>(this IObservable<T> source, IObserver<T> observer)
		{
			if (source == null)
			{
				throw new ArgumentNullException("source");
			}
			if (observer == null)
			{
				throw new ArgumentNullException("observer");
			}
			if (source is ObservableBase<T>)
			{
				return source.Subscribe(observer);
			}
			if (source is IProducer<T> producer)
			{
				return producer.SubscribeRaw(observer, enableSafeguard: false);
			}
			IDisposable result = Disposable.Empty;
			try
			{
				result = source.Subscribe(observer);
			}
			catch (Exception error)
			{
				observer.OnError(error);
			}
			return result;
		}
	}
}
namespace System.Runtime.CompilerServices
{
	public struct TaskObservableMethodBuilder<T>
	{
		internal sealed class TaskObservable : ITaskObservable<T>, IObservable<T>, ITaskObservableAwaiter<T>, INotifyCompletion
		{
			private readonly AsyncSubject<T> _subject;

			private readonly T _result;

			private readonly Exception _exception;

			public bool IsCompleted => _subject?.IsCompleted ?? true;

			public TaskObservable()
			{
				_subject = new AsyncSubject<T>();
			}

			public TaskObservable(T result)
			{
				_result = result;
			}

			public TaskObservable(Exception exception)
			{
				_exception = exception;
			}

			public void SetResult(T result)
			{
				if (IsCompleted)
				{
					throw new InvalidOperationException();
				}
				_subject.OnNext(result);
				_subject.OnCompleted();
			}

			public void SetException(Exception exception)
			{
				if (IsCompleted)
				{
					throw new InvalidOperationException();
				}
				_subject.OnError(exception);
			}

			public IDisposable Subscribe(IObserver<T> observer)
			{
				if (_subject != null)
				{
					return _subject.Subscribe(observer);
				}
				if (_exception != null)
				{
					observer.OnError(_exception);
					return Disposable.Empty;
				}
				observer.OnNext(_result);
				return Disposable.Empty;
			}

			public ITaskObservableAwaiter<T> GetAwaiter()
			{
				return this;
			}

			public T GetResult()
			{
				if (_subject != null)
				{
					return _subject.GetResult();
				}
				_exception.ThrowIfNotNull();
				return _result;
			}

			public void OnCompleted(Action continuation)
			{
				if (_subject != null)
				{
					_subject.OnCompleted(continuation);
				}
				else
				{
					continuation();
				}
			}
		}

		private IAsyncStateMachine _stateMachine;

		private TaskObservable _inner;

		public ITaskObservable<T> Task => _inner ?? (_inner = new TaskObservable());

		public static TaskObservableMethodBuilder<T> Create()
		{
			return default(TaskObservableMethodBuilder<T>);
		}

		public void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine
		{
			if (stateMachine == null)
			{
				throw new ArgumentNullException("stateMachine");
			}
			stateMachine.MoveNext();
		}

		public void SetStateMachine(IAsyncStateMachine stateMachine)
		{
			if (_stateMachine != null)
			{
				throw new InvalidOperationException();
			}
			_stateMachine = stateMachine ?? throw new ArgumentNullException("stateMachine");
		}

		public void SetResult(T result)
		{
			if (_inner == null)
			{
				_inner = new TaskObservable(result);
			}
			else
			{
				_inner.SetResult(result);
			}
		}

		public void SetException(Exception exception)
		{
			if (exception == null)
			{
				throw new ArgumentNullException("exception");
			}
			if (_inner == null)
			{
				_inner = new TaskObservable(exception);
			}
			else
			{
				_inner.SetException(exception);
			}
		}

		public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : INotifyCompletion where TStateMachine : IAsyncStateMachine
		{
			try
			{
				if (_stateMachine == null)
				{
					_ = Task;
					_stateMachine = stateMachine;
					_stateMachine.SetStateMachine(_stateMachine);
				}
				awaiter.OnCompleted(_stateMachine.MoveNext);
			}
			catch (Exception exception)
			{
				Rethrow(exception);
			}
		}

		[SecuritySafeCritical]
		public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : ICriticalNotifyCompletion where TStateMachine : IAsyncStateMachine
		{
			try
			{
				if (_stateMachine == null)
				{
					_ = Task;
					_stateMachine = stateMachine;
					_stateMachine.SetStateMachine(_stateMachine);
				}
				awaiter.UnsafeOnCompleted(_stateMachine.MoveNext);
			}
			catch (Exception exception)
			{
				Rethrow(exception);
			}
		}

		private static void Rethrow(Exception exception)
		{
			Scheduler.Default.Schedule(exception, delegate(Exception ex, Action<Exception> recurse)
			{
				ex.Throw();
			});
		}
	}
}
namespace System.Threading.Tasks
{
	internal static class TaskExtensions
	{
		public static Task ContinueWithState<TState>(this Task task, Action<Task, TState> continuationAction, TState state)
		{
			return task.ContinueWith(delegate(Task t, object tupleObject)
			{
				var (action, arg) = ((Action<Task, TState>, TState))tupleObject;
				action(t, arg);
			}, (continuationAction, state));
		}

		public static Task ContinueWithState<TState>(this Task task, Action<Task, TState> continuationAction, TState state, CancellationToken cancellationToken)
		{
			return task.ContinueWith(delegate(Task t, object tupleObject)
			{
				var (action, arg) = ((Action<Task, TState>, TState))tupleObject;
				action(t, arg);
			}, (continuationAction, state), cancellationToken);
		}

		public static Task ContinueWithState<TState>(this Task task, Action<Task, TState> continuationAction, TState state, TaskContinuationOptions continuationOptions)
		{
			return task.ContinueWith(delegate(Task t, object tupleObject)
			{
				var (action, arg) = ((Action<Task, TState>, TState))tupleObject;
				action(t, arg);
			}, (continuationAction, state), continuationOptions);
		}

		public static Task ContinueWithState<TState>(this Task task, Action<Task, TState> continuationAction, TState state, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions)
		{
			return task.ContinueWith(delegate(Task t, object tupleObject)
			{
				var (action, arg) = ((Action<Task, TState>, TState))tupleObject;
				action(t, arg);
			}, (continuationAction, state), cancellationToken, continuationOptions, TaskScheduler.Default);
		}

		public static Task ContinueWithState<TResult, TState>(this Task<TResult> task, Action<Task<TResult>, TState> continuationAction, TState state)
		{
			return task.ContinueWith(delegate(Task<TResult> t, object tupleObject)
			{
				var (action, arg) = ((Action<Task<TResult>, TState>, TState))tupleObject;
				action(t, arg);
			}, (continuationAction, state));
		}

		public static Task ContinueWithState<TResult, TState>(this Task<TResult> task, Action<Task<TResult>, TState> continuationAction, TState state, CancellationToken cancellationToken)
		{
			return task.ContinueWith(delegate(Task<TResult> t, object tupleObject)
			{
				var (action, arg) = ((Action<Task<TResult>, TState>, TState))tupleObject;
				action(t, arg);
			}, (continuationAction, state), cancellationToken);
		}

		public static Task ContinueWithState<TResult, TState>(this Task<TResult> task, Action<Task<TResult>, TState> continuationAction, TState state, TaskContinuationOptions continuationOptions)
		{
			return task.ContinueWith(delegate(Task<TResult> t, object tupleObject)
			{
				var (action, arg) = ((Action<Task<TResult>, TState>, TState))tupleObject;
				action(t, arg);
			}, (continuationAction, state), continuationOptions);
		}

		public static Task ContinueWithState<TResult, TState>(this Task<TResult> task, Action<Task<TResult>, TState> continuationAction, TState state, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions)
		{
			return task.ContinueWith(delegate(Task<TResult> t, object tupleObject)
			{
				var (action, arg) = ((Action<Task<TResult>, TState>, TState))tupleObject;
				action(t, arg);
			}, (continuationAction, state), cancellationToken, continuationOptions, TaskScheduler.Default);
		}
	}
}
namespace System.Reactive
{
	public sealed class AnonymousObservable<T> : ObservableBase<T>
	{
		private readonly Func<IObserver<T>, IDisposable> _subscribe;

		public AnonymousObservable(Func<IObserver<T>, IDisposable> subscribe)
		{
			_subscribe = subscribe ?? throw new ArgumentNullException("subscribe");
		}

		protected override IDisposable SubscribeCore(IObserver<T> observer)
		{
			return _subscribe(observer) ?? Disposable.Empty;
		}
	}
	public sealed class AnonymousObserver<T> : ObserverBase<T>
	{
		private readonly Action<T> _onNext;

		private readonly Action<Exception> _onError;

		private readonly Action _onCompleted;

		public AnonymousObserver(Action<T> onNext, Action<Exception> onError, Action onCompleted)
		{
			_onNext = onNext ?? throw new ArgumentNullException("onNext");
			_onError = onError ?? throw new ArgumentNullException("onError");
			_onCompleted = onCompleted ?? throw new ArgumentNullException("onCompleted");
		}

		public AnonymousObserver(Action<T> onNext)
			: this(onNext, Stubs.Throw, Stubs.Nop)
		{
		}

		public AnonymousObserver(Action<T> onNext, Action<Exception> onError)
			: this(onNext, onError, Stubs.Nop)
		{
		}

		public AnonymousObserver(Action<T> onNext, Action onCompleted)
			: this(onNext, Stubs.Throw, onCompleted)
		{
		}

		protected override void OnNextCore(T value)
		{
			_onNext(value);
		}

		protected override void OnErrorCore(Exception error)
		{
			_onError(error);
		}

		protected override void OnCompletedCore()
		{
			_onCompleted();
		}

		internal ISafeObserver<T> MakeSafe()
		{
			return new AnonymousSafeObserver<T>(_onNext, _onError, _onCompleted);
		}
	}
	internal sealed class AnonymousSafeObserver<T> : SafeObserver<T>
	{
		private readonly Action<T> _onNext;

		private readonly Action<Exception> _onError;

		private readonly Action _onCompleted;

		private int _isStopped;

		public AnonymousSafeObserver(Action<T> onNext, Action<Exception> onError, Action onCompleted)
		{
			_onNext = onNext;
			_onError = onError;
			_onCompleted = onCompleted;
		}

		public override void OnNext(T value)
		{
			if (_isStopped != 0)
			{
				return;
			}
			bool flag = false;
			try
			{
				_onNext(value);
				flag = true;
			}
			finally
			{
				if (!flag)
				{
					Dispose();
				}
			}
		}

		public override void OnError(Exception error)
		{
			if (Interlocked.Exchange(ref _isStopped, 1) == 0)
			{
				using (this)
				{
					_onError(error);
				}
			}
		}

		public override void OnCompleted()
		{
			if (Interlocked.Exchange(ref _isStopped, 1) == 0)
			{
				using (this)
				{
					_onCompleted();
				}
			}
		}
	}
	public class EventPattern<TEventArgs> : EventPattern<object, TEventArgs>
	{
		public EventPattern(object sender, TEventArgs e)
			: base(sender, e)
		{
		}
	}
	public class EventPattern<TSender, TEventArgs> : IEquatable<EventPattern<TSender, TEventArgs>>, IEventPattern<TSender, TEventArgs>
	{
		public TSender Sender { get; }

		public TEventArgs EventArgs { get; }

		public EventPattern(TSender sender, TEventArgs e)
		{
			Sender = sender;
			EventArgs = e;
		}

		public bool Equals(EventPattern<TSender, TEventArgs> other)
		{
			if ((object)other == null)
			{
				return false;
			}
			if ((object)this == other)
			{
				return true;
			}
			if (EqualityComparer<TSender>.Default.Equals(Sender, other.Sender))
			{
				return EqualityComparer<TEventArgs>.Default.Equals(EventArgs, other.EventArgs);
			}
			return false;
		}

		public override bool Equals(object obj)
		{
			return Equals(obj as EventPattern<TSender, TEventArgs>);
		}

		public override int GetHashCode()
		{
			int hashCode = EqualityComparer<TSender>.Default.GetHashCode(Sender);
			int hashCode2 = EqualityComparer<TEventArgs>.Default.GetHashCode(EventArgs);
			return (hashCode << 5) + (hashCode ^ hashCode2);
		}

		public static bool operator ==(EventPattern<TSender, TEventArgs> first, EventPattern<TSender, TEventArgs> second)
		{
			return object.Equals(first, second);
		}

		public static bool operator !=(EventPattern<TSender, TEventArgs> first, EventPattern<TSender, TEventArgs> second)
		{
			return !object.Equals(first, second);
		}
	}
	internal sealed class EventPatternSource<TEventArgs> : EventPatternSourceBase<object, TEventArgs>, IEventPatternSource<TEventArgs>
	{
		event EventHandler<TEventArgs> IEventPatternSource<TEventArgs>.OnNext
		{
			add
			{
				Add(value, delegate(object o, TEventArgs e)
				{
					value(o, e);
				});
			}
			remove
			{
				Remove(value);
			}
		}

		public EventPatternSource(IObservable<EventPattern<object, TEventArgs>> source, Action<Action<object, TEventArgs>, EventPattern<object, TEventArgs>> invokeHandler)
			: base(source, invokeHandler)
		{
		}
	}
	public abstract class EventPatternSourceBase<TSender, TEventArgs>
	{
		private sealed class Observer : ObserverBase<EventPattern<TSender, TEventArgs>>, ISafeObserver<EventPattern<TSender, TEventArgs>>, IObserver<EventPattern<TSender, TEventArgs>>, IDisposable
		{
			private bool _isDone;

			private bool _isAdded;

			private readonly Delegate _handler;

			private readonly object _gate = new object();

			private readonly Action<TSender, TEventArgs> _invoke;

			private readonly EventPatternSourceBase<TSender, TEventArgs> _sourceBase;

			public Observer(EventPatternSourceBase<TSender, TEventArgs> sourceBase, Delegate handler, Action<TSender, TEventArgs> invoke)
			{
				_handler = handler;
				_invoke = invoke;
				_sourceBase = sourceBase;
			}

			protected override void OnNextCore(EventPattern<TSender, TEventArgs> value)
			{
				_sourceBase._invokeHandler(_invoke, value);
			}

			protected override void OnErrorCore(Exception error)
			{
				Remove();
				error.Throw();
			}

			protected override void OnCompletedCore()
			{
				Remove();
			}

			private void Remove()
			{
				lock (_gate)
				{
					if (_isAdded)
					{
						_sourceBase.Remove(_handler);
					}
					else
					{
						_isDone = true;
					}
				}
			}

			public void SetResource(IDisposable resource)
			{
				lock (_gate)
				{
					if (!_isDone)
					{
						_sourceBase.Add(_handler, resource);
						_isAdded = true;
					}
				}
			}
		}

		private readonly IObservable<EventPattern<TSender, TEventArgs>> _source;

		private readonly Dictionary<Delegate, Stack<IDisposable>> _subscriptions;

		private readonly Action<Action<TSender, TEventArgs>, EventPattern<TSender, TEventArgs>> _invokeHandler;

		protected EventPatternSourceBase(IObservable<EventPattern<TSender, TEventArgs>> source, Action<Action<TSender, TEventArgs>, EventPattern<TSender, TEventArgs>> invokeHandler)
		{
			_source = source ?? throw new ArgumentNullException("source");
			_invokeHandler = invokeHandler ?? throw new ArgumentNullException("invokeHandler");
			_subscriptions = new Dictionary<Delegate, Stack<IDisposable>>();
		}

		protected void Add(Delegate handler, Action<TSender, TEventArgs> invoke)
		{
			if ((object)handler == null)
			{
				throw new ArgumentNullException("handler");
			}
			if (invoke == null)
			{
				throw new ArgumentNullException("invoke");
			}
			Observer observer = new Observer(this, handler, invoke);
			observer.SetResource(_source.Subscribe(observer));
		}

		private void Add(Delegate handler, IDisposable disposable)
		{
			lock (_subscriptions)
			{
				if (!_subscriptions.TryGetValue(handler, out var value))
				{
					value = (_subscriptions[handler] = new Stack<IDisposable>());
				}
				value.Push(disposable);
			}
		}

		protected void Remove(Delegate handler)
		{
			if ((object)handler == null)
			{
				throw new ArgumentNullException("handler");
			}
			IDisposable disposable = null;
			lock (_subscriptions)
			{
				if (_subscriptions.TryGetValue(handler, out var value))
				{
					disposable = value.Pop();
					if (value.Count == 0)
					{
						_subscriptions.Remove(handler);
					}
				}
			}
			disposable?.Dispose();
		}
	}
	internal sealed class EventSource<T> : IEventSource<T>
	{
		private readonly IObservable<T> _source;

		private readonly Dictionary<Delegate, Stack<IDisposable>> _subscriptions;

		private readonly Action<Action<T>, T> _invokeHandler;

		public event Action<T> OnNext
		{
			add
			{
				object gate = new object();
				bool isAdded = false;
				bool isDone = false;
				Action remove = delegate
				{
					lock (gate)
					{
						if (isAdded)
						{
							Remove(value);
						}
						else
						{
							isDone = true;
						}
					}
				};
				IDisposable disposable = _source.Subscribe(delegate(T x)
				{
					_invokeHandler(value, x);
				}, delegate(Exception ex)
				{
					remove();
					ex.Throw();
				}, remove);
				lock (gate)
				{
					if (!isDone)
					{
						Add(value, disposable);
						isAdded = true;
					}
				}
			}
			remove
			{
				Remove(value);
			}
		}

		public EventSource(IObservable<T> source, Action<Action<T>, T> invokeHandler)
		{
			_source = source;
			_invokeHandler = invokeHandler;
			_subscriptions = new Dictionary<Delegate, Stack<IDisposable>>();
		}

		private void Add(Delegate handler, IDisposable disposable)
		{
			lock (_subscriptions)
			{
				if (!_subscriptions.TryGetValue(handler, out var value))
				{
					value = (_subscriptions[handler] = new Stack<IDisposable>());
				}
				value.Push(disposable);
			}
		}

		private void Remove(Delegate handler)
		{
			IDisposable disposable = null;
			lock (_subscriptions)
			{
				Stack<IDisposable> value = new Stack<IDisposable>();
				if (_subscriptions.TryGetValue(handler, out value))
				{
					disposable = value.Pop();
					if (value.Count == 0)
					{
						_subscriptions.Remove(handler);
					}
				}
			}
			disposable?.Dispose();
		}
	}
	[Experimental]
	[AttributeUsage(AttributeTargets.All)]
	public sealed class ExperimentalAttribute : Attribute
	{
	}
	public interface IEventPattern<out TSender, out TEventArgs>
	{
		TSender Sender { get; }

		TEventArgs EventArgs { get; }
	}
	public interface IEventPatternSource<TEventArgs>
	{
		event EventHandler<TEventArgs> OnNext;
	}
	public interface IEventSource<out T>
	{
		event Action<T> OnNext;
	}
	internal sealed class AnonymousEnumerable<T> : IEnumerable<T>, IEnumerable
	{
		private readonly Func<IEnumerator<T>> _getEnumerator;

		public AnonymousEnumerable(Func<IEnumerator<T>> getEnumerator)
		{
			_getEnumerator = getEnumerator;
		}

		public IEnumerator<T> GetEnumerator()
		{
			return _getEnumerator();
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return _getEnumerator();
		}
	}
	internal sealed class AsyncLockObserver<T> : ObserverBase<T>
	{
		private readonly AsyncLock _gate;

		private readonly IObserver<T> _observer;

		public AsyncLockObserver(IObserver<T> observer, AsyncLock gate)
		{
			_gate = gate;
			_observer = observer;
		}

		protected override void OnNextCore(T value)
		{
			_gate.Wait((_observer, value), delegate((IObserver<T> _observer, T value) tuple)
			{
				tuple._observer.OnNext(tuple.value);
			});
		}

		protected override void OnErrorCore(Exception exception)
		{
			_gate.Wait((_observer, exception), delegate((IObserver<T> _observer, Exception exception) tuple)
			{
				tuple._observer.OnError(tuple.exception);
			});
		}

		protected override void OnCompletedCore()
		{
			_gate.Wait(_observer, delegate(IObserver<T> closureObserver)
			{
				closureObserver.OnCompleted();
			});
		}
	}
	internal sealed class AutoDetachObserver<T> : ObserverBase<T>, ISafeObserver<T>, IObserver<T>, IDisposable
	{
		private readonly IObserver<T> _observer;

		private IDisposable _disposable;

		public AutoDetachObserver(IObserver<T> observer)
		{
			_observer = observer;
		}

		public void SetResource(IDisposable resource)
		{
			Disposable.SetSingle(ref _disposable, resource);
		}

		protected override void OnNextCore(T value)
		{
			bool flag = false;
			try
			{
				_observer.OnNext(value);
				flag = true;
			}
			finally
			{
				if (!flag)
				{
					Dispose();
				}
			}
		}

		protected override void OnErrorCore(Exception exception)
		{
			try
			{
				_observer.OnError(exception);
			}
			finally
			{
				Dispose();
			}
		}

		protected override void OnCompletedCore()
		{
			try
			{
				_observer.OnCompleted();
			}
			finally
			{
				Dispose();
			}
		}

		protected override void Dispose(bool disposing)
		{
			base.Dispose(disposing);
			if (disposing)
			{
				Disposable.TryDispose(ref _disposable);
			}
		}
	}
	internal sealed class BinaryObserver<TLeft, TRight> : IObserver<Either<Notification<TLeft>, Notification<TRight>>>
	{
		public IObserver<TLeft> LeftObserver { get; }

		public IObserver<TRight> RightObserver { get; }

		public BinaryObserver(IObserver<TLeft> leftObserver, IObserver<TRight> rightObserver)
		{
			LeftObserver = leftObserver;
			RightObserver = rightObserver;
		}

		public BinaryObserver(Action<Notification<TLeft>> left, Action<Notification<TRight>> right)
			: this(left.ToObserver(), right.ToObserver())
		{
		}

		void IObserver<Either<Notification<TLeft>, Notification<TRight>>>.OnNext(Either<Notification<TLeft>, Notification<TRight>> value)
		{
			value.Switch(delegate(Notification<TLeft> left)
			{
				left.Accept(LeftObserver);
			}, delegate(Notification<TRight> right)
			{
				right.Accept(RightObserver);
			});
		}

		void IObserver<Either<Notification<TLeft>, Notification<TRight>>>.OnError(Exception exception)
		{
		}

		void IObserver<Either<Notification<TLeft>, Notification<TRight>>>.OnCompleted()
		{
		}
	}
	internal sealed class CheckedObserver<T> : IObserver<T>
	{
		private readonly IObserver<T> _observer;

		private int _state;

		private const int Idle = 0;

		private const int Busy = 1;

		private const int Done = 2;

		public CheckedObserver(IObserver<T> observer)
		{
			_observer = observer;
		}

		public void OnNext(T value)
		{
			CheckAccess();
			try
			{
				_observer.OnNext(value);
			}
			finally
			{
				Interlocked.Exchange(ref _state, 0);
			}
		}

		public void OnError(Exception error)
		{
			CheckAccess();
			try
			{
				_observer.OnError(error);
			}
			finally
			{
				Interlocked.Exchange(ref _state, 2);
			}
		}

		public void OnCompleted()
		{
			CheckAccess();
			try
			{
				_observer.OnCompleted();
			}
			finally
			{
				Interlocked.Exchange(ref _state, 2);
			}
		}

		private void CheckAccess()
		{
			switch (Interlocked.CompareExchange(ref _state, 1, 0))
			{
			case 1:
				throw new InvalidOperationException(Strings_Core.REENTRANCY_DETECTED);
			case 2:
				throw new InvalidOperationException(Strings_Core.OBSERVER_TERMINATED);
			}
		}
	}
	internal abstract class ConcatSink<TSource> : TailRecursiveSink<TSource>
	{
		protected ConcatSink(IObserver<TSource> observer)
			: base(observer)
		{
		}

		protected override IEnumerable<IObservable<TSource>> Extract(IObservable<TSource> source)
		{
			return (source as IConcatenatable<TSource>)?.GetSources();
		}

		public override void OnCompleted()
		{
			Recurse();
		}
	}
	internal static class Constants_Core
	{
		private const string ObsoleteRefactoring = "This property is no longer supported due to refactoring of the API surface and elimination of platform-specific dependencies.";

		public const string ObsoleteSchedulerNewthread = "This property is no longer supported due to refactoring of the API surface and elimination of platform-specific dependencies. Please use NewThreadScheduler.Default to obtain an instance of this scheduler type.";

		public const string ObsoleteSchedulerTaskpool = "This property is no longer supported due to refactoring of the API surface and elimination of platform-specific dependencies. Please use TaskPoolScheduler.Default to obtain an instance of this scheduler type.";

		public const string ObsoleteSchedulerThreadpool = "This property is no longer supported due to refactoring of the API surface and elimination of platform-specific dependencies. Consider using Scheduler.Default to obtain the platform's most appropriate pool-based scheduler. In order to access a specific pool-based scheduler, please add a reference to the System.Reactive.PlatformServices assembly for your target platform and use the appropriate scheduler in the System.Reactive.Concurrency namespace.";

		public const string ObsoleteSchedulerequired = "This instance property is no longer supported. Use CurrentThreadScheduler.IsScheduleRequired instead.";
	}
	internal static class Constants_Linq
	{
		public const string UseAsync = "This blocking operation is no longer supported. Instead, use the async version in combination with C# and Visual Basic async/await support. In case you need a blocking operation, use Wait or convert the resulting observable sequence to a Task object and block.";

		public const string UseTaskFromAsyncPattern = "This conversion is no longer supported. Replace use of the Begin/End asynchronous method pair with a new Task-based async method, and convert the result using ToObservable. If no Task-based async method is available, use Task.Factory.FromAsync to obtain a Task object.";
	}
	internal abstract class Either<TLeft, TRight>
	{
		public sealed class Left : Either<TLeft, TRight>, IEquatable<Left>
		{
			public TLeft Value { get; }

			public Left(TLeft value)
			{
				Value = value;
			}

			public override TResult Switch<TResult>(Func<TLeft, TResult> caseLeft, Func<TRight, TResult> caseRight)
			{
				return caseLeft(Value);
			}

			public override void Switch(Action<TLeft> caseLeft, Action<TRight> caseRight)
			{
				caseLeft(Value);
			}

			public bool Equals(Left other)
			{
				if (other == this)
				{
					return true;
				}
				if (other == null)
				{
					return false;
				}
				return EqualityComparer<TLeft>.Default.Equals(Value, other.Value);
			}

			public override bool Equals(object obj)
			{
				return Equals(obj as Left);
			}

			public override int GetHashCode()
			{
				return EqualityComparer<TLeft>.Default.GetHashCode(Value);
			}

			public override string ToString()
			{
				return string.Format(CultureInfo.CurrentCulture, "Left({0})", Value);
			}
		}

		public sealed class Right : Either<TLeft, TRight>, IEquatable<Right>
		{
			public TRight Value { get; }

			public Right(TRight value)
			{
				Value = value;
			}

			public override TResult Switch<TResult>(Func<TLeft, TResult> caseLeft, Func<TRight, TResult> caseRight)
			{
				return caseRight(Value);
			}

			public override void Switch(Action<TLeft> caseLeft, Action<TRight> caseRight)
			{
				caseRight(Value);
			}

			public bool Equals(Right other)
			{
				if (other == this)
				{
					return true;
				}
				if (other == null)
				{
					return false;
				}
				return EqualityComparer<TRight>.Default.Equals(Value, other.Value);
			}

			public override bool Equals(object obj)
			{
				return Equals(obj as Right);
			}

			public override int GetHashCode()
			{
				return EqualityComparer<TRight>.Default.GetHashCode(Value);
			}

			public override string ToString()
			{
				return string.Format(CultureInfo.CurrentCulture, "Right({0})", Value);
			}
		}

		private Either()
		{
		}

		public static Either<TLeft, TRight> CreateLeft(TLeft value)
		{
			return new Left(value);
		}

		public static Either<TLeft, TRight> CreateRight(TRight value)
		{
			return new Right(value);
		}

		public abstract TResult Switch<TResult>(Func<TLeft, TResult> caseLeft, Func<TRight, TResult> caseRight);

		public abstract void Switch(Action<TLeft> caseLeft, Action<TRight> caseRight);
	}
	internal static class ExceptionHelper
	{
		private sealed class TerminatedException : Exception
		{
			internal TerminatedException()
				: base("No further exceptions")
			{
			}
		}

		public static Exception Terminated { get; } = new TerminatedException();


		public static bool TrySetException(ref Exception field, Exception ex)
		{
			return Interlocked.CompareExchange(ref field, ex, null) == null;
		}

		public static Exception Terminate(ref Exception field)
		{
			Exception ex = Volatile.Read(ref field);
			if (ex != Terminated)
			{
				ex = Interlocked.Exchange(ref field, Terminated);
			}
			return ex;
		}

		public static bool TryAddException(ref Exception field, Exception ex)
		{
			Exception ex2;
			Exception value;
			do
			{
				ex2 = Volatile.Read(ref field);
				if (ex2 == Terminated)
				{
					return false;
				}
				value = ((ex2 == null) ? ex : ((!(ex2 is AggregateException ex3)) ? new AggregateException(ex2, ex) : new AggregateException(new List<Exception>(ex3.InnerExceptions) { ex })));
			}
			while (Interlocked.CompareExchange(ref field, value, ex2) != ex2);
			return true;
		}
	}
	internal static class ExceptionHelpers
	{
		private static readonly Lazy<IExceptionServices> Services = new Lazy<IExceptionServices>(Initialize);

		public static void Throw(this Exception exception)
		{
			Services.Value.Rethrow(exception);
		}

		public static void ThrowIfNotNull(this Exception exception)
		{
			if (exception != null)
			{
				Services.Value.Rethrow(exception);
			}
		}

		private static IExceptionServices Initialize()
		{
			return PlatformEnlightenmentProvider.Current.GetService<IExceptionServices>(Array.Empty<object>()) ?? new DefaultExceptionServices();
		}
	}
	internal static class HalfSerializer
	{
		public static void ForwardOnNext<T>(ISink<T> sink, T item, ref int wip, ref Exception error)
		{
			if (Interlocked.CompareExchange(ref wip, 1, 0) == 0)
			{
				sink.ForwardOnNext(item);
				if (Interlocked.Decrement(ref wip) != 0)
				{
					Exception ex = error;
					if (ex != ExceptionHelper.Terminated)
					{
						error = ExceptionHelper.Terminated;
						sink.ForwardOnError(ex);
					}
					else
					{
						sink.ForwardOnCompleted();
					}
				}
			}
			else if (error == null)
			{
				Trace.TraceWarning("OnNext called while another OnNext call was in progress on the same Observer.");
			}
		}

		public static void ForwardOnError<T>(ISink<T> sink, Exception ex, ref int wip, ref Exception error)
		{
			if (ExceptionHelper.TrySetException(ref error, ex) && Interlocked.Increment(ref wip) == 1)
			{
				error = ExceptionHelper.Terminated;
				sink.ForwardOnError(ex);
			}
		}

		public static void ForwardOnCompleted<T>(ISink<T> sink, ref int wip, ref Exception error)
		{
			if (ExceptionHelper.TrySetException(ref error, ExceptionHelper.Terminated) && Interlocked.Increment(ref wip) == 1)
			{
				sink.ForwardOnCompleted();
			}
		}
	}
	internal static class Helpers
	{
		public static int? GetLength<T>(IEnumerable<T> source)
		{
			if (source is T[] array)
			{
				return array.Length;
			}
			if (source is IList<T> list)
			{
				return list.Count;
			}
			return null;
		}

		public static IObservable<T> Unpack<T>(IObservable<T> source)
		{
			bool flag;
			do
			{
				flag = false;
				if (source is IEvaluatableObservable<T> evaluatableObservable)
				{
					source = evaluatableObservable.Eval();
					flag = true;
				}
			}
			while (flag);
			return source;
		}

		public static bool All(this bool[] values)
		{
			for (int i = 0; i < values.Length; i++)
			{
				if (!values[i])
				{
					return false;
				}
			}
			return true;
		}

		public static bool AllExcept(this bool[] values, int index)
		{
			for (int i = 0; i < values.Length; i++)
			{
				if (i != index && !values[i])
				{
					return false;
				}
			}
			return true;
		}
	}
	internal interface IConcatenatable<out TSource>
	{
		IEnumerable<IObservable<TSource>> GetSources();
	}
	internal abstract class IdentitySink<T> : Sink<T, T>
	{
		protected IdentitySink(IObserver<T> observer)
			: base(observer)
		{
		}

		public override void OnNext(T value)
		{
			ForwardOnNext(value);
		}
	}
	internal interface IEvaluatableObservable<out T>
	{
		IObservable<T> Eval();
	}
	internal sealed class ImmutableList<T>
	{
		public static readonly ImmutableList<T> Empty = new ImmutableList<T>();

		private readonly T[] _data;

		public T[] Data => _data;

		private ImmutableList()
		{
			_data = Array.Empty<T>();
		}

		public ImmutableList(T[] data)
		{
			_data = data;
		}

		public ImmutableList<T> Add(T value)
		{
			T[] array = new T[_data.Length + 1];
			Array.Copy(_data, array, _data.Length);
			array[_data.Length] = value;
			return new ImmutableList<T>(array);
		}

		public ImmutableList<T> Remove(T value)
		{
			int num = IndexOf(value);
			if (num < 0)
			{
				return this;
			}
			int num2 = _data.Length;
			if (num2 == 1)
			{
				return Empty;
			}
			T[] array = new T[num2 - 1];
			Array.Copy(_data, 0, array, 0, num);
			Array.Copy(_data, num + 1, array, num, num2 - num - 1);
			return new ImmutableList<T>(array);
		}

		private int IndexOf(T value)
		{
			for (int i = 0; i < _data.Length; i++)
			{
				if (object.Equals(_data[i], value))
				{
					return i;
				}
			}
			return -1;
		}
	}
	internal interface ISafeObserver<in T> : IObserver<T>, IDisposable
	{
		void SetResource(IDisposable resource);
	}
	internal sealed class Lookup<K, E> : ILookup<K, E>, IEnumerable<IGrouping<K, E>>, IEnumerable
	{
		private sealed class Grouping : IGrouping<K, E>, IEnumerable<E>, IEnumerable
		{
			private readonly KeyValuePair<K, List<E>> _keyValuePair;

			public K Key
			{
				get
				{
					KeyValuePair<K, List<E>> keyValuePair = _keyValuePair;
					return keyValuePair.Key;
				}
			}

			public Grouping(KeyValuePair<K, List<E>> keyValuePair)
			{
				_keyValuePair = keyValuePair;
			}

			public IEnumerator<E> GetEnumerator()
			{
				KeyValuePair<K, List<E>> keyValuePair = _keyValuePair;
				return keyValuePair.Value.GetEnumerator();
			}

			IEnumerator IEnumerable.GetEnumerator()
			{
				return GetEnumerator();
			}
		}

		private readonly Dictionary<K, List<E>> _dictionary;

		public int Count => _dictionary.Count;

		public IEnumerable<E> this[K key]
		{
			get
			{
				if (!_dictionary.TryGetValue(key, out var value))
				{
					return Enumerable.Empty<E>();
				}
				return Hide(value);
			}
		}

		public Lookup(IEqualityComparer<K> comparer)
		{
			_dictionary = new Dictionary<K, List<E>>(comparer);
		}

		public void Add(K key, E element)
		{
			if (!_dictionary.TryGetValue(key, out var value))
			{
				value = (_dictionary[key] = new List<E>());
			}
			value.Add(element);
		}

		public bool Contains(K key)
		{
			return _dictionary.ContainsKey(key);
		}

		private static IEnumerable<E> Hide(List<E> elements)
		{
			return elements.Skip(0);
		}

		public IEnumerator<IGrouping<K, E>> GetEnumerator()
		{
			foreach (KeyValuePair<K, List<E>> item in _dictionary)
			{
				yield return new Grouping(item);
			}
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return GetEnumerator();
		}
	}
	internal sealed class NopObserver<T> : IObserver<T>
	{
		public static readonly IObserver<T> Instance = new NopObserver<T>();

		public void OnCompleted()
		{
		}

		public void OnError(Exception error)
		{
		}

		public void OnNext(T value)
		{
		}
	}
	internal sealed class PriorityQueue<T> where T : IComparable<T>
	{
		private struct IndexedItem : IComparable<IndexedItem>
		{
			public T Value;

			public long Id;

			public int CompareTo(IndexedItem other)
			{
				int num = Value.CompareTo(other.Value);
				if (num == 0)
				{
					num = Id.CompareTo(other.Id);
				}
				return num;
			}
		}

		private long _count = long.MinValue;

		private IndexedItem[] _items;

		private int _size;

		public int Count => _size;

		public PriorityQueue()
			: this(16)
		{
		}

		public PriorityQueue(int capacity)
		{
			_items = new IndexedItem[capacity];
			_size = 0;
		}

		private bool IsHigherPriority(int left, int right)
		{
			return _items[left].CompareTo(_items[right]) < 0;
		}

		private int Percolate(int index)
		{
			if (index >= _size || index < 0)
			{
				return index;
			}
			int num = (index - 1) / 2;
			while (num >= 0 && num != index && IsHigherPriority(index, num))
			{
				IndexedItem indexedItem = _items[index];
				_items[index] = _items[num];
				_items[num] = indexedItem;
				index = num;
				num = (index - 1) / 2;
			}
			return index;
		}

		private void Heapify(int index)
		{
			if (index >= _size || index < 0)
			{
				return;
			}
			while (true)
			{
				int num = 2 * index + 1;
				int num2 = 2 * index + 2;
				int num3 = index;
				if (num < _size && IsHigherPriority(num, num3))
				{
					num3 = num;
				}
				if (num2 < _size && IsHigherPriority(num2, num3))
				{
					num3 = num2;
				}
				if (num3 != index)
				{
					IndexedItem indexedItem = _items[index];
					_items[index] = _items[num3];
					_items[num3] = indexedItem;
					index = num3;
					continue;
				}
				break;
			}
		}

		public T Peek()
		{
			if (_size == 0)
			{
				throw new InvalidOperationException(Strings_Core.HEAP_EMPTY);
			}
			return _items[0].Value;
		}

		private void RemoveAt(int index)
		{
			_items[index] = _items[--_size];
			_items[_size] = default(IndexedItem);
			if (Percolate(index) == index)
			{
				Heapify(index);
			}
			if (_size < _items.Length / 4)
			{
				IndexedItem[] items = _items;
				_items = new IndexedItem[_items.Length / 2];
				Array.Copy(items, 0, _items, 0, _size);
			}
		}

		public T Dequeue()
		{
			T result = Peek();
			RemoveAt(0);
			return result;
		}

		public void Enqueue(T item)
		{
			if (_size >= _items.Length)
			{
				IndexedItem[] items = _items;
				_items = new IndexedItem[_items.Length * 2];
				Array.Copy(items, _items, items.Length);
			}
			int num = _size++;
			_items[num] = new IndexedItem
			{
				Value = item,
				Id = ++_count
			};
			Percolate(num);
		}

		public bool Remove(T item)
		{
			for (int i = 0; i < _size; i++)
			{
				if (EqualityComparer<T>.Default.Equals(_items[i].Value, item))
				{
					RemoveAt(i);
					return true;
				}
			}
			return false;
		}
	}
	internal interface IProducer<out TSource> : IObservable<TSource>
	{
		IDisposable SubscribeRaw(IObserver<TSource> observer, bool enableSafeguard);
	}
	internal abstract class BasicProducer<TSource> : IProducer<TSource>, IObservable<TSource>
	{
		public IDisposable Subscribe(IObserver<TSource> observer)
		{
			if (observer == null)
			{
				throw new ArgumentNullException("observer");
			}
			return SubscribeRaw(observer, enableSafeguard: true);
		}

		public IDisposable SubscribeRaw(IObserver<TSource> observer, bool enableSafeguard)
		{
			ISafeObserver<TSource> safeObserver = null;
			if (enableSafeguard)
			{
				observer = (safeObserver = SafeObserver<TSource>.Wrap(observer));
			}
			IDisposable disposable;
			if (CurrentThreadScheduler.IsScheduleRequired)
			{
				SingleAssignmentDisposable singleAssignmentDisposable = new SingleAssignmentDisposable();
				CurrentThreadScheduler.Instance.ScheduleAction((this, singleAssignmentDisposable, observer), ((BasicProducer<TSource> @this, SingleAssignmentDisposable runAssignable, IObserver<TSource> observer) tuple) => tuple.runAssignable.Disposable = tuple.@this.Run(tuple.observer));
				disposable = singleAssignmentDisposable;
			}
			else
			{
				disposable = Run(observer);
			}
			safeObserver?.SetResource(disposable);
			return disposable;
		}

		protected abstract IDisposable Run(IObserver<TSource> observer);
	}
	internal abstract class Producer<TTarget, TSink> : IProducer<TTarget>, IObservable<TTarget> where TSink : IDisposable
	{
		public IDisposable Subscribe(IObserver<TTarget> observer)
		{
			if (observer == null)
			{
				throw new ArgumentNullException("observer");
			}
			return SubscribeRaw(observer, enableSafeguard: true);
		}

		public IDisposable SubscribeRaw(IObserver<TTarget> observer, bool enableSafeguard)
		{
			ISafeObserver<TTarget> safeObserver = null;
			if (enableSafeguard)
			{
				observer = (safeObserver = SafeObserver<TTarget>.Wrap(observer));
			}
			TSink val = CreateSink(observer);
			safeObserver?.SetResource(val);
			if (CurrentThreadScheduler.IsScheduleRequired)
			{
				CurrentThreadScheduler.Instance.ScheduleAction((this, val), delegate((Producer<TTarget, TSink> @this, TSink sink) tuple)
				{
					tuple.@this.Run(tuple.sink);
				});
			}
			else
			{
				Run(val);
			}
			return val;
		}

		protected abstract void Run(TSink sink);

		protected abstract TSink CreateSink(IObserver<TTarget> observer);
	}
	internal static class ReflectionUtils
	{
		public static TDelegate CreateDelegate<TDelegate>(object o, MethodInfo method)
		{
			return (TDelegate)(object)Delegate.CreateDelegate(typeof(TDelegate), o, method);
		}

		public static Delegate CreateDelegate(Type delegateType, object o, MethodInfo method)
		{
			return Delegate.CreateDelegate(delegateType, o, method);
		}

		public static void GetEventMethods<TSender, TEventArgs>(Type targetType, object target, string eventName, out MethodInfo addMethod, out MethodInfo removeMethod, out Type delegateType, out bool isWinRT)
		{
			EventInfo eventInfo = null;
			if (target == null)
			{
				eventInfo = targetType.GetEventEx(eventName, isStatic: true);
				if (eventInfo == null)
				{
					throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Strings_Linq.COULD_NOT_FIND_STATIC_EVENT, eventName, targetType.FullName));
				}
			}
			else
			{
				eventInfo = targetType.GetEventEx(eventName, isStatic: false);
				if (eventInfo == null)
				{
					throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Strings_Linq.COULD_NOT_FIND_INSTANCE_EVENT, eventName, targetType.FullName));
				}
			}
			addMethod = eventInfo.GetAddMethod();
			removeMethod = eventInfo.GetRemoveMethod();
			if (addMethod == null)
			{
				throw new InvalidOperationException(Strings_Linq.EVENT_MISSING_ADD_METHOD);
			}
			if (removeMethod == null)
			{
				throw new InvalidOperationException(Strings_Linq.EVENT_MISSING_REMOVE_METHOD);
			}
			ParameterInfo[] parameters = addMethod.GetParameters();
			if (parameters.Length != 1)
			{
				throw new InvalidOperationException(Strings_Linq.EVENT_ADD_METHOD_SHOULD_TAKE_ONE_PARAMETER);
			}
			ParameterInfo[] parameters2 = removeMethod.GetParameters();
			if (parameters2.Length != 1)
			{
				throw new InvalidOperationException(Strings_Linq.EVENT_REMOVE_METHOD_SHOULD_TAKE_ONE_PARAMETER);
			}
			isWinRT = false;
			if (addMethod.ReturnType == typeof(EventRegistrationToken))
			{
				isWinRT = true;
				if (parameters2[0].ParameterType != typeof(EventRegistrationToken))
				{
					throw new InvalidOperationException(Strings_Linq.EVENT_WINRT_REMOVE_METHOD_SHOULD_TAKE_ERT);
				}
			}
			delegateType = parameters[0].ParameterType;
			MethodInfo? method = delegateType.GetMethod("Invoke");
			ParameterInfo[] parameters3 = method.GetParameters();
			if (parameters3.Length != 2)
			{
				throw new InvalidOperationException(Strings_Linq.EVENT_PATTERN_REQUIRES_TWO_PARAMETERS);
			}
			if (!typeof(TSender).IsAssignableFrom(parameters3[0].ParameterType))
			{
				throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Strings_Linq.EVENT_SENDER_NOT_ASSIGNABLE, typeof(TSender).FullName));
			}
			if (!typeof(TEventArgs).IsAssignableFrom(parameters3[1].ParameterType))
			{
				throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Strings_Linq.EVENT_ARGS_NOT_ASSIGNABLE, typeof(TEventArgs).FullName));
			}
			if (method.ReturnType != typeof(void))
			{
				throw new InvalidOperationException(Strings_Linq.EVENT_MUST_RETURN_VOID);
			}
		}

		public static EventInfo GetEventEx(this Type type, string name, bool isStatic)
		{
			return type.GetEvent(name, isStatic ? (BindingFlags.Static | BindingFlags.Public) : (BindingFlags.Instance | BindingFlags.Public));
		}
	}
	internal abstract class SafeObserver<TSource> : ISafeObserver<TSource>, IObserver<TSource>, IDisposable
	{
		private sealed class WrappingSafeObserver : SafeObserver<TSource>
		{
			private readonly IObserver<TSource> _observer;

			public WrappingSafeObserver(IObserver<TSource> observer)
			{
				_observer = observer;
			}

			public override void OnNext(TSource value)
			{
				bool flag = false;
				try
				{
					_observer.OnNext(value);
					flag = true;
				}
				finally
				{
					if (!flag)
					{
						Dispose();
					}
				}
			}

			public override void OnError(Exception error)
			{
				using (this)
				{
					_observer.OnError(error);
				}
			}

			public override void OnCompleted()
			{
				using (this)
				{
					_observer.OnCompleted();
				}
			}
		}

		private IDisposable _disposable;

		public static ISafeObserver<TSource> Wrap(IObserver<TSource> observer)
		{
			if (observer is AnonymousObserver<TSource> anonymousObserver)
			{
				return anonymousObserver.MakeSafe();
			}
			return new WrappingSafeObserver(observer);
		}

		public abstract void OnNext(TSource value);

		public abstract void OnError(Exception error);

		public abstract void OnCompleted();

		public void SetResource(IDisposable resource)
		{
			Disposable.SetSingle(ref _disposable, resource);
		}

		public void Dispose()
		{
			Dispose(disposing: true);
		}

		protected virtual void Dispose(bool disposing)
		{
			if (disposing)
			{
				Disposable.TryDispose(ref _disposable);
			}
		}
	}
	internal class ScheduledObserver<T> : ObserverBase<T>, IScheduledObserver<T>, IObserver<T>, IDisposable
	{
		private sealed class SemaphoreSlimRelease : IDisposable
		{
			private SemaphoreSlim _dispatcherEvent;

			public SemaphoreSlimRelease(SemaphoreSlim dispatcherEvent)
			{
				Volatile.Write(ref _dispatcherEvent, dispatcherEvent);
			}

			public void Dispose()
			{
				Interlocked.Exchange(ref _dispatcherEvent, null)?.Release();
			}
		}

		private int _state;

		private const int Stopped = 0;

		private const int Running = 1;

		private const int Pending = 2;

		private const int Faulted = 9;

		private readonly ConcurrentQueue<T> _queue = new ConcurrentQueue<T>();

		private bool _failed;

		private Exception _error;

		private bool _completed;

		private readonly IObserver<T> _observer;

		private readonly IScheduler _scheduler;

		private readonly ISchedulerLongRunning _longRunning;

		private IDisposable _disposable;

		private readonly object _dispatcherInitGate = new object();

		private readonly SemaphoreSlim _dispatcherEvent;

		private readonly IDisposable _dispatcherEventRelease;

		private IDisposable _dispatcherJob;

		public ScheduledObserver(IScheduler scheduler, IObserver<T> observer)
		{
			_scheduler = scheduler;
			_observer = observer;
			_longRunning = _scheduler.AsLongRunning();
			if (_longRunning != null)
			{
				_dispatcherEvent = new SemaphoreSlim(0);
				_dispatcherEventRelease = new SemaphoreSlimRelease(_dispatcherEvent);
			}
		}

		private void EnsureDispatcher()
		{
			if (_dispatcherJob != null)
			{
				return;
			}
			lock (_dispatcherInitGate)
			{
				if (_dispatcherJob == null)
				{
					_dispatcherJob = _longRunning.ScheduleLongRunning(Dispatch);
					Disposable.TrySetSerial(ref _disposable, StableCompositeDisposable.Create(_dispatcherJob, _dispatcherEventRelease));
				}
			}
		}

		private void Dispatch(ICancelable cancel)
		{
			do
			{
				_dispatcherEvent.Wait();
				if (cancel.IsDisposed)
				{
					return;
				}
				T result = default(T);
				while (_queue.TryDequeue(out result))
				{
					try
					{
						_observer.OnNext(result);
					}
					catch
					{
						T result2;
						while (_queue.TryDequeue(out result2))
						{
						}
						throw;
					}
					_dispatcherEvent.Wait();
					if (cancel.IsDisposed)
					{
						return;
					}
				}
				if (_failed)
				{
					_observer.OnError(_error);
					Dispose();
					return;
				}
			}
			while (!_completed);
			_observer.OnCompleted();
			Dispose();
		}

		public void EnsureActive()
		{
			EnsureActive(1);
		}

		public void EnsureActive(int n)
		{
			if (_longRunning != null)
			{
				if (n > 0)
				{
					_dispatcherEvent.Release(n);
				}
				EnsureDispatcher();
			}
			else
			{
				EnsureActiveSlow();
			}
		}

		private void EnsureActiveSlow()
		{
			bool flag = false;
			do
			{
				IL_0002:
				switch (Interlocked.CompareExchange(ref _state, 1, 0))
				{
				default:
					goto IL_0002;
				case 0:
					flag = true;
					break;
				case 9:
					return;
				case 1:
					continue;
				case 2:
					break;
				}
				break;
			}
			while (Interlocked.CompareExchange(ref _state, 2, 1) != 1);
			if (flag)
			{
				Disposable.TrySetSerial(ref _disposable, _scheduler.Schedule<object>(null, Run));
			}
		}

		private void Run(object state, Action<object> recurse)
		{
			T result = default(T);
			while (!_queue.TryDequeue(out result))
			{
				if (_failed)
				{
					if (_queue.IsEmpty)
					{
						Interlocked.Exchange(ref _state, 0);
						_observer.OnError(_error);
						Dispose();
						return;
					}
				}
				else if (_completed)
				{
					if (_queue.IsEmpty)
					{
						Interlocked.Exchange(ref _state, 0);
						_observer.OnCompleted();
						Dispose();
						return;
					}
				}
				else
				{
					int num = Interlocked.CompareExchange(ref _state, 0, 1);
					if (num == 1 || num == 9)
					{
						return;
					}
					_state = 1;
				}
			}
			Interlocked.Exchange(ref _state, 1);
			try
			{
				_observer.OnNext(result);
			}
			catch
			{
				Interlocked.Exchange(ref _state, 9);
				T result2;
				while (_queue.TryDequeue(out result2))
				{
				}
				throw;
			}
			recurse(state);
		}

		protected override void OnNextCore(T value)
		{
			_queue.Enqueue(value);
		}

		protected override void OnErrorCore(Exception exception)
		{
			_error = exception;
			_failed = true;
		}

		protected override void OnCompletedCore()
		{
			_completed = true;
		}

		protected override void Dispose(bool disposing)
		{
			base.Dispose(disposing);
			if (disposing)
			{
				Disposable.TryDispose(ref _disposable);
			}
		}
	}
	internal sealed class ObserveOnObserver<T> : ScheduledObserver<T>
	{
		private IDisposable _run;

		public ObserveOnObserver(IScheduler scheduler, IObserver<T> observer)
			: base(scheduler, observer)
		{
		}

		public void Run(IObservable<T> source)
		{
			Disposable.SetSingle(ref _run, source.SubscribeSafe(this));
		}

		protected override void OnNextCore(T value)
		{
			base.OnNextCore(value);
			EnsureActive();
		}

		protected override void OnErrorCore(Exception exception)
		{
			base.OnErrorCore(exception);
			EnsureActive();
		}

		protected override void OnCompletedCore()
		{
			base.OnCompletedCore();
			EnsureActive();
		}

		protected override void Dispose(bool disposing)
		{
			base.Dispose(disposing);
			if (disposing)
			{
				Disposable.TryDispose(ref _run);
			}
		}
	}
	internal interface IScheduledObserver<T> : IObserver<T>, IDisposable
	{
		void EnsureActive();

		void EnsureActive(int count);
	}
	internal sealed class ObserveOnObserverNew<T> : IdentitySink<T>
	{
		private readonly IScheduler _scheduler;

		private readonly ConcurrentQueue<T> _queue;

		private IDisposable _task;

		private int _wip;

		private bool _done;

		private Exception _error;

		private bool _disposed;

		private static readonly Func<IScheduler, ObserveOnObserverNew<T>, IDisposable> DrainShortRunningFunc = (IScheduler scheduler, ObserveOnObserverNew<T> self) => self.DrainShortRunning(scheduler);

		public ObserveOnObserverNew(IScheduler scheduler, IObserver<T> downstream)
			: base(downstream)
		{
			_scheduler = scheduler;
			_queue = new ConcurrentQueue<T>();
		}

		protected override void Dispose(bool disposing)
		{
			Volatile.Write(ref _disposed, value: true);
			base.Dispose(disposing);
			if (disposing)
			{
				Disposable.TryDispose(ref _task);
				Clear(_queue);
			}
		}

		private void Clear(ConcurrentQueue<T> q)
		{
			T result;
			while (q.TryDequeue(out result))
			{
			}
		}

		public override void OnCompleted()
		{
			Volatile.Write(ref _done, value: true);
			Schedule();
		}

		public override void OnError(Exception error)
		{
			_error = error;
			Volatile.Write(ref _done, value: true);
			Schedule();
		}

		public override void OnNext(T value)
		{
			_queue.Enqueue(value);
			Schedule();
		}

		private void Schedule()
		{
			if (Interlocked.Increment(ref _wip) == 1)
			{
				SingleAssignmentDisposable singleAssignmentDisposable = new SingleAssignmentDisposable();
				if (Disposable.TrySetMultiple(ref _task, singleAssignmentDisposable))
				{
					singleAssignmentDisposable.Disposable = _scheduler.Schedule(this, DrainShortRunningFunc);
				}
				if (Volatile.Read(ref _disposed))
				{
					Clear(_queue);
				}
			}
		}

		private IDisposable DrainShortRunning(IScheduler recursiveScheduler)
		{
			DrainStep(_queue);
			if (Interlocked.Decrement(ref _wip) != 0)
			{
				IDisposable value = recursiveScheduler.Schedule(this, DrainShortRunningFunc);
				Disposable.TrySetMultiple(ref _task, value);
			}
			return Disposable.Empty;
		}

		private void DrainStep(ConcurrentQueue<T> q)
		{
			if (Volatile.Read(ref _disposed))
			{
				Clear(q);
				return;
			}
			bool flag = Volatile.Read(ref _done);
			if (flag)
			{
				Exception error = _error;
				if (error != null)
				{
					Volatile.Write(ref _disposed, value: true);
					ForwardOnError(error);
					return;
				}
			}
			T result;
			bool flag2 = !q.TryDequeue(out result);
			if (flag && flag2)
			{
				Volatile.Write(ref _disposed, value: true);
				ForwardOnCompleted();
			}
			else if (!flag2)
			{
				ForwardOnNext(result);
			}
		}
	}
	internal sealed class ObserveOnObserverLongRunning<TSource> : IdentitySink<TSource>
	{
		private readonly ISchedulerLongRunning _scheduler;

		private readonly ConcurrentQueue<TSource> _queue;

		private readonly object _suspendGuard;

		private long _wip;

		private bool _done;

		private Exception _error;

		private bool _disposed;

		private int _runDrainOnce;

		private IDisposable _drainTask;

		private static readonly Action<ObserveOnObserverLongRunning<TSource>, ICancelable> DrainLongRunning = delegate(ObserveOnObserverLongRunning<TSource> self, ICancelable cancelable)
		{
			self.Drain();
		};

		public ObserveOnObserverLongRunning(ISchedulerLongRunning scheduler, IObserver<TSource> observer)
			: base(observer)
		{
			_scheduler = scheduler;
			_queue = new ConcurrentQueue<TSource>();
			_suspendGuard = new object();
		}

		public override void OnCompleted()
		{
			Volatile.Write(ref _done, value: true);
			Schedule();
		}

		public override void OnError(Exception error)
		{
			_error = error;
			Volatile.Write(ref _done, value: true);
			Schedule();
		}

		public override void OnNext(TSource value)
		{
			_queue.Enqueue(value);
			Schedule();
		}

		private void Schedule()
		{
			if (Volatile.Read(ref _runDrainOnce) == 0 && Interlocked.CompareExchange(ref _runDrainOnce, 1, 0) == 0)
			{
				Disposable.SetSingle(ref _drainTask, _scheduler.ScheduleLongRunning(this, DrainLongRunning));
			}
			if (Interlocked.Increment(ref _wip) == 1)
			{
				lock (_suspendGuard)
				{
					Monitor.Pulse(_suspendGuard);
				}
			}
		}

		protected override void Dispose(bool disposing)
		{
			Volatile.Write(ref _disposed, value: true);
			lock (_suspendGuard)
			{
				Monitor.Pulse(_suspendGuard);
			}
			Disposable.TryDispose(ref _drainTask);
			base.Dispose(disposing);
		}

		private void Drain()
		{
			ConcurrentQueue<TSource> queue = _queue;
			while (true)
			{
				if (Volatile.Read(ref _disposed))
				{
					TSource result;
					while (queue.TryDequeue(out result))
					{
					}
					return;
				}
				bool num = Volatile.Read(ref _done);
				TSource result2;
				bool flag = queue.TryDequeue(out result2);
				if (num && !flag)
				{
					break;
				}
				if (flag)
				{
					ForwardOnNext(result2);
					if (Interlocked.Decrement(ref _wip) != 0L)
					{
						continue;
					}
				}
				if (Volatile.Read(ref _wip) != 0L || Volatile.Read(ref _disposed))
				{
					continue;
				}
				object suspendGuard = _suspendGuard;
				if (Monitor.TryEnter(suspendGuard))
				{
					if (Volatile.Read(ref _wip) == 0L && !Volatile.Read(ref _disposed))
					{
						Monitor.Wait(suspendGuard);
					}
					Monitor.Exit(suspendGuard);
				}
			}
			Exception error = _error;
			if (error != null)
			{
				ForwardOnError(error);
			}
			else
			{
				ForwardOnCompleted();
			}
		}
	}
	internal interface ISink<in TTarget>
	{
		void ForwardOnNext(TTarget value);

		void ForwardOnCompleted();

		void ForwardOnError(Exception error);
	}
	internal abstract class Sink<TTarget> : ISink<TTarget>, IDisposable
	{
		private IDisposable _upstream;

		private volatile IObserver<TTarget> _observer;

		protected Sink(IObserver<TTarget> observer)
		{
			_observer = observer;
		}

		public void Dispose()
		{
			if (Interlocked.Exchange(ref _observer, NopObserver<TTarget>.Instance) != NopObserver<TTarget>.Instance)
			{
				Dispose(disposing: true);
			}
		}

		protected virtual void Dispose(bool disposing)
		{
			Disposable.TryDispose(ref _upstream);
		}

		public void ForwardOnNext(TTarget value)
		{
			_observer.OnNext(value);
		}

		public void ForwardOnCompleted()
		{
			_observer.OnCompleted();
			Dispose();
		}

		public void ForwardOnError(Exception error)
		{
			_observer.OnError(error);
			Dispose();
		}

		protected void SetUpstream(IDisposable upstream)
		{
			Disposable.SetSingle(ref _upstream, upstream);
		}

		protected void DisposeUpstream()
		{
			Disposable.TryDispose(ref _upstream);
		}
	}
	internal abstract class Sink<TSource, TTarget> : Sink<TTarget>, IObserver<TSource>
	{
		private sealed class @_ : IObserver<TTarget>
		{
			private readonly Sink<TSource, TTarget> _forward;

			public _(Sink<TSource, TTarget> forward)
			{
				_forward = forward;
			}

			public void OnNext(TTarget value)
			{
				_forward.ForwardOnNext(value);
			}

			public void OnError(Exception error)
			{
				_forward.ForwardOnError(error);
			}

			public void OnCompleted()
			{
				_forward.ForwardOnCompleted();
			}
		}

		protected Sink(IObserver<TTarget> observer)
			: base(observer)
		{
		}

		public virtual void Run(IObservable<TSource> source)
		{
			SetUpstream(source.SubscribeSafe(this));
		}

		public abstract void OnNext(TSource value);

		public virtual void OnError(Exception error)
		{
			ForwardOnError(error);
		}

		public virtual void OnCompleted()
		{
			ForwardOnCompleted();
		}

		public IObserver<TTarget> GetForwarder()
		{
			return new @_(this);
		}
	}
	internal static class Stubs<T>
	{
		public static readonly Action<T> Ignore = delegate
		{
		};

		public static readonly Func<T, T> I = (T _) => _;
	}
	internal static class Stubs
	{
		public static readonly Action Nop = delegate
		{
		};

		public static readonly Action<Exception> Throw = delegate(Exception ex)
		{
			ex.Throw();
		};
	}
	internal static class TimerStubs
	{
		public static readonly System.Threading.Timer Never = new System.Threading.Timer(delegate
		{
		});
	}
	internal sealed class SynchronizedObserver<T> : ObserverBase<T>
	{
		private readonly object _gate;

		private readonly IObserver<T> _observer;

		public SynchronizedObserver(IObserver<T> observer, object gate)
		{
			_gate = gate;
			_observer = observer;
		}

		protected override void OnNextCore(T value)
		{
			lock (_gate)
			{
				_observer.OnNext(value);
			}
		}

		protected override void OnErrorCore(Exception exception)
		{
			lock (_gate)
			{
				_observer.OnError(exception);
			}
		}

		protected override void OnCompletedCore()
		{
			lock (_gate)
			{
				_observer.OnCompleted();
			}
		}
	}
	internal abstract class TailRecursiveSink<TSource> : IdentitySink<TSource>
	{
		private bool _isDisposed;

		private int _trampoline;

		private IDisposable _currentSubscription;

		private readonly Stack<IEnumerator<IObservable<TSource>>> _stack = new Stack<IEnumerator<IObservable<TSource>>>();

		protected TailRecursiveSink(IObserver<TSource> observer)
			: base(observer)
		{
		}

		public void Run(IEnumerable<IObservable<TSource>> sources)
		{
			if (TryGetEnumerator(sources, out var result))
			{
				_stack.Push(result);
				Drain();
			}
		}

		protected override void Dispose(bool disposing)
		{
			if (disposing)
			{
				DisposeAll();
			}
			base.Dispose(disposing);
		}

		private void Drain()
		{
			if (Interlocked.Increment(ref _trampoline) != 1)
			{
				return;
			}
			do
			{
				IL_000f:
				if (Volatile.Read(ref _isDisposed))
				{
					while (_stack.Count != 0)
					{
						_stack.Pop().Dispose();
					}
					Disposable.TryDispose(ref _currentSubscription);
				}
				else if (_stack.Count != 0)
				{
					IEnumerator<IObservable<TSource>> enumerator = _stack.Peek();
					IObservable<TSource> source = null;
					IObservable<TSource> observable = null;
					try
					{
						if (enumerator.MoveNext())
						{
							source = enumerator.Current;
						}
					}
					catch (Exception error)
					{
						enumerator.Dispose();
						ForwardOnError(error);
						Volatile.Write(ref _isDisposed, value: true);
						goto IL_000f;
					}
					try
					{
						observable = Helpers.Unpack(source);
					}
					catch (Exception error2)
					{
						observable = null;
						if (!Fail(error2))
						{
							Volatile.Write(ref _isDisposed, value: true);
						}
						goto IL_000f;
					}
					if (observable == null)
					{
						_stack.Pop();
						enumerator.Dispose();
						goto IL_000f;
					}
					IEnumerable<IObservable<TSource>> enumerable = Extract(observable);
					if (enumerable != null)
					{
						if (TryGetEnumerator(enumerable, out var result))
						{
							_stack.Push(result);
						}
						else
						{
							Volatile.Write(ref _isDisposed, value: true);
						}
						goto IL_000f;
					}
					IDisposable ready = ReadyToken.Ready;
					if (Disposable.TrySetSingle(ref _currentSubscription, ready) != 0)
					{
						goto IL_000f;
					}
					IDisposable disposable = observable.SubscribeSafe(this);
					IDisposable disposable2 = Interlocked.CompareExchange(ref _currentSubscription, disposable, ready);
					if (disposable2 != ready)
					{
						disposable.Dispose();
						if (disposable2 == BooleanDisposable.True)
						{
							goto IL_000f;
						}
					}
				}
				else
				{
					Volatile.Write(ref _isDisposed, value: true);
					Done();
				}
			}
			while (Interlocked.Decrement(ref _trampoline) != 0);
		}

		private void DisposeAll()
		{
			Volatile.Write(ref _isDisposed, value: true);
			Drain();
		}

		protected void Recurse()
		{
			if (Disposable.TrySetSerial(ref _currentSubscription, null))
			{
				Drain();
			}
		}

		protected abstract IEnumerable<IObservable<TSource>> Extract(IObservable<TSource> source);

		private bool TryGetEnumerator(IEnumerable<IObservable<TSource>> sources, out IEnumerator<IObservable<TSource>> result)
		{
			try
			{
				result = sources.GetEnumerator();
				return true;
			}
			catch (Exception error)
			{
				ForwardOnError(error);
				result = null;
				return false;
			}
		}

		protected virtual void Done()
		{
			ForwardOnCompleted();
		}

		protected virtual bool Fail(Exception error)
		{
			ForwardOnError(error);
			return false;
		}
	}
	internal static class ReadyToken
	{
		private sealed class ReadyDisposable : IDisposable
		{
			public void Dispose()
			{
			}
		}

		internal static readonly IDisposable Ready = new ReadyDisposable();
	}
	public interface IObserver<in TValue, out TResult>
	{
		TResult OnNext(TValue value);

		TResult OnError(Exception exception);

		TResult OnCompleted();
	}
	[Experimental]
	public class ListObservable<T> : IList<T>, ICollection<T>, IEnumerable<T>, IEnumerable, IObservable<object>
	{
		private readonly IDisposable _subscription;

		private readonly AsyncSubject<object> _subject = new AsyncSubject<object>();

		private readonly List<T> _results = new List<T>();

		public T Value
		{
			get
			{
				Wait();
				if (_results.Count == 0)
				{
					throw new InvalidOperationException(Strings_Linq.NO_ELEMENTS);
				}
				return _results[_results.Count - 1];
			}
		}

		public T this[int index]
		{
			get
			{
				Wait();
				return _results[index];
			}
			set
			{
				Wait();
				_results[index] = value;
			}
		}

		public int Count
		{
			get
			{
				Wait();
				return _results.Count;
			}
		}

		public bool IsReadOnly => false;

		public ListObservable(IObservable<T> source)
		{
			if (source == null)
			{
				throw new ArgumentNullException("source");
			}
			_subscription = source.Subscribe(_results.Add, _subject.OnError, _subject.OnCompleted);
		}

		private void Wait()
		{
			_subject.DefaultIfEmpty().Wait();
		}

		public int IndexOf(T item)
		{
			Wait();
			return _results.IndexOf(item);
		}

		public void Insert(int index, T item)
		{
			Wait();
			_results.Insert(index, item);
		}

		public void RemoveAt(int index)
		{
			Wait();
			_results.RemoveAt(index);
		}

		public void Add(T item)
		{
			Wait();
			_results.Add(item);
		}

		public void Clear()
		{
			Wait();
			_results.Clear();
		}

		public bool Contains(T item)
		{
			Wait();
			return _results.Contains(item);
		}

		public void CopyTo(T[] array, int arrayIndex)
		{
			Wait();
			_results.CopyTo(array, arrayIndex);
		}

		public bool Remove(T item)
		{
			Wait();
			return _results.Remove(item);
		}

		public IEnumerator<T> GetEnumerator()
		{
			Wait();
			return _results.GetEnumerator();
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return GetEnumerator();
		}

		public IDisposable Subscribe(IObserver<object> observer)
		{
			if (observer == null)
			{
				throw new ArgumentNullException("observer");
			}
			return StableCompositeDisposable.Create(_subscription, _subject.Subscribe(observer));
		}
	}
	[CompilerGenerated]
	internal class NamespaceDoc
	{
	}
	public enum NotificationKind
	{
		OnNext,
		OnError,
		OnCompleted
	}
	[Serializable]
	public abstract class Notification<T> : IEquatable<Notification<T>>
	{
		[Serializable]
		[DebuggerDisplay("OnNext({Value})")]
		internal sealed class OnNextNotification : Notification<T>
		{
			public override T Value { get; }

			public override Exception Exception => null;

			public override bool HasValue => true;

			public override NotificationKind Kind => NotificationKind.OnNext;

			public OnNextNotification(T value)
			{
				Value = value;
			}

			public override int GetHashCode()
			{
				return EqualityComparer<T>.Default.GetHashCode(Value);
			}

			public override bool Equals(Notification<T> other)
			{
				if ((object)this == other)
				{
					return true;
				}
				if ((object)other == null)
				{
					return false;
				}
				if (other.Kind != 0)
				{
					return false;
				}
				return EqualityComparer<T>.Default.Equals(Value, other.Value);
			}

			public override string ToString()
			{
				return string.Format(CultureInfo.CurrentCulture, "OnNext({0})", Value);
			}

			public override void Accept(IObserver<T> observer)
			{
				if (observer == null)
				{
					throw new ArgumentNullException("observer");
				}
				observer.OnNext(Value);
			}

			public override TResult Accept<TResult>(IObserver<T, TResult> observer)
			{
				if (observer == null)
				{
					throw new ArgumentNullException("observer");
				}
				return observer.OnNext(Value);
			}

			public override void Accept(Action<T> onNext, Action<Exception> onError, Action onCompleted)
			{
				if (onNext == null)
				{
					throw new ArgumentNullException("onNext");
				}
				if (onError == null)
				{
					throw new ArgumentNullException("onError");
				}
				if (onCompleted == null)
				{
					throw new ArgumentNullException("onCompleted");
				}
				onNext(Value);
			}

			public override TResult Accept<TResult>(Func<T, TResult> onNext, Func<Exception, TResult> onError, Func<TResult> onCompleted)
			{
				if (onNext == null)
				{
					throw new ArgumentNullException("onNext");
				}
				if (onError == null)
				{
					throw new ArgumentNullException("onError");
				}
				if (onCompleted == null)
				{
					throw new ArgumentNullException("onCompleted");
				}
				return onNext(Value);
			}
		}

		[Serializable]
		[DebuggerDisplay("OnError({Exception})")]
		internal sealed class OnErrorNotification : Notification<T>
		{
			public override T Value
			{
				get
				{
					Exception.Throw();
					return default(T);
				}
			}

			public override Exception Exception { get; }

			public override bool HasValue => false;

			public override NotificationKind Kind => NotificationKind.OnError;

			public OnErrorNotification(Exception exception)
			{
				Exception = exception;
			}

			public override int GetHashCode()
			{
				return Exception.GetHashCode();
			}

			public override bool Equals(Notification<T> other)
			{
				if ((object)this == other)
				{
					return true;
				}
				if ((object)other == null)
				{
					return false;
				}
				if (other.Kind != NotificationKind.OnError)
				{
					return false;
				}
				return object.Equals(Exception, other.Exception);
			}

			public override string ToString()
			{
				return string.Format(CultureInfo.CurrentCulture, "OnError({0})", Exception.GetType().FullName);
			}

			public override void Accept(IObserver<T> observer)
			{
				if (observer == null)
				{
					throw new ArgumentNullException("observer");
				}
				observer.OnError(Exception);
			}

			public override TResult Accept<TResult>(IObserver<T, TResult> observer)
			{
				if (observer == null)
				{
					throw new ArgumentNullException("observer");
				}
				return observer.OnError(Exception);
			}

			public override void Accept(Action<T> onNext, Action<Exception> onError, Action onCompleted)
			{
				if (onNext == null)
				{
					throw new ArgumentNullException("onNext");
				}
				if (onError == null)
				{
					throw new ArgumentNullException("onError");
				}
				if (onCompleted == null)
				{
					throw new ArgumentNullException("onCompleted");
				}
				onError(Exception);
			}

			public override TResult Accept<TResult>(Func<T, TResult> onNext, Func<Exception, TResult> onError, Func<TResult> onCompleted)
			{
				if (onNext == null)
				{
					throw new ArgumentNullException("onNext");
				}
				if (onError == null)
				{
					throw new ArgumentNullException("onError");
				}
				if (onCompleted == null)
				{
					throw new ArgumentNullException("onCompleted");
				}
				return onError(Exception);
			}
		}

		[Serializable]
		[DebuggerDisplay("OnCompleted()")]
		internal sealed class OnCompletedNotification : Notification<T>
		{
			internal static readonly Notification<T> Instance = new OnCompletedNotification();

			public override T Value
			{
				get
				{
					throw new InvalidOperationException(Strings_Core.COMPLETED_NO_VALUE);
				}
			}

			public override Exception Exception => null;

			public override bool HasValue => false;

			public override NotificationKind Kind => NotificationKind.OnCompleted;

			private OnCompletedNotification()
			{
			}

			public override int GetHashCode()
			{
				return typeof(T).GetHashCode() ^ 0x213E;
			}

			public override bool Equals(Notification<T> other)
			{
				if ((object)this == other)
				{
					return true;
				}
				if ((object)other == null)
				{
					return false;
				}
				return other.Kind == NotificationKind.OnCompleted;
			}

			public override string ToString()
			{
				return "OnCompleted()";
			}

			public override void Accept(IObserver<T> observer)
			{
				if (observer == null)
				{
					throw new ArgumentNullException("observer");
				}
				observer.OnCompleted();
			}

			public override TResult Accept<TResult>(IObserver<T, TResult> observer)
			{
				if (observer == null)
				{
					throw new ArgumentNullException("observer");
				}
				return observer.OnCompleted();
			}

			public override void Accept(Action<T> onNext, Action<Exception> onError, Action onCompleted)
			{
				if (onNext == null)
				{
					throw new ArgumentNullException("onNext");
				}
				if (onError == null)
				{
					throw new ArgumentNullException("onError");
				}
				if (onCompleted == null)
				{
					throw new ArgumentNullException("onCompleted");
				}
				onCompleted();
			}

			public override TResult Accept<TResult>(Func<T, TResult> onNext, Func<Exception, TResult> onError, Func<TResult> onCompleted)
			{
				if (onNext == null)
				{
					throw new ArgumentNullException("onNext");
				}
				if (onError == null)
				{
					throw new ArgumentNullException("onError");
				}
				if (onCompleted == null)
				{
					throw new ArgumentNullException("onCompleted");
				}
				return onCompleted();
			}
		}

		private sealed class NotificationToObservable : ObservableBase<T>
		{
			private readonly IScheduler _scheduler;

			private readonly Notification<T> _parent;

			public NotificationToObservable(IScheduler scheduler, Notification<T> parent)
			{
				_scheduler = scheduler;
				_parent = parent;
			}

			protected override IDisposable SubscribeCore(IObserver<T> observer)
			{
				return _scheduler.ScheduleAction((_parent, observer), delegate((Notification<T> _parent, IObserver<T> observer) state)
				{
					var (notification, observer2) = state;
					notification.Accept(observer2);
					if (notification.Kind == NotificationKind.OnNext)
					{
						observer2.OnCompleted();
					}
				});
			}
		}

		public abstract T Value { get; }

		public abstract bool HasValue { get; }

		public abstract Exception Exception { get; }

		public abstract NotificationKind Kind { get; }

		protected internal Notification()
		{
		}

		public abstract bool Equals(Notification<T> other);

		public static bool operator ==(Notification<T> left, Notification<T> right)
		{
			if ((object)left == right)
			{
				return true;
			}
			if ((object)left == null || (object)right == null)
			{
				return false;
			}
			return left.Equals(right);
		}

		public static bool operator !=(Notification<T> left, Notification<T> right)
		{
			return !(left == right);
		}

		public override bool Equals(object obj)
		{
			return Equals(obj as Notification<T>);
		}

		public abstract void Accept(IObserver<T> observer);

		public abstract TResult Accept<TResult>(IObserver<T, TResult> observer);

		public abstract void Accept(Action<T> onNext, Action<Exception> onError, Action onCompleted);

		public abstract TResult Accept<TResult>(Func<T, TResult> onNext, Func<Exception, TResult> onError, Func<TResult> onCompleted);

		public IObservable<T> ToObservable()
		{
			return ToObservable(ImmediateScheduler.Instance);
		}

		public IObservable<T> ToObservable(IScheduler scheduler)
		{
			if (scheduler == null)
			{
				throw new ArgumentNullException("scheduler");
			}
			return new NotificationToObservable(scheduler, this);
		}
	}
	public static class Notification
	{
		public static Notification<T> CreateOnNext<T>(T value)
		{
			return new Notification<T>.OnNextNotification(value);
		}

		public static Notification<T> CreateOnError<T>(Exception error)
		{
			if (error == null)
			{
				throw new ArgumentNullException("error");
			}
			return new Notification<T>.OnErrorNotification(error);
		}

		public static Notification<T> CreateOnCompleted<T>()
		{
			return Notification<T>.OnCompletedNotification.Instance;
		}
	}
	public abstract class ObservableBase<T> : IObservable<T>
	{
		public IDisposable Subscribe(IObserver<T> observer)
		{
			if (observer == null)
			{
				throw new ArgumentNullException("observer");
			}
			AutoDetachObserver<T> autoDetachObserver = new AutoDetachObserver<T>(observer);
			if (CurrentThreadScheduler.IsScheduleRequired)
			{
				((IScheduler)CurrentThreadScheduler.Instance).ScheduleAction(autoDetachObserver, (Action<AutoDetachObserver<T>>)ScheduledSubscribe);
			}
			else
			{
				try
				{
					autoDetachObserver.SetResource(SubscribeCore(autoDetachObserver));
				}
				catch (Exception error)
				{
					if (!autoDetachObserver.Fail(error))
					{
						throw;
					}
				}
			}
			return autoDetachObserver;
		}

		private void ScheduledSubscribe(AutoDetachObserver<T> autoDetachObserver)
		{
			try
			{
				autoDetachObserver.SetResource(SubscribeCore(autoDetachObserver));
			}
			catch (Exception error)
			{
				if (!autoDetachObserver.Fail(error))
				{
					throw;
				}
			}
		}

		protected abstract IDisposable SubscribeCore(IObserver<T> observer);
	}
	internal class ObservableQueryProvider : IQbservableProvider, IQueryProvider
	{
		private static MethodInfo _staticAsQueryable;

		private static MethodInfo AsQueryable
		{
			get
			{
				if (_staticAsQueryable == null)
				{
					_staticAsQueryable = Qbservable.InfoOf((Expression<Func<object>>)(() => ((IEnumerable<object>)null).AsQueryable())).GetGenericMethodDefinition();
				}
				return _staticAsQueryable;
			}
		}

		public IQbservable<TResult> CreateQuery<TResult>(Expression expression)
		{
			if (expression == null)
			{
				throw new ArgumentNullException("expression");
			}
			if (!typeof(IObservable<TResult>).IsAssignableFrom(expression.Type))
			{
				throw new ArgumentException(Strings_Providers.INVALID_TREE_TYPE, "expression");
			}
			return new ObservableQuery<TResult>(expression);
		}

		IQueryable<TElement> IQueryProvider.CreateQuery<TElement>(Expression expression)
		{
			if (!(expression is MethodCallExpression methodCallExpression) || methodCallExpression.Method.DeclaringType != typeof(Qbservable) || methodCallExpression.Method.Name != "ToQueryable")
			{
				throw new ArgumentException(Strings_Providers.EXPECTED_TOQUERYABLE_METHODCALL, "expression");
			}
			Expression arg = methodCallExpression.Arguments[0];
			return Expression.Lambda<Func<IQueryable<TElement>>>(Expression.Call(AsQueryable.MakeGenericMethod(typeof(TElement)), Expression.Call(typeof(Observable).GetMethod("ToEnumerable").MakeGenericMethod(typeof(TElement)), arg)), Array.Empty<ParameterExpression>()).Compile()();
		}

		IQueryable IQueryProvider.CreateQuery(Expression expression)
		{
			throw new NotImplementedException();
		}

		TResult IQueryProvider.Execute<TResult>(Expression expression)
		{
			throw new NotImplementedException();
		}

		object IQueryProvider.Execute(Expression expression)
		{
			throw new NotImplementedException();
		}
	}
	internal class ObservableQuery
	{
		protected object _source;

		protected Expression _expression;

		public object Source => _source;

		public Expression Expression => _expression;
	}
	internal class ObservableQuery<TSource> : ObservableQuery, IQbservable<TSource>, IQbservable, IObservable<TSource>
	{
		private class ObservableRewriter : ExpressionVisitor
		{
			private class Lazy<T>
			{
				private readonly Func<T> _factory;

				private T _value;

				private bool _initialized;

				public T Value
				{
					get
					{
						lock (_factory)
						{
							if (!_initialized)
							{
								_value = _factory();
								_initialized = true;
							}
						}
						return _value;
					}
				}

				public Lazy(Func<T> factory)
				{
					_factory = factory;
				}
			}

			private static readonly Lazy<ILookup<string, MethodInfo>> ObservableMethods = new Lazy<ILookup<string, MethodInfo>>(() => GetMethods(typeof(Observable)));

			protected override Expression VisitConstant(ConstantExpression node)
			{
				if (node.Value is ObservableQuery observableQuery)
				{
					object source = observableQuery.Source;
					if (source != null)
					{
						return Expression.Constant(source);
					}
					return Visit(observableQuery.Expression);
				}
				return node;
			}

			protected override Expression VisitMethodCall(MethodCallExpression node)
			{
				MethodInfo method = node.Method;
				if (method.DeclaringType.BaseType == typeof(QueryablePattern))
				{
					if (method.Name == "Then")
					{
						return Expression.Call(Visit(node.Object), arguments: node.Arguments.Select((Expression arg) => Unquote(Visit(arg))).ToArray(), methodName: "Then", typeArguments: method.GetGenericArguments());
					}
					if (method.Name == "And")
					{
						return Expression.Call(Visit(node.Object), arguments: node.Arguments.Select((Expression arg) => Visit(arg)).ToArray(), methodName: "And", typeArguments: method.GetGenericArguments());
					}
				}
				else
				{
					IEnumerable<Expression> enumerable = node.Arguments.AsEnumerable();
					bool flag = false;
					ParameterInfo parameterInfo = method.GetParameters().FirstOrDefault();
					if (parameterInfo != null)
					{
						Type parameterType = parameterInfo.ParameterType;
						if (parameterType == typeof(IQbservableProvider))
						{
							flag = true;
							if (!(Expression.Lambda<Func<IQbservableProvider>>(Visit(node.Arguments[0]), Array.Empty<ParameterExpression>()).Compile()() is ObservableQueryProvider))
							{
								return node;
							}
							enumerable = enumerable.Skip(1);
						}
						else if (typeof(IQbservable).IsAssignableFrom(parameterType))
						{
							flag = true;
						}
					}
					if (flag)
					{
						IList<Expression> arguments3 = VisitQbservableOperatorArguments(method, enumerable);
						return FindObservableMethod(method, arguments3);
					}
				}
				return base.VisitMethodCall(node);
			}

			protected override Expression VisitLambda<T>(Expression<T> node)
			{
				return node;
			}

			private IList<Expression> VisitQbservableOperatorArguments(MethodInfo method, IEnumerable<Expression> arguments)
			{
				if (method.Name == "When")
				{
					Expression expression = arguments.Last();
					if (expression.NodeType == ExpressionType.NewArrayInit)
					{
						NewArrayExpression newArrayExpression = (NewArrayExpression)expression;
						List<Expression> list = new List<Expression>();
						list.Add(Expression.NewArrayInit(typeof(Plan<>).MakeGenericType(method.GetGenericArguments()[0]), newArrayExpression.Expressions.Select((Expression param) => Visit(param))));
						return list;
					}
				}
				return arguments.Select((Expression arg) => Visit(arg)).ToList();
			}

			private static MethodCallExpression FindObservableMethod(MethodInfo method, IList<Expression> arguments)
			{
				Type type = null;
				ILookup<string, MethodInfo> lookup = null;
				if (method.DeclaringType == typeof(Qbservable))
				{
					type = typeof(Observable);
					lookup = ObservableMethods.Value;
				}
				else
				{
					type = method.DeclaringType;
					if (type.IsDefined(typeof(LocalQueryMethodImplementationTypeAttribute), inherit: false))
					{
						type = ((LocalQueryMethodImplementationTypeAttribute)type.GetCustomAttributes(typeof(LocalQueryMethodImplementationTypeAttribute), inherit: false)[0]).TargetType;
					}
					lookup = GetMethods(type);
				}
				Type[] typeArgs = (method.IsGenericMethod ? method.GetGenericArguments() : null);
				MethodInfo methodInfo = lookup[method.Name].FirstOrDefault((MethodInfo candidateMethod) => ArgsMatch(candidateMethod, arguments, typeArgs));
				if (methodInfo == null)
				{
					throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Strings_Providers.NO_MATCHING_METHOD_FOUND, method.Name, type.Name));
				}
				if (typeArgs != null)
				{
					methodInfo = methodInfo.MakeGenericMethod(typeArgs);
				}
				ParameterInfo[] parameters = methodInfo.GetParameters();
				int i = 0;
				for (int num = parameters.Length; i < num; i++)
				{
					arguments[i] = Unquote(arguments[i]);
				}
				return Expression.Call(null, methodInfo, arguments);
			}

			private static ILookup<string, MethodInfo> GetMethods(Type type)
			{
				return type.GetMethods(BindingFlags.Static | BindingFlags.Public).ToLookup((MethodInfo m) => m.Name);
			}

			private static bool ArgsMatch(MethodInfo method, IList<Expression> arguments, Type[] typeArgs)
			{
				ParameterInfo[] parameters = method.GetParameters();
				if (parameters.Length != arguments.Count)
				{
					return false;
				}
				if (!method.IsGenericMethod && typeArgs != null && typeArgs.Length != 0)
				{
					return false;
				}
				if (method.IsGenericMethodDefinition)
				{
					if (typeArgs == null)
					{
						return false;
					}
					if (method.GetGenericArguments().Length != typeArgs.Length)
					{
						return false;
					}
					parameters = method.MakeGenericMethod(typeArgs).GetParameters();
				}
				int i = 0;
				for (int count = arguments.Count; i < count; i++)
				{
					Type parameterType = parameters[i].ParameterType;
					Expression expression = arguments[i];
					if (!parameterType.IsAssignableFrom(expression.Type))
					{
						expression = Unquote(expression);
						if (!parameterType.IsAssignableFrom(expression.Type))
						{
							return false;
						}
					}
				}
				return true;
			}

			private static Expression Unquote(Expression expression)
			{
				while (expression.NodeType == ExpressionType.Quote)
				{
					expression = ((UnaryExpression)expression).Operand;
				}
				return expression;
			}
		}

		public Type ElementType => typeof(TSource);

		public IQbservableProvider Provider => Qbservable.Provider;

		internal ObservableQuery(IObservable<TSource> source)
		{
			_source = source;
			_expression = Expression.Constant(this);
		}

		internal ObservableQuery(Expression expression)
		{
			_expression = expression;
		}

		public IDisposable Subscribe(IObserver<TSource> observer)
		{
			if (_source == null)
			{
				Expression<Func<IObservable<TSource>>> expression = Expression.Lambda<Func<IObservable<TSource>>>(new ObservableRewriter().Visit(_expression), Array.Empty<ParameterExpression>());
				_source = expression.Compile()();
			}
			return ((IObservable<TSource>)_source).Subscribe(observer);
		}

		public override string ToString()
		{
			if (_expression is ConstantExpression constantExpression && constantExpression.Value == this)
			{
				if (_source != null)
				{
					return _source.ToString();
				}
				return "null";
			}
			return _expression.ToString();
		}
	}
	public static class Observer
	{
		private class AnonymousProgress<T> : IProgress<T>
		{
			private readonly Action<T> _progress;

			public AnonymousProgress(Action<T> progress)
			{
				_progress = progress;
			}

			public void Report(T value)
			{
				_progress(value);
			}
		}

		public static IObserver<T> ToObserver<T>(this Action<Notification<T>> handler)
		{
			if (handler == null)
			{
				throw new ArgumentNullException("handler");
			}
			return new AnonymousObserver<T>(delegate(T x)
			{
				handler(Notification.CreateOnNext(x));
			}, delegate(Exception exception)
			{
				handler(Notification.CreateOnError<T>(exception));
			}, delegate
			{
				handler(Notification.CreateOnCompleted<T>());
			});
		}

		public static Action<Notification<T>> ToNotifier<T>(this IObserver<T> observer)
		{
			if (observer == null)
			{
				throw new ArgumentNullException("observer");
			}
			return delegate(Notification<T> n)
			{
				n.Accept(observer);
			};
		}

		public static IObserver<T> Create<T>(Action<T> onNext)
		{
			if (onNext == null)
			{
				throw new ArgumentNullException("onNext");
			}
			return new AnonymousObserver<T>(onNext);
		}

		public static IObserver<T> Create<T>(Action<T> onNext, Action<Exception> onError)
		{
			if (onNext == null)
			{
				throw new ArgumentNullException("onNext");
			}
			if (onError == null)
			{
				throw new ArgumentNullException("onError");
			}
			return new AnonymousObserver<T>(onNext, onError);
		}

		public static IObserver<T> Create<T>(Action<T> onNext, Action onCompleted)
		{
			if (onNext == null)
			{
				throw new ArgumentNullException("onNext");
			}
			if (onCompleted == null)
			{
				throw new ArgumentNullException("onCompleted");
			}
			return new AnonymousObserver<T>(onNext, onCompleted);
		}

		public static IObserver<T> Create<T>(Action<T> onNext, Action<Exception> onError, Action onCompleted)
		{
			if (onNext == null)
			{
				throw new ArgumentNullException("onNext");
			}
			if (onError == null)
			{
				throw new ArgumentNullException("onError");
			}
			if (onCompleted == null)
			{
				throw new ArgumentNullException("onCompleted");
			}
			return new AnonymousObserver<T>(onNext, onError, onCompleted);
		}

		public static IObserver<T> AsObserver<T>(this IObserver<T> observer)
		{
			if (observer == null)
			{
				throw new ArgumentNullException("observer");
			}
			return new AnonymousObserver<T>(observer.OnNext, observer.OnError, observer.OnCompleted);
		}

		public static IObserver<T> Checked<T>(this IObserver<T> observer)
		{
			if (observer == null)
			{
				throw new ArgumentNullException("observer");
			}
			return new CheckedObserver<T>(observer);
		}

		public static IObserver<T> Synchronize<T>(IObserver<T> observer)
		{
			if (observer == null)
			{
				throw new ArgumentNullException("observer");
			}
			return new SynchronizedObserver<T>(observer, new object());
		}

		public static IObserver<T> Synchronize<T>(IObserver<T> observer, bool preventReentrancy)
		{
			if (observer == null)
			{
				throw new ArgumentNullException("observer");
			}
			if (preventReentrancy)
			{
				return new AsyncLockObserver<T>(observer, new AsyncLock());
			}
			return new SynchronizedObserver<T>(observer, new object());
		}

		public static IObserver<T> Synchronize<T>(IObserver<T> observer, object gate)
		{
			if (observer == null)
			{
				throw new ArgumentNullException("observer");
			}
			if (gate == null)
			{
				throw new ArgumentNullException("gate");
			}
			return new SynchronizedObserver<T>(observer, gate);
		}

		public static IObserver<T> Synchronize<T>(IObserver<T> observer, AsyncLock asyncLock)
		{
			if (observer == null)
			{
				throw new ArgumentNullException("observer");
			}
			if (asyncLock == null)
			{
				throw new ArgumentNullException("asyncLock");
			}
			return new AsyncLockObserver<T>(observer, asyncLock);
		}

		public static IObserver<T> NotifyOn<T>(this IObserver<T> observer, IScheduler scheduler)
		{
			if (observer == null)
			{
				throw new ArgumentNullException("observer");
			}
			if (scheduler == null)
			{
				throw new ArgumentNullException("scheduler");
			}
			return new ObserveOnObserver<T>(scheduler, observer);
		}

		public static IObserver<T> NotifyOn<T>(this IObserver<T> observer, SynchronizationContext context)
		{
			if (observer == null)
			{
				throw new ArgumentNullException("observer");
			}
			if (context == null)
			{
				throw new ArgumentNullException("context");
			}
			return new ObserveOnObserver<T>(new SynchronizationContextScheduler(context), observer);
		}

		public static IProgress<T> ToProgress<T>(this IObserver<T> observer)
		{
			if (observer == null)
			{
				throw new ArgumentNullException("observer");
			}
			return new AnonymousProgress<T>(observer.OnNext);
		}

		public static IProgress<T> ToProgress<T>(this IObserver<T> observer, IScheduler scheduler)
		{
			if (observer == null)
			{
				throw new ArgumentNullException("observer");
			}
			if (scheduler == null)
			{
				throw new ArgumentNullException("scheduler");
			}
			return new AnonymousProgress<T>(new ObserveOnObserver<T>(scheduler, observer).OnNext);
		}

		public static IObserver<T> ToObserver<T>(this IProgress<T> progress)
		{
			if (progress == null)
			{
				throw new ArgumentNullException("progress");
			}
			return new AnonymousObserver<T>(progress.Report);
		}
	}
	public abstract class ObserverBase<T> : IObserver<T>, IDisposable
	{
		private int _isStopped;

		protected ObserverBase()
		{
			_isStopped = 0;
		}

		public void OnNext(T value)
		{
			if (Volatile.Read(ref _isStopped) == 0)
			{
				OnNextCore(value);
			}
		}

		protected abstract void OnNextCore(T value);

		public void OnError(Exception error)
		{
			if (error == null)
			{
				throw new ArgumentNullException("error");
			}
			if (Interlocked.Exchange(ref _isStopped, 1) == 0)
			{
				OnErrorCore(error);
			}
		}

		protected abstract void OnErrorCore(Exception error);

		public void OnCompleted()
		{
			if (Interlocked.Exchange(ref _isStopped, 1) == 0)
			{
				OnCompletedCore();
			}
		}

		protected abstract void OnCompletedCore();

		public void Dispose()
		{
			Dispose(disposing: true);
			GC.SuppressFinalize(this);
		}

		protected virtual void Dispose(bool disposing)
		{
			if (disposing)
			{
				Volatile.Write(ref _isStopped, 1);
			}
		}

		internal bool Fail(Exception error)
		{
			if (Interlocked.Exchange(ref _isStopped, 1) == 0)
			{
				OnErrorCore(error);
				return true;
			}
			return false;
		}
	}
	[GeneratedCode("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
	[DebuggerNonUserCode]
	[CompilerGenerated]
	internal class Strings_Core
	{
		private static ResourceManager resourceMan;

		private static CultureInfo resourceCulture;

		[EditorBrowsable(EditorBrowsableState.Advanced)]
		internal static ResourceManager ResourceManager
		{
			get
			{
				if (resourceMan == null)
				{
					resourceMan = new ResourceManager("System.Reactive.Strings_Core", typeof(Strings_Core).GetTypeInfo().Assembly);
				}
				return resourceMan;
			}
		}

		[EditorBrowsable(EditorBrowsableState.Advanced)]
		internal static CultureInfo Culture
		{
			get
			{
				return resourceCulture;
			}
			set
			{
				resourceCulture = value;
			}
		}

		internal static string CANT_OBTAIN_SCHEDULER => ResourceManager.GetString("CANT_OBTAIN_SCHEDULER", resourceCulture);

		internal static string COMPLETED_NO_VALUE => ResourceManager.GetString("COMPLETED_NO_VALUE", resourceCulture);

		internal static string DISPOSABLE_ALREADY_ASSIGNED => ResourceManager.GetString("DISPOSABLE_ALREADY_ASSIGNED", resourceCulture);

		internal static string DISPOSABLES_CANT_CONTAIN_NULL => ResourceManager.GetString("DISPOSABLES_CANT_CONTAIN_NULL", resourceCulture);

		internal static string FAILED_CLOCK_MONITORING => ResourceManager.GetSt

UserLibs/Websocket.Client.dll

Decompiled a month ago
#define TRACE
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Net.WebSockets;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Channels;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Websocket.Client.Exceptions;
using Websocket.Client.Logging;
using Websocket.Client.Logging.LogProviders;
using Websocket.Client.Models;
using Websocket.Client.Threading;
using Websocket.Client.Validations;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("Mariusz Kotas")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright 2020 Mariusz Kotas. All rights reserved.")]
[assembly: AssemblyDescription("Client for websocket API with built-in reconnection and error handling")]
[assembly: AssemblyFileVersion("4.4.0.0")]
[assembly: AssemblyInformationalVersion("4.4.0")]
[assembly: AssemblyProduct("Websocket.Client")]
[assembly: AssemblyTitle("Websocket.Client")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/Marfusios/websocket-client")]
[assembly: AssemblyVersion("4.4.0.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
}
namespace Websocket.Client
{
	public interface IWebsocketClient : IDisposable
	{
		Uri Url { get; set; }

		IObservable<ResponseMessage> MessageReceived { get; }

		IObservable<ReconnectionInfo> ReconnectionHappened { get; }

		IObservable<DisconnectionInfo> DisconnectionHappened { get; }

		TimeSpan? ReconnectTimeout { get; set; }

		TimeSpan? ErrorReconnectTimeout { get; set; }

		string Name { get; set; }

		bool IsStarted { get; }

		bool IsRunning { get; }

		bool IsReconnectionEnabled { get; set; }

		bool IsTextMessageConversionEnabled { get; set; }

		ClientWebSocket NativeClient { get; }

		Encoding MessageEncoding { get; set; }

		Task Start();

		Task StartOrFail();

		Task<bool> Stop(WebSocketCloseStatus status, string statusDescription);

		Task<bool> StopOrFail(WebSocketCloseStatus status, string statusDescription);

		void Send(string message);

		void Send(byte[] message);

		void Send(ArraySegment<byte> message);

		Task SendInstant(string message);

		Task SendInstant(byte[] message);

		Task Reconnect();

		Task ReconnectOrFail();

		void StreamFakeMessage(ResponseMessage message);
	}
	public class DisconnectionInfo
	{
		public DisconnectionType Type { get; }

		public WebSocketCloseStatus? CloseStatus { get; }

		public string CloseStatusDescription { get; }

		public string SubProtocol { get; }

		public Exception Exception { get; }

		public bool CancelReconnection { get; set; }

		public bool CancelClosing { get; set; }

		public DisconnectionInfo(DisconnectionType type, WebSocketCloseStatus? closeStatus, string closeStatusDescription, string subProtocol, Exception exception)
		{
			Type = type;
			CloseStatus = closeStatus;
			CloseStatusDescription = closeStatusDescription;
			SubProtocol = subProtocol;
			Exception = exception;
		}

		public static DisconnectionInfo Create(DisconnectionType type, WebSocket client, Exception exception)
		{
			return new DisconnectionInfo(type, client?.CloseStatus, client?.CloseStatusDescription, client?.SubProtocol, exception);
		}
	}
	public enum DisconnectionType
	{
		Exit,
		Lost,
		NoMessageReceived,
		Error,
		ByUser,
		ByServer
	}
	public enum ReconnectionType
	{
		Initial,
		Lost,
		NoMessageReceived,
		Error,
		ByUser,
		ByServer
	}
	public class ResponseMessage
	{
		public string Text { get; }

		public byte[] Binary { get; }

		public WebSocketMessageType MessageType { get; }

		private ResponseMessage(byte[] binary, string text, WebSocketMessageType messageType)
		{
			Binary = binary;
			Text = text;
			MessageType = messageType;
		}

		public override string ToString()
		{
			if (MessageType == WebSocketMessageType.Text)
			{
				return Text;
			}
			return $"Type binary, length: {Binary?.Length}";
		}

		public static ResponseMessage TextMessage(string data)
		{
			return new ResponseMessage(null, data, WebSocketMessageType.Text);
		}

		public static ResponseMessage BinaryMessage(byte[] data)
		{
			return new ResponseMessage(data, null, WebSocketMessageType.Binary);
		}
	}
	public class WebsocketClient : IWebsocketClient, IDisposable
	{
		private static readonly ILog Logger = GetLogger();

		private readonly WebsocketAsyncLock _locker = new WebsocketAsyncLock();

		private readonly Func<Uri, CancellationToken, Task<WebSocket>> _connectionFactory;

		private Uri _url;

		private Timer _lastChanceTimer;

		private DateTime _lastReceivedMsg = DateTime.UtcNow;

		private bool _disposing;

		private bool _reconnecting;

		private bool _stopping;

		private bool _isReconnectionEnabled = true;

		private WebSocket _client;

		private CancellationTokenSource _cancellation;

		private CancellationTokenSource _cancellationTotal;

		private readonly Subject<ResponseMessage> _messageReceivedSubject = new Subject<ResponseMessage>();

		private readonly Subject<ReconnectionInfo> _reconnectionSubject = new Subject<ReconnectionInfo>();

		private readonly Subject<DisconnectionInfo> _disconnectedSubject = new Subject<DisconnectionInfo>();

		private readonly Channel<string> _messagesTextToSendQueue = Channel.CreateUnbounded<string>(new UnboundedChannelOptions
		{
			SingleReader = true,
			SingleWriter = false
		});

		private readonly Channel<ArraySegment<byte>> _messagesBinaryToSendQueue = Channel.CreateUnbounded<ArraySegment<byte>>(new UnboundedChannelOptions
		{
			SingleReader = true,
			SingleWriter = false
		});

		public Uri Url
		{
			get
			{
				return _url;
			}
			set
			{
				Websocket.Client.Validations.Validations.ValidateInput(value, "Url");
				_url = value;
			}
		}

		public IObservable<ResponseMessage> MessageReceived => Observable.AsObservable<ResponseMessage>((IObservable<ResponseMessage>)_messageReceivedSubject);

		public IObservable<ReconnectionInfo> ReconnectionHappened => Observable.AsObservable<ReconnectionInfo>((IObservable<ReconnectionInfo>)_reconnectionSubject);

		public IObservable<DisconnectionInfo> DisconnectionHappened => Observable.AsObservable<DisconnectionInfo>((IObservable<DisconnectionInfo>)_disconnectedSubject);

		public TimeSpan? ReconnectTimeout { get; set; } = TimeSpan.FromMinutes(1.0);


		public TimeSpan? ErrorReconnectTimeout { get; set; } = TimeSpan.FromMinutes(1.0);


		public bool IsReconnectionEnabled
		{
			get
			{
				return _isReconnectionEnabled;
			}
			set
			{
				_isReconnectionEnabled = value;
				if (IsStarted)
				{
					if (_isReconnectionEnabled)
					{
						ActivateLastChance();
					}
					else
					{
						DeactivateLastChance();
					}
				}
			}
		}

		public string Name { get; set; }

		public bool IsStarted { get; private set; }

		public bool IsRunning { get; private set; }

		public bool IsTextMessageConversionEnabled { get; set; } = true;


		public Encoding MessageEncoding { get; set; }

		public ClientWebSocket NativeClient => GetSpecificOrThrow(_client);

		public WebsocketClient(Uri url, Func<ClientWebSocket> clientFactory = null)
			: this(url, GetClientFactory(clientFactory))
		{
		}

		public WebsocketClient(Uri url, Func<Uri, CancellationToken, Task<WebSocket>> connectionFactory)
		{
			Websocket.Client.Validations.Validations.ValidateInput(url, "url");
			_url = url;
			_connectionFactory = connectionFactory ?? ((Func<Uri, CancellationToken, Task<WebSocket>>)async delegate(Uri uri, CancellationToken token)
			{
				ClientWebSocket client = new ClientWebSocket();
				await client.ConnectAsync(uri, token).ConfigureAwait(continueOnCapturedContext: false);
				return client;
			});
		}

		public void Dispose()
		{
			_disposing = true;
			Logger.Debug(L("Disposing.."));
			try
			{
				_messagesTextToSendQueue?.Writer.Complete();
				_messagesBinaryToSendQueue?.Writer.Complete();
				_lastChanceTimer?.Dispose();
				_cancellation?.Cancel();
				_cancellationTotal?.Cancel();
				_client?.Abort();
				_client?.Dispose();
				_cancellation?.Dispose();
				_cancellationTotal?.Dispose();
				((SubjectBase<ResponseMessage>)(object)_messageReceivedSubject).OnCompleted();
				((SubjectBase<ReconnectionInfo>)(object)_reconnectionSubject).OnCompleted();
			}
			catch (Exception ex)
			{
				Logger.Error(ex, L("Failed to dispose client, error: " + ex.Message));
			}
			IsRunning = false;
			IsStarted = false;
			((SubjectBase<DisconnectionInfo>)(object)_disconnectedSubject).OnNext(DisconnectionInfo.Create(DisconnectionType.Exit, _client, null));
			((SubjectBase<DisconnectionInfo>)(object)_disconnectedSubject).OnCompleted();
		}

		public Task Start()
		{
			return StartInternal(failFast: false);
		}

		public Task StartOrFail()
		{
			return StartInternal(failFast: true);
		}

		public async Task<bool> Stop(WebSocketCloseStatus status, string statusDescription)
		{
			bool result = await StopInternal(_client, status, statusDescription, null, failFast: false, byServer: false).ConfigureAwait(continueOnCapturedContext: false);
			((SubjectBase<DisconnectionInfo>)(object)_disconnectedSubject).OnNext(DisconnectionInfo.Create(DisconnectionType.ByUser, _client, null));
			return result;
		}

		public async Task<bool> StopOrFail(WebSocketCloseStatus status, string statusDescription)
		{
			bool result = await StopInternal(_client, status, statusDescription, null, failFast: true, byServer: false).ConfigureAwait(continueOnCapturedContext: false);
			((SubjectBase<DisconnectionInfo>)(object)_disconnectedSubject).OnNext(DisconnectionInfo.Create(DisconnectionType.ByUser, _client, null));
			return result;
		}

		private static Func<Uri, CancellationToken, Task<WebSocket>> GetClientFactory(Func<ClientWebSocket> clientFactory)
		{
			if (clientFactory == null)
			{
				return null;
			}
			return async delegate(Uri uri, CancellationToken token)
			{
				ClientWebSocket client = clientFactory();
				await client.ConnectAsync(uri, token).ConfigureAwait(continueOnCapturedContext: false);
				return client;
			};
		}

		private async Task StartInternal(bool failFast)
		{
			if (_disposing)
			{
				throw new WebsocketException(L("Client is already disposed, starting not possible"));
			}
			if (IsStarted)
			{
				Logger.Debug(L("Client already started, ignoring.."));
				return;
			}
			IsStarted = true;
			Logger.Debug(L("Starting.."));
			_cancellation = new CancellationTokenSource();
			_cancellationTotal = new CancellationTokenSource();
			await StartClient(_url, _cancellation.Token, ReconnectionType.Initial, failFast).ConfigureAwait(continueOnCapturedContext: false);
			StartBackgroundThreadForSendingText();
			StartBackgroundThreadForSendingBinary();
		}

		private async Task<bool> StopInternal(WebSocket client, WebSocketCloseStatus status, string statusDescription, CancellationToken? cancellation, bool failFast, bool byServer)
		{
			if (_disposing)
			{
				throw new WebsocketException(L("Client is already disposed, stopping not possible"));
			}
			if (!IsRunning)
			{
				Logger.Info(L("Client is already stopped"));
				return false;
			}
			bool result = false;
			if (client == null)
			{
				IsStarted = false;
				IsRunning = false;
				return false;
			}
			DeactivateLastChance();
			try
			{
				CancellationToken cancellationToken = cancellation ?? CancellationToken.None;
				_stopping = true;
				if (!byServer)
				{
					await client.CloseAsync(status, statusDescription, cancellationToken);
				}
				else
				{
					await client.CloseOutputAsync(status, statusDescription, cancellationToken);
				}
				result = true;
			}
			catch (Exception ex)
			{
				Logger.Error(ex, L("Error while stopping client, message: '" + ex.Message + "'"));
				if (failFast)
				{
					throw new WebsocketException("Failed to stop Websocket client, error: '" + ex.Message + "'", ex);
				}
			}
			finally
			{
				IsStarted = false;
				IsRunning = false;
				_stopping = false;
			}
			return result;
		}

		private async Task StartClient(Uri uri, CancellationToken token, ReconnectionType type, bool failFast)
		{
			DeactivateLastChance();
			try
			{
				_client = await _connectionFactory(uri, token).ConfigureAwait(continueOnCapturedContext: false);
				Listen(_client, token);
				IsRunning = true;
				IsStarted = true;
				((SubjectBase<ReconnectionInfo>)(object)_reconnectionSubject).OnNext(ReconnectionInfo.Create(type));
				_lastReceivedMsg = DateTime.UtcNow;
				ActivateLastChance();
			}
			catch (Exception e)
			{
				DisconnectionInfo disconnectionInfo = DisconnectionInfo.Create(DisconnectionType.Error, _client, e);
				((SubjectBase<DisconnectionInfo>)(object)_disconnectedSubject).OnNext(disconnectionInfo);
				if (disconnectionInfo.CancelReconnection)
				{
					Logger.Error(e, L("Exception while connecting. Reconnecting canceled by user, exiting. Error: '" + e.Message + "'"));
					return;
				}
				if (failFast)
				{
					throw new WebsocketException("Failed to start Websocket client, error: '" + e.Message + "'", e);
				}
				if (!ErrorReconnectTimeout.HasValue)
				{
					Logger.Error(e, L("Exception while connecting. Reconnecting disabled, exiting. Error: '" + e.Message + "'"));
					return;
				}
				TimeSpan value = ErrorReconnectTimeout.Value;
				Logger.Error(e, L($"Exception while connecting. Waiting {value.TotalSeconds} sec before next reconnection try. Error: '{e.Message}'"));
				await Task.Delay(value, token).ConfigureAwait(continueOnCapturedContext: false);
				await Reconnect(ReconnectionType.Error, failFast: false, e).ConfigureAwait(continueOnCapturedContext: false);
			}
		}

		private bool IsClientConnected()
		{
			return _client.State == WebSocketState.Open;
		}

		private async Task Listen(WebSocket client, CancellationToken token)
		{
			Exception causedException = null;
			try
			{
				ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[4096]);
				do
				{
					byte[] resultArrayWithTrailing = null;
					int resultArraySize = 0;
					bool isResultArrayCloned = false;
					MemoryStream ms = null;
					WebSocketReceiveResult webSocketReceiveResult;
					while (true)
					{
						webSocketReceiveResult = await client.ReceiveAsync(buffer, token);
						byte[] array = buffer.Array;
						int count = webSocketReceiveResult.Count;
						if (resultArrayWithTrailing == null)
						{
							resultArraySize += count;
							resultArrayWithTrailing = array;
							isResultArrayCloned = false;
						}
						else if (array != null)
						{
							if (ms == null)
							{
								ms = new MemoryStream();
								ms.Write(resultArrayWithTrailing, 0, resultArraySize);
							}
							ms.Write(array, buffer.Offset, count);
						}
						if (webSocketReceiveResult.EndOfMessage)
						{
							break;
						}
						if (!isResultArrayCloned)
						{
							resultArrayWithTrailing = resultArrayWithTrailing?.ToArray();
							isResultArrayCloned = true;
						}
					}
					ms?.Seek(0L, SeekOrigin.Begin);
					ResponseMessage responseMessage;
					if (webSocketReceiveResult.MessageType == WebSocketMessageType.Text && IsTextMessageConversionEnabled)
					{
						responseMessage = ResponseMessage.TextMessage((ms != null) ? GetEncoding().GetString(ms.ToArray()) : ((resultArrayWithTrailing != null) ? GetEncoding().GetString(resultArrayWithTrailing, 0, resultArraySize) : null));
					}
					else
					{
						if (webSocketReceiveResult.MessageType == WebSocketMessageType.Close)
						{
							Logger.Trace(L("Received close message"));
							if (!IsStarted || _stopping)
							{
								return;
							}
							DisconnectionInfo disconnectionInfo = DisconnectionInfo.Create(DisconnectionType.ByServer, client, null);
							((SubjectBase<DisconnectionInfo>)(object)_disconnectedSubject).OnNext(disconnectionInfo);
							if (disconnectionInfo.CancelClosing)
							{
								if (IsReconnectionEnabled)
								{
									throw new OperationCanceledException("Websocket connection was closed by server");
								}
								continue;
							}
							await StopInternal(client, WebSocketCloseStatus.NormalClosure, "Closing", token, failFast: false, byServer: true);
							if (IsReconnectionEnabled && !ShouldIgnoreReconnection(client))
							{
								ReconnectSynchronized(ReconnectionType.Lost, failFast: false, null);
							}
							return;
						}
						if (ms != null)
						{
							responseMessage = ResponseMessage.BinaryMessage(ms.ToArray());
						}
						else
						{
							Array.Resize(ref resultArrayWithTrailing, resultArraySize);
							responseMessage = ResponseMessage.BinaryMessage(resultArrayWithTrailing);
						}
					}
					ms?.Dispose();
					Logger.Trace(L($"Received:  {responseMessage}"));
					_lastReceivedMsg = DateTime.UtcNow;
					((SubjectBase<ResponseMessage>)(object)_messageReceivedSubject).OnNext(responseMessage);
				}
				while (client.State == WebSocketState.Open && !token.IsCancellationRequested);
			}
			catch (TaskCanceledException ex)
			{
				causedException = ex;
			}
			catch (OperationCanceledException ex2)
			{
				causedException = ex2;
			}
			catch (ObjectDisposedException ex3)
			{
				causedException = ex3;
			}
			catch (Exception ex4)
			{
				Logger.Error(ex4, L("Error while listening to websocket stream, error: '" + ex4.Message + "'"));
				causedException = ex4;
			}
			if (!ShouldIgnoreReconnection(client) && IsStarted)
			{
				ReconnectSynchronized(ReconnectionType.Lost, failFast: false, causedException);
			}
		}

		private bool ShouldIgnoreReconnection(WebSocket client)
		{
			bool num = _disposing || _reconnecting || _stopping;
			bool flag = client != _client;
			return num || flag;
		}

		private Encoding GetEncoding()
		{
			if (MessageEncoding == null)
			{
				MessageEncoding = Encoding.UTF8;
			}
			return MessageEncoding;
		}

		private ClientWebSocket GetSpecificOrThrow(WebSocket client)
		{
			if (client == null)
			{
				return null;
			}
			return (client as ClientWebSocket) ?? throw new WebsocketException("Cannot cast 'WebSocket' client to 'ClientWebSocket', provide correct type via factory or don't use this property at all.");
		}

		private string L(string msg)
		{
			string text = Name ?? "CLIENT";
			return "[WEBSOCKET " + text + "] " + msg;
		}

		private static ILog GetLogger()
		{
			try
			{
				return LogProvider.GetCurrentClassLogger();
			}
			catch (Exception value)
			{
				Trace.WriteLine($"[WEBSOCKET] Failed to initialize logger, disabling.. Error: {value}");
				return LogProvider.NoOpLogger.Instance;
			}
		}

		private DisconnectionType TranslateTypeToDisconnection(ReconnectionType type)
		{
			return (DisconnectionType)type;
		}

		public Task Reconnect()
		{
			return ReconnectInternal(failFast: false);
		}

		public Task ReconnectOrFail()
		{
			return ReconnectInternal(failFast: true);
		}

		private async Task ReconnectInternal(bool failFast)
		{
			if (!IsStarted)
			{
				Logger.Debug(L("Client not started, ignoring reconnection.."));
				return;
			}
			try
			{
				await ReconnectSynchronized(ReconnectionType.ByUser, failFast, null).ConfigureAwait(continueOnCapturedContext: false);
			}
			finally
			{
				_reconnecting = false;
			}
		}

		private async Task ReconnectSynchronized(ReconnectionType type, bool failFast, Exception causedException)
		{
			using (await _locker.LockAsync())
			{
				await Reconnect(type, failFast, causedException);
			}
		}

		private async Task Reconnect(ReconnectionType type, bool failFast, Exception causedException)
		{
			IsRunning = false;
			if (_disposing)
			{
				return;
			}
			_reconnecting = true;
			DisconnectionInfo disconnectionInfo = DisconnectionInfo.Create(TranslateTypeToDisconnection(type), _client, causedException);
			if (type != ReconnectionType.Error)
			{
				((SubjectBase<DisconnectionInfo>)(object)_disconnectedSubject).OnNext(disconnectionInfo);
				if (disconnectionInfo.CancelReconnection)
				{
					Logger.Info(L("Reconnecting canceled by user, exiting."));
				}
			}
			_cancellation.Cancel();
			try
			{
				_client?.Abort();
			}
			catch (Exception ex)
			{
				Logger.Error(ex, L("Exception while aborting client. Error: '" + ex.Message + "'"));
			}
			_client?.Dispose();
			if (!IsReconnectionEnabled || disconnectionInfo.CancelReconnection)
			{
				IsStarted = false;
				_reconnecting = false;
				return;
			}
			Logger.Debug(L("Reconnecting..."));
			_cancellation = new CancellationTokenSource();
			await StartClient(_url, _cancellation.Token, type, failFast).ConfigureAwait(continueOnCapturedContext: false);
			_reconnecting = false;
		}

		private void ActivateLastChance()
		{
			int num = 1000;
			_lastChanceTimer = new Timer(LastChance, null, num, num);
		}

		private void DeactivateLastChance()
		{
			_lastChanceTimer?.Dispose();
			_lastChanceTimer = null;
		}

		private void LastChance(object state)
		{
			if (!IsReconnectionEnabled || !ReconnectTimeout.HasValue)
			{
				DeactivateLastChance();
				return;
			}
			double num = Math.Abs(ReconnectTimeout.Value.TotalMilliseconds);
			if (Math.Abs(DateTime.UtcNow.Subtract(_lastReceivedMsg).TotalMilliseconds) > num)
			{
				Logger.Debug(L($"Last message received more than {num:F} ms ago. Hard restart.."));
				DeactivateLastChance();
				ReconnectSynchronized(ReconnectionType.NoMessageReceived, failFast: false, null);
			}
		}

		public void Send(string message)
		{
			Websocket.Client.Validations.Validations.ValidateInput(message, "message");
			_messagesTextToSendQueue.Writer.TryWrite(message);
		}

		public void Send(byte[] message)
		{
			Websocket.Client.Validations.Validations.ValidateInput(message, "message");
			_messagesBinaryToSendQueue.Writer.TryWrite(new ArraySegment<byte>(message));
		}

		public void Send(ArraySegment<byte> message)
		{
			Websocket.Client.Validations.Validations.ValidateInput(message, "message");
			_messagesBinaryToSendQueue.Writer.TryWrite(message);
		}

		public Task SendInstant(string message)
		{
			Websocket.Client.Validations.Validations.ValidateInput(message, "message");
			return SendInternalSynchronized(message);
		}

		public Task SendInstant(byte[] message)
		{
			return SendInternalSynchronized(new ArraySegment<byte>(message));
		}

		public void StreamFakeMessage(ResponseMessage message)
		{
			Websocket.Client.Validations.Validations.ValidateInput(message, "message");
			((SubjectBase<ResponseMessage>)(object)_messageReceivedSubject).OnNext(message);
		}

		private async Task SendTextFromQueue()
		{
			_ = 1;
			try
			{
				while (await _messagesTextToSendQueue.Reader.WaitToReadAsync())
				{
					string message;
					while (_messagesTextToSendQueue.Reader.TryRead(out message))
					{
						try
						{
							await SendInternalSynchronized(message).ConfigureAwait(continueOnCapturedContext: false);
						}
						catch (Exception ex)
						{
							Logger.Error(ex, L("Failed to send text message: '" + message + "'. Error: " + ex.Message));
						}
					}
				}
			}
			catch (TaskCanceledException)
			{
			}
			catch (OperationCanceledException)
			{
			}
			catch (Exception ex4)
			{
				if (!_cancellationTotal.IsCancellationRequested && !_disposing)
				{
					Logger.Trace(L("Sending text thread failed, error: " + ex4.Message + ". Creating a new sending thread."));
					StartBackgroundThreadForSendingText();
				}
			}
		}

		private async Task SendBinaryFromQueue()
		{
			_ = 1;
			try
			{
				while (await _messagesBinaryToSendQueue.Reader.WaitToReadAsync())
				{
					ArraySegment<byte> message;
					while (_messagesBinaryToSendQueue.Reader.TryRead(out message))
					{
						try
						{
							await SendInternalSynchronized(message).ConfigureAwait(continueOnCapturedContext: false);
						}
						catch (Exception ex)
						{
							Logger.Error(ex, L($"Failed to send binary message: '{message}'. Error: {ex.Message}"));
						}
					}
				}
			}
			catch (TaskCanceledException)
			{
			}
			catch (OperationCanceledException)
			{
			}
			catch (Exception ex4)
			{
				if (!_cancellationTotal.IsCancellationRequested && !_disposing)
				{
					Logger.Trace(L("Sending binary thread failed, error: " + ex4.Message + ". Creating a new sending thread."));
					StartBackgroundThreadForSendingBinary();
				}
			}
		}

		private void StartBackgroundThreadForSendingText()
		{
			Task.Factory.StartNew((object? _) => SendTextFromQueue(), TaskCreationOptions.LongRunning, _cancellationTotal.Token);
		}

		private void StartBackgroundThreadForSendingBinary()
		{
			Task.Factory.StartNew((object? _) => SendBinaryFromQueue(), TaskCreationOptions.LongRunning, _cancellationTotal.Token);
		}

		private async Task SendInternalSynchronized(string message)
		{
			using (await _locker.LockAsync())
			{
				await SendInternal(message);
			}
		}

		private async Task SendInternal(string message)
		{
			if (!IsClientConnected())
			{
				Logger.Debug(L("Client is not connected to server, cannot send:  " + message));
				return;
			}
			Logger.Trace(L("Sending:  " + message));
			byte[] bytes = GetEncoding().GetBytes(message);
			ArraySegment<byte> buffer = new ArraySegment<byte>(bytes);
			await _client.SendAsync(buffer, WebSocketMessageType.Text, endOfMessage: true, _cancellation.Token).ConfigureAwait(continueOnCapturedContext: false);
		}

		private async Task SendInternalSynchronized(ArraySegment<byte> message)
		{
			using (await _locker.LockAsync())
			{
				await SendInternal(message);
			}
		}

		private async Task SendInternal(ArraySegment<byte> message)
		{
			if (!IsClientConnected())
			{
				Logger.Debug(L($"Client is not connected to server, cannot send binary, length: {message.Count}"));
			}
			else
			{
				Logger.Trace(L($"Sending binary, length: {message.Count}"));
				await _client.SendAsync(message, WebSocketMessageType.Binary, endOfMessage: true, _cancellation.Token).ConfigureAwait(continueOnCapturedContext: false);
			}
		}
	}
}
namespace Websocket.Client.Logging
{
	internal interface ILog
	{
		bool Log(LogLevel logLevel, Func<string> messageFunc, Exception exception = null, params object[] formatParameters);
	}
	public interface ILogProvider
	{
		Logger GetLogger(string name);

		IDisposable OpenNestedContext(string message);

		IDisposable OpenMappedContext(string key, object value, bool destructure = false);
	}
	internal static class LogExtensions
	{
		internal static readonly object[] EmptyParams = new object[0];

		public static bool IsDebugEnabled(this ILog logger)
		{
			GuardAgainstNullLogger(logger);
			return logger.Log(LogLevel.Debug, null, null, EmptyParams);
		}

		public static bool IsErrorEnabled(this ILog logger)
		{
			GuardAgainstNullLogger(logger);
			return logger.Log(LogLevel.Error, null, null, EmptyParams);
		}

		public static bool IsFatalEnabled(this ILog logger)
		{
			GuardAgainstNullLogger(logger);
			return logger.Log(LogLevel.Fatal, null, null, EmptyParams);
		}

		public static bool IsInfoEnabled(this ILog logger)
		{
			GuardAgainstNullLogger(logger);
			return logger.Log(LogLevel.Info, null, null, EmptyParams);
		}

		public static bool IsTraceEnabled(this ILog logger)
		{
			GuardAgainstNullLogger(logger);
			return logger.Log(LogLevel.Trace, null, null, EmptyParams);
		}

		public static bool IsWarnEnabled(this ILog logger)
		{
			GuardAgainstNullLogger(logger);
			return logger.Log(LogLevel.Warn, null, null, EmptyParams);
		}

		public static void Debug(this ILog logger, Func<string> messageFunc)
		{
			GuardAgainstNullLogger(logger);
			logger.Log(LogLevel.Debug, WrapLogInternal(messageFunc), null, EmptyParams);
		}

		public static void Debug(this ILog logger, string message)
		{
			if (logger.IsDebugEnabled())
			{
				logger.Log(LogLevel.Debug, message.AsFunc(), null, EmptyParams);
			}
		}

		public static void Debug(this ILog logger, string message, params object[] args)
		{
			logger.DebugFormat(message, args);
		}

		public static void Debug(this ILog logger, Exception exception, string message, params object[] args)
		{
			logger.DebugException(message, exception, args);
		}

		public static void DebugFormat(this ILog logger, string message, params object[] args)
		{
			if (logger.IsDebugEnabled())
			{
				logger.LogFormat(LogLevel.Debug, message, args);
			}
		}

		public static void DebugException(this ILog logger, string message, Exception exception)
		{
			if (logger.IsDebugEnabled())
			{
				logger.Log(LogLevel.Debug, message.AsFunc(), exception, EmptyParams);
			}
		}

		public static void DebugException(this ILog logger, string message, Exception exception, params object[] args)
		{
			if (logger.IsDebugEnabled())
			{
				logger.Log(LogLevel.Debug, message.AsFunc(), exception, args);
			}
		}

		public static void Error(this ILog logger, Func<string> messageFunc)
		{
			GuardAgainstNullLogger(logger);
			logger.Log(LogLevel.Error, WrapLogInternal(messageFunc), null, EmptyParams);
		}

		public static void Error(this ILog logger, string message)
		{
			if (logger.IsErrorEnabled())
			{
				logger.Log(LogLevel.Error, message.AsFunc(), null, EmptyParams);
			}
		}

		public static void Error(this ILog logger, string message, params object[] args)
		{
			logger.ErrorFormat(message, args);
		}

		public static void Error(this ILog logger, Exception exception, string message, params object[] args)
		{
			logger.ErrorException(message, exception, args);
		}

		public static void ErrorFormat(this ILog logger, string message, params object[] args)
		{
			if (logger.IsErrorEnabled())
			{
				logger.LogFormat(LogLevel.Error, message, args);
			}
		}

		public static void ErrorException(this ILog logger, string message, Exception exception, params object[] args)
		{
			if (logger.IsErrorEnabled())
			{
				logger.Log(LogLevel.Error, message.AsFunc(), exception, args);
			}
		}

		public static void Fatal(this ILog logger, Func<string> messageFunc)
		{
			logger.Log(LogLevel.Fatal, WrapLogInternal(messageFunc), null, EmptyParams);
		}

		public static void Fatal(this ILog logger, string message)
		{
			if (logger.IsFatalEnabled())
			{
				logger.Log(LogLevel.Fatal, message.AsFunc(), null, EmptyParams);
			}
		}

		public static void Fatal(this ILog logger, string message, params object[] args)
		{
			logger.FatalFormat(message, args);
		}

		public static void Fatal(this ILog logger, Exception exception, string message, params object[] args)
		{
			logger.FatalException(message, exception, args);
		}

		public static void FatalFormat(this ILog logger, string message, params object[] args)
		{
			if (logger.IsFatalEnabled())
			{
				logger.LogFormat(LogLevel.Fatal, message, args);
			}
		}

		public static void FatalException(this ILog logger, string message, Exception exception, params object[] args)
		{
			if (logger.IsFatalEnabled())
			{
				logger.Log(LogLevel.Fatal, message.AsFunc(), exception, args);
			}
		}

		public static void Info(this ILog logger, Func<string> messageFunc)
		{
			GuardAgainstNullLogger(logger);
			logger.Log(LogLevel.Info, WrapLogInternal(messageFunc), null, EmptyParams);
		}

		public static void Info(this ILog logger, string message)
		{
			if (logger.IsInfoEnabled())
			{
				logger.Log(LogLevel.Info, message.AsFunc(), null, EmptyParams);
			}
		}

		public static void Info(this ILog logger, string message, params object[] args)
		{
			logger.InfoFormat(message, args);
		}

		public static void Info(this ILog logger, Exception exception, string message, params object[] args)
		{
			logger.InfoException(message, exception, args);
		}

		public static void InfoFormat(this ILog logger, string message, params object[] args)
		{
			if (logger.IsInfoEnabled())
			{
				logger.LogFormat(LogLevel.Info, message, args);
			}
		}

		public static void InfoException(this ILog logger, string message, Exception exception, params object[] args)
		{
			if (logger.IsInfoEnabled())
			{
				logger.Log(LogLevel.Info, message.AsFunc(), exception, args);
			}
		}

		public static void Trace(this ILog logger, Func<string> messageFunc)
		{
			GuardAgainstNullLogger(logger);
			logger.Log(LogLevel.Trace, WrapLogInternal(messageFunc), null, EmptyParams);
		}

		public static void Trace(this ILog logger, string message)
		{
			if (logger.IsTraceEnabled())
			{
				logger.Log(LogLevel.Trace, message.AsFunc(), null, EmptyParams);
			}
		}

		public static void Trace(this ILog logger, string message, params object[] args)
		{
			logger.TraceFormat(message, args);
		}

		public static void Trace(this ILog logger, Exception exception, string message, params object[] args)
		{
			logger.TraceException(message, exception, args);
		}

		public static void TraceFormat(this ILog logger, string message, params object[] args)
		{
			if (logger.IsTraceEnabled())
			{
				logger.LogFormat(LogLevel.Trace, message, args);
			}
		}

		public static void TraceException(this ILog logger, string message, Exception exception, params object[] args)
		{
			if (logger.IsTraceEnabled())
			{
				logger.Log(LogLevel.Trace, message.AsFunc(), exception, args);
			}
		}

		public static void Warn(this ILog logger, Func<string> messageFunc)
		{
			GuardAgainstNullLogger(logger);
			logger.Log(LogLevel.Warn, WrapLogInternal(messageFunc), null, EmptyParams);
		}

		public static void Warn(this ILog logger, string message)
		{
			if (logger.IsWarnEnabled())
			{
				logger.Log(LogLevel.Warn, message.AsFunc(), null, EmptyParams);
			}
		}

		public static void Warn(this ILog logger, string message, params object[] args)
		{
			logger.WarnFormat(message, args);
		}

		public static void Warn(this ILog logger, Exception exception, string message, params object[] args)
		{
			logger.WarnException(message, exception, args);
		}

		public static void WarnFormat(this ILog logger, string message, params object[] args)
		{
			if (logger.IsWarnEnabled())
			{
				logger.LogFormat(LogLevel.Warn, message, args);
			}
		}

		public static void WarnException(this ILog logger, string message, Exception exception, params object[] args)
		{
			if (logger.IsWarnEnabled())
			{
				logger.Log(LogLevel.Warn, message.AsFunc(), exception, args);
			}
		}

		private static void GuardAgainstNullLogger(ILog logger)
		{
			if (logger == null)
			{
				throw new ArgumentNullException("logger");
			}
		}

		private static void LogFormat(this ILog logger, LogLevel logLevel, string message, params object[] args)
		{
			logger.Log(logLevel, message.AsFunc(), null, args);
		}

		private static Func<T> AsFunc<T>(this T value) where T : class
		{
			return value.Return;
		}

		private static T Return<T>(this T value)
		{
			return value;
		}

		internal static Func<string> WrapLogSafeInternal(LoggerExecutionWrapper logger, Func<string> messageFunc)
		{
			return delegate
			{
				try
				{
					return messageFunc();
				}
				catch (Exception exception)
				{
					logger.WrappedLogger(LogLevel.Error, () => "Failed to generate log message", exception, EmptyParams);
				}
				return null;
			};
		}

		private static Func<string> WrapLogInternal(Func<string> messageFunc)
		{
			return () => messageFunc();
		}
	}
	public enum LogLevel
	{
		Trace,
		Debug,
		Info,
		Warn,
		Error,
		Fatal
	}
	public static class LogProvider
	{
		internal delegate bool IsLoggerAvailable();

		internal delegate ILogProvider CreateLogProvider();

		internal class NoOpLogger : ILog
		{
			internal static readonly NoOpLogger Instance = new NoOpLogger();

			public bool Log(LogLevel logLevel, Func<string> messageFunc, Exception exception, params object[] formatParameters)
			{
				return false;
			}
		}

		private static readonly Lazy<ILogProvider> ResolvedLogProvider;

		private static ILogProvider s_currentLogProvider;

		private static Action<ILogProvider> s_onCurrentLogProviderSet;

		internal static readonly List<Tuple<IsLoggerAvailable, CreateLogProvider>> LogProviderResolvers;

		public static bool IsDisabled { get; set; }

		internal static Action<ILogProvider> OnCurrentLogProviderSet
		{
			set
			{
				s_onCurrentLogProviderSet = value;
				RaiseOnCurrentLogProviderSet();
			}
		}

		internal static ILogProvider CurrentLogProvider => s_currentLogProvider;

		static LogProvider()
		{
			ResolvedLogProvider = new Lazy<ILogProvider>(ForceResolveLogProvider);
			LogProviderResolvers = new List<Tuple<IsLoggerAvailable, CreateLogProvider>>
			{
				new Tuple<IsLoggerAvailable, CreateLogProvider>(SerilogLogProvider.IsLoggerAvailable, () => new SerilogLogProvider()),
				new Tuple<IsLoggerAvailable, CreateLogProvider>(NLogLogProvider.IsLoggerAvailable, () => new NLogLogProvider()),
				new Tuple<IsLoggerAvailable, CreateLogProvider>(Log4NetLogProvider.IsLoggerAvailable, () => new Log4NetLogProvider()),
				new Tuple<IsLoggerAvailable, CreateLogProvider>(LoupeLogProvider.IsLoggerAvailable, () => new LoupeLogProvider())
			};
			IsDisabled = false;
		}

		public static void SetCurrentLogProvider(ILogProvider logProvider)
		{
			s_currentLogProvider = logProvider;
			RaiseOnCurrentLogProviderSet();
		}

		internal static ILog For<T>()
		{
			return GetLogger(typeof(T));
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		internal static ILog GetCurrentClassLogger()
		{
			return GetLogger(new StackFrame(1, needFileInfo: false).GetMethod().DeclaringType);
		}

		internal static ILog GetLogger(Type type, string fallbackTypeName = "System.Object")
		{
			return GetLogger((type != null) ? type.ToString() : fallbackTypeName);
		}

		internal static ILog GetLogger(string name)
		{
			ILogProvider logProvider = CurrentLogProvider ?? ResolveLogProvider();
			if (logProvider != null)
			{
				return new LoggerExecutionWrapper(logProvider.GetLogger(name), () => IsDisabled);
			}
			return NoOpLogger.Instance;
		}

		internal static IDisposable OpenNestedContext(string message)
		{
			ILogProvider logProvider = CurrentLogProvider ?? ResolveLogProvider();
			if (logProvider != null)
			{
				return logProvider.OpenNestedContext(message);
			}
			return new DisposableAction(delegate
			{
			});
		}

		internal static IDisposable OpenMappedContext(string key, object value, bool destructure = false)
		{
			ILogProvider logProvider = CurrentLogProvider ?? ResolveLogProvider();
			if (logProvider != null)
			{
				return logProvider.OpenMappedContext(key, value, destructure);
			}
			return new DisposableAction(delegate
			{
			});
		}

		private static void RaiseOnCurrentLogProviderSet()
		{
			if (s_onCurrentLogProviderSet != null)
			{
				s_onCurrentLogProviderSet(s_currentLogProvider);
			}
		}

		internal static ILogProvider ResolveLogProvider()
		{
			return ResolvedLogProvider.Value;
		}

		internal static ILogProvider ForceResolveLogProvider()
		{
			try
			{
				foreach (Tuple<IsLoggerAvailable, CreateLogProvider> logProviderResolver in LogProviderResolvers)
				{
					if (logProviderResolver.Item1())
					{
						return logProviderResolver.Item2();
					}
				}
			}
			catch (Exception arg)
			{
				Console.WriteLine("Exception occurred resolving a log provider. Logging for this assembly {0} is disabled. {1}", typeof(LogProvider).Assembly.FullName, arg);
			}
			return null;
		}
	}
	public delegate bool Logger(LogLevel logLevel, Func<string> messageFunc, Exception exception = null, params object[] formatParameters);
	internal class LoggerExecutionWrapper : ILog
	{
		private interface ICallSiteExtension
		{
			bool Log(Logger logger, LogLevel logLevel, Func<string> messageFunc, Exception exception, object[] formatParameters);
		}

		private class CallSiteExtension : ICallSiteExtension
		{
			bool ICallSiteExtension.Log(Logger logger, LogLevel logLevel, Func<string> messageFunc, Exception exception, object[] formatParameters)
			{
				return logger(logLevel, messageFunc, exception, formatParameters);
			}
		}

		internal const string FailedToGenerateLogMessage = "Failed to generate log message";

		private readonly ICallSiteExtension _callsiteLogger;

		private readonly Func<bool> _getIsDisabled;

		private Func<string> _lastExtensionMethod;

		internal Logger WrappedLogger { get; }

		internal LoggerExecutionWrapper(Logger logger, Func<bool> getIsDisabled = null)
		{
			WrappedLogger = logger;
			_callsiteLogger = new CallSiteExtension();
			_getIsDisabled = getIsDisabled ?? ((Func<bool>)(() => false));
		}

		public bool Log(LogLevel logLevel, Func<string> messageFunc, Exception exception = null, params object[] formatParameters)
		{
			if (_getIsDisabled())
			{
				return false;
			}
			if (messageFunc == null)
			{
				return WrappedLogger(logLevel, null, null, LogExtensions.EmptyParams);
			}
			Func<string> func = _lastExtensionMethod;
			if (func == null || !func.Equals(messageFunc))
			{
				func = null;
				Type declaringType = messageFunc.Method.DeclaringType;
				if (declaringType == typeof(LogExtensions) || (declaringType != null && declaringType.DeclaringType == typeof(LogExtensions)))
				{
					func = messageFunc;
				}
			}
			if (func != null)
			{
				_lastExtensionMethod = func;
				return WrappedLogger(logLevel, LogExtensions.WrapLogSafeInternal(this, messageFunc), exception, formatParameters);
			}
			Func<string> messageFunc2 = delegate
			{
				try
				{
					return messageFunc();
				}
				catch (Exception exception2)
				{
					WrappedLogger(LogLevel.Error, () => "Failed to generate log message", exception2);
				}
				return null;
			};
			return _callsiteLogger.Log(WrappedLogger, logLevel, messageFunc2, exception, formatParameters);
		}
	}
}
namespace Websocket.Client.Logging.LogProviders
{
	internal class DisposableAction : IDisposable
	{
		private readonly Action _onDispose;

		public DisposableAction(Action onDispose = null)
		{
			_onDispose = onDispose;
		}

		public void Dispose()
		{
			if (_onDispose != null)
			{
				_onDispose();
			}
		}
	}
	public class LibLogException : Exception
	{
		public LibLogException(string message)
			: base(message)
		{
		}

		public LibLogException(string message, Exception inner)
			: base(message, inner)
		{
		}
	}
	internal class Log4NetLogProvider : LogProviderBase
	{
		internal class Log4NetLogger
		{
			private static object s_levelAll;

			private static object s_levelDebug;

			private static object s_levelInfo;

			private static object s_levelWarn;

			private static object s_levelError;

			private static object s_levelFatal;

			private static Func<object, object, bool> s_isEnabledForDelegate;

			private static Action<object, object> s_logDelegate;

			private static Func<object, Type, object, string, Exception, object> s_createLoggingEvent;

			private static Action<object, string, object> s_loggingEventPropertySetter;

			private static readonly Lazy<bool> Initialized = new Lazy<bool>(Initialize, LazyThreadSafetyMode.ExecutionAndPublication);

			private static Exception s_initializeException;

			private readonly object _logger;

			internal Log4NetLogger(object logger)
			{
				_logger = logger.GetType().GetProperty("Logger").GetValue(logger);
			}

			private static bool Initialize()
			{
				try
				{
					Type type = LogProviderBase.FindType("log4net.Core.Level", "log4net");
					if (type == null)
					{
						throw new LibLogException("Type log4net.Core.Level was not found.");
					}
					List<FieldInfo> source = type.GetFields().ToList();
					s_levelAll = source.First((FieldInfo x) => x.Name == "All").GetValue(null);
					s_levelDebug = source.First((FieldInfo x) => x.Name == "Debug").GetValue(null);
					s_levelInfo = source.First((FieldInfo x) => x.Name == "Info").GetValue(null);
					s_levelWarn = source.First((FieldInfo x) => x.Name == "Warn").GetValue(null);
					s_levelError = source.First((FieldInfo x) => x.Name == "Error").GetValue(null);
					s_levelFatal = source.First((FieldInfo x) => x.Name == "Fatal").GetValue(null);
					Type type2 = LogProviderBase.FindType("log4net.Core.ILogger", "log4net");
					if (type2 == null)
					{
						throw new LibLogException("Type log4net.Core.ILogger, was not found.");
					}
					ParameterExpression parameterExpression = Expression.Parameter(typeof(object));
					UnaryExpression instanceCast = Expression.Convert(parameterExpression, type2);
					ParameterExpression parameterExpression2 = Expression.Parameter(typeof(object));
					UnaryExpression levelCast = Expression.Convert(parameterExpression2, type);
					s_isEnabledForDelegate = GetIsEnabledFor(type2, type, instanceCast, levelCast, parameterExpression, parameterExpression2);
					Type loggingEventType = LogProviderBase.FindType("log4net.Core.LoggingEvent", "log4net");
					s_createLoggingEvent = GetCreateLoggingEvent(parameterExpression, instanceCast, parameterExpression2, levelCast, loggingEventType);
					s_logDelegate = GetLogDelegate(type2, loggingEventType, instanceCast, parameterExpression);
					s_loggingEventPropertySetter = GetLoggingEventPropertySetter(loggingEventType);
				}
				catch (Exception ex)
				{
					s_initializeException = ex;
					return false;
				}
				return true;
			}

			private static Action<object, object> GetLogDelegate(Type loggerType, Type loggingEventType, UnaryExpression instanceCast, ParameterExpression instanceParam)
			{
				MethodInfo method = loggerType.GetMethod("Log", loggingEventType);
				ParameterExpression parameterExpression = Expression.Parameter(typeof(object), "loggingEvent");
				UnaryExpression unaryExpression = Expression.Convert(parameterExpression, loggingEventType);
				return Expression.Lambda<Action<object, object>>(Expression.Call(instanceCast, method, unaryExpression), new ParameterExpression[2] { instanceParam, parameterExpression }).Compile();
			}

			private static Func<object, Type, object, string, Exception, object> GetCreateLoggingEvent(ParameterExpression instanceParam, UnaryExpression instanceCast, ParameterExpression levelParam, UnaryExpression levelCast, Type loggingEventType)
			{
				ParameterExpression parameterExpression = Expression.Parameter(typeof(Type));
				ParameterExpression parameterExpression2 = Expression.Parameter(typeof(string));
				ParameterExpression parameterExpression3 = Expression.Parameter(typeof(Exception));
				PropertyInfo property = loggingEventType.GetProperty("Repository");
				PropertyInfo property2 = loggingEventType.GetProperty("Level");
				return Expression.Lambda<Func<object, Type, object, string, Exception, object>>(Expression.New(loggingEventType.GetConstructorPortable(typeof(Type), property.PropertyType, typeof(string), property2.PropertyType, typeof(object), typeof(Exception)), parameterExpression, Expression.Property(instanceCast, "Repository"), Expression.Property(instanceCast, "Name"), levelCast, parameterExpression2, parameterExpression3), new ParameterExpression[5] { instanceParam, parameterExpression, levelParam, parameterExpression2, parameterExpression3 }).Compile();
			}

			private static Func<object, object, bool> GetIsEnabledFor(Type loggerType, Type logEventLevelType, UnaryExpression instanceCast, UnaryExpression levelCast, ParameterExpression instanceParam, ParameterExpression levelParam)
			{
				MethodInfo method = loggerType.GetMethod("IsEnabledFor", logEventLevelType);
				return Expression.Lambda<Func<object, object, bool>>(Expression.Call(instanceCast, method, levelCast), new ParameterExpression[2] { instanceParam, levelParam }).Compile();
			}

			private static Action<object, string, object> GetLoggingEventPropertySetter(Type loggingEventType)
			{
				ParameterExpression parameterExpression = Expression.Parameter(typeof(object), "loggingEvent");
				ParameterExpression parameterExpression2 = Expression.Parameter(typeof(string), "key");
				ParameterExpression parameterExpression3 = Expression.Parameter(typeof(object), "value");
				PropertyInfo property = loggingEventType.GetProperty("Properties");
				PropertyInfo property2 = property.PropertyType.GetProperty("Item");
				return Expression.Lambda<Action<object, string, object>>(Expression.Assign(Expression.Property(Expression.Property(Expression.Convert(parameterExpression, loggingEventType), property), property2, parameterExpression2), parameterExpression3), new ParameterExpression[3] { parameterExpression, parameterExpression2, parameterExpression3 }).Compile();
			}

			public bool Log(LogLevel logLevel, Func<string> messageFunc, Exception exception, params object[] formatParameters)
			{
				if (!Initialized.Value)
				{
					throw new LibLogException("Unable to log due to problem initializing the log provider. See inner exception for details.", s_initializeException);
				}
				if (messageFunc == null)
				{
					return IsLogLevelEnable(logLevel);
				}
				if (!IsLogLevelEnable(logLevel))
				{
					return false;
				}
				IEnumerable<string> patternMatches;
				string arg = LogMessageFormatter.FormatStructuredMessage(messageFunc(), formatParameters, out patternMatches);
				Type typeFromHandle = typeof(Log4NetLogger);
				Type declaringType = messageFunc.Method.DeclaringType;
				if (declaringType == typeof(LogExtensions) || (declaringType != null && declaringType.DeclaringType == typeof(LogExtensions)))
				{
					typeFromHandle = typeof(LogExtensions);
				}
				else if (declaringType == typeof(LoggerExecutionWrapper) || (declaringType != null && declaringType.DeclaringType == typeof(LoggerExecutionWrapper)))
				{
					typeFromHandle = typeof(LoggerExecutionWrapper);
				}
				object arg2 = TranslateLevel(logLevel);
				object obj = s_createLoggingEvent(_logger, typeFromHandle, arg2, arg, exception);
				PopulateProperties(obj, patternMatches, formatParameters);
				s_logDelegate(_logger, obj);
				return true;
			}

			private void PopulateProperties(object loggingEvent, IEnumerable<string> patternMatches, IEnumerable<object> formatParameters)
			{
				string[] array = (patternMatches as string[]) ?? patternMatches.ToArray();
				if (!array.Any())
				{
					return;
				}
				foreach (KeyValuePair<string, object> item in array.Zip(formatParameters, (string key, object value) => new KeyValuePair<string, object>(key, value)))
				{
					s_loggingEventPropertySetter(loggingEvent, item.Key, item.Value);
				}
			}

			private bool IsLogLevelEnable(LogLevel logLevel)
			{
				object arg = TranslateLevel(logLevel);
				return s_isEnabledForDelegate(_logger, arg);
			}

			private object TranslateLevel(LogLevel logLevel)
			{
				return logLevel switch
				{
					LogLevel.Trace => s_levelAll, 
					LogLevel.Debug => s_levelDebug, 
					LogLevel.Info => s_levelInfo, 
					LogLevel.Warn => s_levelWarn, 
					LogLevel.Error => s_levelError, 
					LogLevel.Fatal => s_levelFatal, 
					_ => throw new ArgumentOutOfRangeException("logLevel", logLevel, null), 
				};
			}
		}

		private readonly Func<string, object> _getLoggerByNameDelegate;

		public static bool ProviderIsAvailableOverride { get; set; } = true;


		public Log4NetLogProvider()
		{
			if (!IsLoggerAvailable())
			{
				throw new LibLogException("log4net.LogManager not found");
			}
			_getLoggerByNameDelegate = GetGetLoggerMethodCall();
		}

		public override Logger GetLogger(string name)
		{
			return new Log4NetLogger(_getLoggerByNameDelegate(name)).Log;
		}

		internal static bool IsLoggerAvailable()
		{
			if (ProviderIsAvailableOverride)
			{
				return GetLogManagerType() != null;
			}
			return false;
		}

		protected override OpenNdc GetOpenNdcMethod()
		{
			PropertyInfo property = LogProviderBase.FindType("log4net.LogicalThreadContext", "log4net").GetProperty("Stacks");
			PropertyInfo property2 = property.PropertyType.GetProperty("Item");
			MethodInfo method = property2.PropertyType.GetMethod("Push");
			ParameterExpression parameterExpression = Expression.Parameter(typeof(string), "message");
			return Expression.Lambda<OpenNdc>(Expression.Call(Expression.Property(Expression.Property(null, property), property2, Expression.Constant("NDC")), method, parameterExpression), new ParameterExpression[1] { parameterExpression }).Compile();
		}

		protected override OpenMdc GetOpenMdcMethod()
		{
			PropertyInfo property = LogProviderBase.FindType("log4net.LogicalThreadContext", "log4net").GetProperty("Properties");
			Type propertyType = property.PropertyType;
			PropertyInfo property2 = propertyType.GetProperty("Item");
			MethodInfo method = propertyType.GetMethod("Remove");
			ParameterExpression parameterExpression = Expression.Parameter(typeof(string), "key");
			ParameterExpression parameterExpression2 = Expression.Parameter(typeof(string), "value");
			MemberExpression instance = Expression.Property(null, property);
			BinaryExpression body = Expression.Assign(Expression.Property(instance, property2, parameterExpression), parameterExpression2);
			MethodCallExpression body2 = Expression.Call(instance, method, parameterExpression);
			Action<string, string> set = Expression.Lambda<Action<string, string>>(body, new ParameterExpression[2] { parameterExpression, parameterExpression2 }).Compile();
			Action<string> remove = Expression.Lambda<Action<string>>(body2, new ParameterExpression[1] { parameterExpression }).Compile();
			return delegate(string key, object value, bool _)
			{
				set(key, value.ToString());
				return new DisposableAction(delegate
				{
					remove(key);
				});
			};
		}

		private static Type GetLogManagerType()
		{
			return LogProviderBase.FindType("log4net.LogManager", "log4net");
		}

		private static Func<string, object> GetGetLoggerMethodCall()
		{
			Type logManagerType = GetLogManagerType();
			Assembly log4netAssembly = Assembly.GetAssembly(logManagerType);
			MethodInfo method = logManagerType.GetMethod("GetLogger", typeof(Assembly), typeof(string));
			ParameterExpression parameterExpression = Expression.Parameter(typeof(Assembly), "repositoryAssembly");
			ParameterExpression parameterExpression2 = Expression.Parameter(typeof(string), "name");
			MethodCallExpression body = Expression.Call(null, method, parameterExpression, parameterExpression2);
			Func<Assembly, string, object> lambda = Expression.Lambda<Func<Assembly, string, object>>(body, new ParameterExpression[2] { parameterExpression, parameterExpression2 }).Compile();
			return (string name) => lambda(log4netAssembly, name);
		}
	}
	internal static class LogMessageFormatter
	{
		private static readonly Regex Pattern = new Regex("(?<!{){@?(?<arg>[^ :{}]+)(?<format>:[^}]+)?}", RegexOptions.Compiled);

		public static Func<string> SimulateStructuredLogging(Func<string> messageBuilder, object[] formatParameters)
		{
			if (formatParameters == null || formatParameters.Length == 0)
			{
				return messageBuilder;
			}
			IEnumerable<string> patternMatches;
			return () => FormatStructuredMessage(messageBuilder(), formatParameters, out patternMatches);
		}

		private static string ReplaceFirst(string text, string search, string replace)
		{
			int num = text.IndexOf(search, StringComparison.Ordinal);
			if (num < 0)
			{
				return text;
			}
			return text.Substring(0, num) + replace + text.Substring(num + search.Length);
		}

		public static string FormatStructuredMessage(string targetMessage, object[] formatParameters, out IEnumerable<string> patternMatches)
		{
			if (formatParameters == null || formatParameters.Length == 0)
			{
				patternMatches = Enumerable.Empty<string>();
				return targetMessage;
			}
			List<string> list = null;
			foreach (Match item in Pattern.Matches(targetMessage))
			{
				string value = item.Groups["arg"].Value;
				if (!int.TryParse(value, out var _))
				{
					list = list ?? new List<string>(formatParameters.Length);
					int num = list.IndexOf(value);
					if (num == -1)
					{
						num = list.Count;
						list.Add(value);
					}
					targetMessage = ReplaceFirst(targetMessage, item.Value, "{" + num + item.Groups["format"].Value + "}");
				}
			}
			IEnumerable<string> enumerable = list;
			patternMatches = enumerable ?? Enumerable.Empty<string>();
			try
			{
				return string.Format(CultureInfo.InvariantCulture, targetMessage, formatParameters);
			}
			catch (FormatException innerException)
			{
				throw new FormatException("The input string '" + targetMessage + "' could not be formatted using string.Format", innerException);
			}
		}
	}
	internal abstract class LogProviderBase : ILogProvider
	{
		protected delegate IDisposable OpenNdc(string message);

		protected delegate IDisposable OpenMdc(string key, object value, bool destructure);

		private static readonly IDisposable NoopDisposableInstance = new DisposableAction();

		private readonly Lazy<OpenMdc> _lazyOpenMdcMethod;

		protected const string ErrorInitializingProvider = "Unable to log due to problem initializing the log provider. See inner exception for details.";

		private readonly Lazy<OpenNdc> _lazyOpenNdcMethod;

		protected LogProviderBase()
		{
			_lazyOpenNdcMethod = new Lazy<OpenNdc>(GetOpenNdcMethod);
			_lazyOpenMdcMethod = new Lazy<OpenMdc>(GetOpenMdcMethod);
		}

		public abstract Logger GetLogger(string name);

		public IDisposable OpenNestedContext(string message)
		{
			return _lazyOpenNdcMethod.Value(message);
		}

		public IDisposable OpenMappedContext(string key, object value, bool destructure = false)
		{
			return _lazyOpenMdcMethod.Value(key, value, destructure);
		}

		protected virtual OpenNdc GetOpenNdcMethod()
		{
			return (string _) => NoopDisposableInstance;
		}

		protected virtual OpenMdc GetOpenMdcMethod()
		{
			return (string _, object __, bool ___) => NoopDisposableInstance;
		}

		protected static Type FindType(string typeName, string assemblyName)
		{
			return FindType(typeName, new string[1] { assemblyName });
		}

		protected static Type FindType(string typeName, IReadOnlyList<string> assemblyNames)
		{
			return assemblyNames.Select((string assemblyName) => Type.GetType(typeName + ", " + assemblyName)).FirstOrDefault((Type type) => type != null) ?? Type.GetType(typeName);
		}
	}
	internal class LoupeLogProvider : LogProviderBase
	{
		internal delegate void WriteDelegate(int severity, string logSystem, int skipFrames, Exception exception, bool attributeToException, int writeMode, string detailsXml, string category, string caption, string description, params object[] args);

		internal class LoupeLogger
		{
			private const string LogSystem = "LibLog";

			private readonly string _category;

			private readonly WriteDelegate _logWriteDelegate;

			private readonly int _skipLevel;

			internal LoupeLogger(string category, WriteDelegate logWriteDelegate)
			{
				_category = category;
				_logWriteDelegate = logWriteDelegate;
				_skipLevel = 1;
			}

			public bool Log(LogLevel logLevel, Func<string> messageFunc, Exception exception, params object[] formatParameters)
			{
				if (messageFunc == null)
				{
					return true;
				}
				messageFunc = LogMessageFormatter.SimulateStructuredLogging(messageFunc, formatParameters);
				_logWriteDelegate(ToLogMessageSeverity(logLevel), "LibLog", _skipLevel, exception, true, 0, null, _category, null, messageFunc());
				return true;
			}

			private static int ToLogMessageSeverity(LogLevel logLevel)
			{
				return logLevel switch
				{
					LogLevel.Trace => TraceEventTypeValues.Verbose, 
					LogLevel.Debug => TraceEventTypeValues.Verbose, 
					LogLevel.Info => TraceEventTypeValues.Information, 
					LogLevel.Warn => TraceEventTypeValues.Warning, 
					LogLevel.Error => TraceEventTypeValues.Error, 
					LogLevel.Fatal => TraceEventTypeValues.Critical, 
					_ => throw new ArgumentOutOfRangeException("logLevel"), 
				};
			}
		}

		private readonly WriteDelegate _logWriteDelegate;

		private const string LoupeAgentNetCoreDll = "Loupe.Agent.NETCore";

		private const string LoupeAgentNetFrameworkDll = "Gibraltar.Agent";

		public static bool ProviderIsAvailableOverride { get; set; } = true;


		public LoupeLogProvider()
		{
			if (!IsLoggerAvailable())
			{
				throw new LibLogException("Gibraltar.Agent.Log (Loupe) not found");
			}
			_logWriteDelegate = GetLogWriteDelegate();
		}

		public override Logger GetLogger(string name)
		{
			return new LoupeLogger(name, _logWriteDelegate).Log;
		}

		public static bool IsLoggerAvailable()
		{
			if (ProviderIsAvailableOverride)
			{
				return GetLogManagerType() != null;
			}
			return false;
		}

		private static Type GetTypeFromCoreOrFrameworkDll(string typeName)
		{
			return LogProviderBase.FindType(typeName, new string[2] { "Loupe.Agent.NETCore", "Gibraltar.Agent" });
		}

		private static Type GetLogManagerType()
		{
			return GetTypeFromCoreOrFrameworkDll("Gibraltar.Agent.Log");
		}

		private static WriteDelegate GetLogWriteDelegate()
		{
			Type logManagerType = GetLogManagerType();
			Type typeFromCoreOrFrameworkDll = GetTypeFromCoreOrFrameworkDll("Gibraltar.Agent.LogMessageSeverity");
			Type typeFromCoreOrFrameworkDll2 = GetTypeFromCoreOrFrameworkDll("Gibraltar.Agent.LogWriteMode");
			return (WriteDelegate)logManagerType.GetMethod("Write", typeFromCoreOrFrameworkDll, typeof(string), typeof(int), typeof(Exception), typeof(bool), typeFromCoreOrFrameworkDll2, typeof(string), typeof(string), typeof(string), typeof(string), typeof(object[])).CreateDelegate(typeof(WriteDelegate));
		}
	}
	internal class NLogLogProvider : LogProviderBase
	{
		internal class NLogLogger
		{
			private delegate string LoggerNameDelegate(object logger);

			private delegate void LogEventDelegate(object logger, Type wrapperType, object logEvent);

			private delegate bool IsEnabledDelegate(object logger);

			private delegate void LogDelegate(object logger, string message);

			private delegate void LogExceptionDelegate(object logger, string message, Exception exception);

			private static Func<string, object, string, object[], Exception, object> s_logEventInfoFact;

			private static object s_levelTrace;

			private static object s_levelDebug;

			private static object s_levelInfo;

			private static object s_levelWarn;

			private static object s_levelError;

			private static object s_levelFatal;

			private static bool s_structuredLoggingEnabled;

			private static readonly Lazy<bool> Initialized = new Lazy<bool>(Initialize);

			private static Exception s_initializeException;

			private static LoggerNameDelegate s_loggerNameDelegate;

			private static LogEventDelegate s_logEventDelegate;

			private static IsEnabledDelegate s_isTraceEnabledDelegate;

			private static IsEnabledDelegate s_isDebugEnabledDelegate;

			private static IsEnabledDelegate s_isInfoEnabledDelegate;

			private static IsEnabledDelegate s_isWarnEnabledDelegate;

			private static IsEnabledDelegate s_isErrorEnabledDelegate;

			private static IsEnabledDelegate s_isFatalEnabledDelegate;

			private static LogDelegate s_traceDelegate;

			private static LogDelegate s_debugDelegate;

			private static LogDelegate s_infoDelegate;

			private static LogDelegate s_warnDelegate;

			private static LogDelegate s_errorDelegate;

			private static LogDelegate s_fatalDelegate;

			private static LogExceptionDelegate s_traceExceptionDelegate;

			private static LogExceptionDelegate s_debugExceptionDelegate;

			private static LogExceptionDelegate s_infoExceptionDelegate;

			private static LogExceptionDelegate s_warnExceptionDelegate;

			private static LogExceptionDelegate s_errorExceptionDelegate;

			private static LogExceptionDelegate s_fatalExceptionDelegate;

			private readonly object _logger;

			internal NLogLogger(object logger)
			{
				_logger = logger;
			}

			private static bool Initialize()
			{
				try
				{
					Type type = LogProviderBase.FindType("NLog.LogLevel", "NLog");
					if (type == null)
					{
						throw new LibLogException("Type NLog.LogLevel was not found.");
					}
					List<FieldInfo> source = type.GetFields().ToList();
					s_levelTrace = source.First((FieldInfo x) => x.Name == "Trace").GetValue(null);
					s_levelDebug = source.First((FieldInfo x) => x.Name == "Debug").GetValue(null);
					s_levelInfo = source.First((FieldInfo x) => x.Name == "Info").GetValue(null);
					s_levelWarn = source.First((FieldInfo x) => x.Name == "Warn").GetValue(null);
					s_levelError = source.First((FieldInfo x) => x.Name == "Error").GetValue(null);
					s_levelFatal = source.First((FieldInfo x) => x.Name == "Fatal").GetValue(null);
					Type type2 = LogProviderBase.FindType("NLog.LogEventInfo", "NLog");
					if (type2 == null)
					{
						throw new LibLogException("Type NLog.LogEventInfo was not found.");
					}
					ConstructorInfo constructorPortable = type2.GetConstructorPortable(type, typeof(string), typeof(IFormatProvider), typeof(string), typeof(object[]), typeof(Exception));
					ParameterExpression parameterExpression = Expression.Parameter(typeof(string));
					ParameterExpression parameterExpression2 = Expression.Parameter(typeof(object));
					ParameterExpression parameterExpression3 = Expression.Parameter(typeof(string));
					ParameterExpression parameterExpression4 = Expression.Parameter(typeof(object[]));
					ParameterExpression parameterExpression5 = Expression.Parameter(typeof(Exception));
					UnaryExpression unaryExpression = Expression.Convert(parameterExpression2, type);
					s_logEventInfoFact = Expression.Lambda<Func<string, object, string, object[], Exception, object>>(Expression.New(constructorPortable, unaryExpression, parameterExpression, Expression.Constant(null, typeof(IFormatProvider)), parameterExpression3, parameterExpression4, parameterExpression5), new ParameterExpression[5] { parameterExpression, parameterExpression2, parameterExpression3, parameterExpression4, parameterExpression5 }).Compile();
					Type loggerType = LogProviderBase.FindType("NLog.Logger", "NLog");
					s_loggerNameDelegate = GetLoggerNameDelegate(loggerType);
					s_logEventDelegate = GetLogEventDelegate(loggerType, type2);
					s_isTraceEnabledDelegate = GetIsEnabledDelegate(loggerType, "IsTraceEnabled");
					s_isDebugEnabledDelegate = GetIsEnabledDelegate(loggerType, "IsDebugEnabled");
					s_isInfoEnabledDelegate = GetIsEnabledDelegate(loggerType, "IsInfoEnabled");
					s_isWarnEnabledDelegate = GetIsEnabledDelegate(loggerType, "IsWarnEnabled");
					s_isErrorEnabledDelegate = GetIsEnabledDelegate(loggerType, "IsErrorEnabled");
					s_isFatalEnabledDelegate = GetIsEnabledDelegate(loggerType, "IsFatalEnabled");
					s_traceDelegate = GetLogDelegate(loggerType, "Trace");
					s_debugDelegate = GetLogDelegate(loggerType, "Debug");
					s_infoDelegate = GetLogDelegate(loggerType, "Info");
					s_warnDelegate = GetLogDelegate(loggerType, "Warn");
					s_errorDelegate = GetLogDelegate(loggerType, "Error");
					s_fatalDelegate = GetLogDelegate(loggerType, "Fatal");
					s_traceExceptionDelegate = GetLogExceptionDelegate(loggerType, "TraceException");
					s_debugExceptionDelegate = GetLogExceptionDelegate(loggerType, "DebugException");
					s_infoExceptionDelegate = GetLogExceptionDelegate(loggerType, "InfoException");
					s_warnExceptionDelegate = GetLogExceptionDelegate(loggerType, "WarnException");
					s_errorExceptionDelegate = GetLogExceptionDelegate(loggerType, "ErrorException");
					s_fatalExceptionDelegate = GetLogExceptionDelegate(loggerType, "FatalException");
					s_structuredLoggingEnabled = IsStructuredLoggingEnabled();
				}
				catch (Exception ex)
				{
					s_initializeException = ex;
					return false;
				}
				return true;
			}

			private static IsEnabledDelegate GetIsEnabledDelegate(Type loggerType, string propertyName)
			{
				PropertyInfo property = loggerType.GetProperty(propertyName);
				ParameterExpression parameterExpression = Expression.Parameter(typeof(object));
				return Expression.Lambda<IsEnabledDelegate>(Expression.Property(Expression.Convert(parameterExpression, loggerType), property), new ParameterExpression[1] { parameterExpression }).Compile();
			}

			private static LoggerNameDelegate GetLoggerNameDelegate(Type loggerType)
			{
				PropertyInfo property = loggerType.GetProperty("Name");
				ParameterExpression parameterExpression = Expression.Parameter(typeof(object));
				return Expression.Lambda<LoggerNameDelegate>(Expression.Property(Expression.Convert(parameterExpression, loggerType), property), new ParameterExpression[1] { parameterExpression }).Compile();
			}

			private static LogDelegate GetLogDelegate(Type loggerType, string name)
			{
				MethodInfo method = loggerType.GetMethod(name, new Type[1] { typeof(string) });
				ParameterExpression parameterExpression = Expression.Parameter(typeof(object));
				UnaryExpression instance = Expression.Convert(parameterExpression, loggerType);
				ParameterExpression parameterExpression2 = Expression.Parameter(typeof(string));
				return Expression.Lambda<LogDelegate>(Expression.Call(instance, method, parameterExpression2), new ParameterExpression[2] { parameterExpression, parameterExpression2 }).Compile();
			}

			private static LogEventDelegate GetLogEventDelegate(Type loggerType, Type logEventType)
			{
				MethodInfo method = loggerType.GetMethod("Log", new Type[2]
				{
					typeof(Type),
					logEventType
				});
				ParameterExpression parameterExpression = Expression.Parameter(typeof(object));
				UnaryExpression instance = Expression.Convert(parameterExpression, loggerType);
				ParameterExpression parameterExpression2 = Expression.Parameter(typeof(Type));
				ParameterExpression parameterExpression3 = Expression.Parameter(typeof(object));
				UnaryExpression arg = Expression.Convert(parameterExpression3, logEventType);
				return Expression.Lambda<LogEventDelegate>(Expression.Call(instance, method, parameterExpression2, arg), new ParameterExpression[3] { parameterExpression, parameterExpression2, parameterExpression3 }).Compile();
			}

			private static LogExceptionDelegate GetLogExceptionDelegate(Type loggerType, string name)
			{
				MethodInfo method = loggerType.GetMethod(name, new Type[2]
				{
					typeof(string),
					typeof(Exception)
				});
				ParameterExpression parameterExpression = Expression.Parameter(typeof(object));
				UnaryExpression instance = Expression.Convert(parameterExpression, loggerType);
				ParameterExpression parameterExpression2 = Expression.Parameter(typeof(string));
				ParameterExpression parameterExpression3 = Expression.Parameter(typeof(Exception));
				return Expression.Lambda<LogExceptionDelegate>(Expression.Call(instance, method, parameterExpression2, parameterExpression3), new ParameterExpression[3] { parameterExpression, parameterExpression2, parameterExpression3 }).Compile();
			}

			public bool Log(LogLevel logLevel, Func<string> messageFunc, Exception exception, params object[] formatParameters)
			{
				if (!Initialized.Value)
				{
					throw new LibLogException("Unable to log due to problem initializing the log provider. See inner exception for details.", s_initializeException);
				}
				if (messageFunc == null)
				{
					return IsLogLevelEnable(logLevel);
				}
				if (s_logEventInfoFact != null)
				{
					if (IsLogLevelEnable(logLevel))
					{
						string text = messageFunc();
						if (!s_structuredLoggingEnabled)
						{
							text = LogMessageFormatter.FormatStructuredMessage(text, formatParameters, out var _);
							formatParameters = null;
						}
						Type typeFromHandle = typeof(NLogLogger);
						Type declaringType = messageFunc.Method.DeclaringType;
						if (declaringType == typeof(LogExtensions) || (declaringType != null && declaringType.DeclaringType == typeof(LogExtensions)))
						{
							typeFromHandle = typeof(LogExtensions);
						}
						else if (declaringType == typeof(LoggerExecutionWrapper) || (declaringType != null && declaringType.DeclaringType == typeof(LoggerExecutionWrapper)))
						{
							typeFromHandle = typeof(LoggerExecutionWrapper);
						}
						object arg = TranslateLevel(logLevel);
						object logEvent = s_logEventInfoFact(s_loggerNameDelegate(_logger), arg, text, formatParameters, exception);
						s_logEventDelegate(_logger, typeFromHandle, logEvent);
						return true;
					}
					return false;
				}
				messageFunc = LogMessageFormatter.SimulateStructuredLogging(messageFunc, formatParameters);
				if (exception != null)
				{
					return LogException(logLevel, messageFunc, exception);
				}
				switch (logLevel)
				{
				case LogLevel.Debug:
					if (s_isDebugEnabledDelegate(_logger))
					{
						s_debugDelegate(_logger, messageFunc());
						return true;
					}
					break;
				case LogLevel.Info:
					if (s_isInfoEnabledDelegate(_logger))
					{
						s_infoDelegate(_logger, messageFunc());
						return true;
					}
					break;
				case LogLevel.Warn:
					if (s_isWarnEnabledDelegate(_logger))
					{
						s_warnDelegate(_logger, messageFunc());
						return true;
					}
					break;
				case LogLevel.Error:
					if (s_isErrorEnabledDelegate(_logger))
					{
						s_errorDelegate(_logger, messageFunc());
						return true;
					}
					break;
				case LogLevel.Fatal:
					if (s_isFatalEnabledDelegate(_logger))
					{
						s_fatalDelegate(_logger, messageFunc());
						return true;
					}
					break;
				default:
					if (s_isTraceEnabledDelegate(_logger))
					{
						s_traceDelegate(_logger, messageFunc());
						return true;
					}
					break;
				}
				return false;
			}

			private bool LogException(LogLevel logLevel, Func<string> messageFunc, Exception exception)
			{
				switch (logLevel)
				{
				case LogLevel.Debug:
					if (s_isDebugEnabledDelegate(_logger))
					{
						s_debugExceptionDelegate(_logger, messageFunc(), exception);
						return true;
					}
					break;
				case LogLevel.Info:
					if (s_isInfoEnabledDelegate(_logger))
					{
						s_infoExceptionDelegate(_logger, messageFunc(), exception);
						return true;
					}
					break;
				case LogLevel.Warn:
					if (s_isWarnEnabledDelegate(_logger))
					{
						s_warnExceptionDelegate(_logger, messageFunc(), exception);
						return true;
					}
					break;
				case LogLevel.Error:
					if (s_isErrorEnabledDelegate(_logger))
					{
						s_errorExceptionDelegate(_logger, messageFunc(), exception);
						return true;
					}
					break;
				case LogLevel.Fatal:
					if (s_isFatalEnabledDelegate(_logger))
					{
						s_fatalExceptionDelegate(_logger, messageFunc(), exception);
						return true;
					}
					break;
				default:
					if (s_isTraceEnabledDelegate(_logger))
					{
						s_traceExceptionDelegate(_logger, messageFunc(), exception);
						return true;
					}
					break;
				}
				return false;
			}

			private bool IsLogLevelEnable(LogLevel logLevel)
			{
				return logLevel switch
				{
					LogLevel.Debug => s_isDebugEnabledDelegate(_logger), 
					LogLevel.Info => s_isInfoEnabledDelegate(_logger), 
					LogLevel.Warn => s_isWarnEnabledDelegate(_logger), 
					LogLevel.Error => s_isErrorEnabledDelegate(_logger), 
					LogLevel.Fatal => s_isFatalEnabledDelegate(_logger), 
					_ => s_isTraceEnabledDelegate(_logger), 
				};
			}

			private object TranslateLevel(LogLevel logLevel)
			{
				return logLevel switch
				{
					LogLevel.Trace => s_levelTrace, 
					LogLevel.Debug => s_levelDebug, 
					LogLevel.Info => s_levelInfo, 
					LogLevel.Warn => s_levelWarn, 
					LogLevel.Error => s_levelError, 
					LogLevel.Fatal => s_levelFatal, 
					_ => throw new ArgumentOutOfRangeException("logLevel", logLevel, null), 
				};
			}

			private static bool IsStructuredLoggingEnabled()
			{
				Type type = LogProviderBase.FindType("NLog.Config.ConfigurationItemFactory", "NLog");
				if (type != null)
				{
					PropertyInfo property = type.GetProperty("ParseMessageTemplates");
					if (property != null)
					{
						PropertyInfo property2 = type.GetProperty("Default");
						if (property2 != null)
						{
							object value = property2.GetValue(null, null);
							if (value != null && property.GetValue(value, null) as bool? != false)
							{
								return true;
							}
						}
					}
				}
				return false;
			}
		}

		private readonly Func<string, object> _getLoggerByNameDelegate;

		public static bool ProviderIsAvailableOverride { get; set; }

		public NLogLogProvider()
		{
			if (!IsLoggerAvailable())
			{
				throw new LibLogException("NLog.LogManager not found");
			}
			_getLoggerByNameDelegate = GetGetLoggerMethodCall();
		}

		static NLogLogProvider()
		{
			ProviderIsAvailableOverride = true;
		}

		public override Logger GetLogger(string name)
		{
			return new NLogLogger(_getLoggerByNameDelegate(name)).Log;
		}

		public static bool IsLoggerAvailable()
		{
			if (ProviderIsAvailableOverride)
			{
				return GetLogManagerType() != null;
			}
			return false;
		}

		protected override OpenNdc GetOpenNdcMethod()
		{
			ParameterExpression parameterExpression = Expression.Parameter(typeof(string), "message");
			Type type = LogProviderBase.FindType("NLog.NestedDiagnosticsLogicalContext", "NLog");
			if (type != null)
			{
				MethodInfo method = type.GetMethod("PushObject", typeof(object));
				if (method != null)
				{
					return Expression.Lambda<OpenNdc>(Expression.Call(null, method, parameterExpression), new ParameterExpression[1] { parameterExpression }).Compile();
				}
			}
			MethodInfo method2 = LogProviderBase.FindType("NLog.NestedDiagnosticsContext", "NLog").GetMethod("Push", typeof(string));
			return Expression.Lambda<OpenNdc>(Expression.Call(null, method2, parameterExpression), new ParameterExpression[1] { parameterExpression }).Compile();
		}

		protected override OpenMdc GetOpenMdcMethod()
		{
			ParameterExpression parameterExpression = Expression.Parameter(typeof(string), "key");
			Type type = LogProviderBase.FindType("NLog.NestedDiagnosticsLogicalContext", "NLog");
			if (type != null && type.GetMethod("PushObject", typeof(object)) != null)
			{
				Type type2 = LogProviderBase.FindType("NLog.MappedDiagnosticsLogicalContext", "NLog");
				if (type2 != null)
				{
					MethodInfo method = type2.GetMethod("SetScoped", typeof(string), typeof(object));
					if (method != null)
					{
						ParameterExpression parameterExpression2 = Expression.Parameter(typeof(object), "value");
						MethodCallExpression body = Expression.Call(null, method, parameterExpression, parameterExpression2);
						Func<string, object, IDisposable> setMethodLambda = Expression.Lambda<Func<string, object, IDisposable>>(body, new ParameterExpression[2] { parameterExpression, parameterExpression2 }).Compile();
						return (string key, object value, bool _) => setMethodLambda(key, value);
					}
				}
			}
			Type type3 = LogProviderBase.FindType("NLog.MappedDiagnosticsContext", "NLog");
			MethodInfo method2 = type3.GetMethod("Set", typeof(string), typeof(string));
			MethodInfo method3 = type3.GetMethod("Remove", typeof(string));
			ParameterExpression parameterExpression3 = Expression.Parameter(typeof(string), "value");
			MethodCallExpression body2 = Expression.Call(null, method2, parameterExpression, parameterExpression3);
			MethodCallExpression body3 = Expression.Call(null, method3, parameterExpression);
			Action<string, string> set = Expression.Lambda<Action<string, string>>(body2, new ParameterExpression[2] { parameterExpression, parameterExpression3 }).Compile();
			Action<string> remove = Expression.Lambda<Action<string>>(body3, new ParameterExpression[1] { parameterExpression }).Compile();
			return delegate(string key, object value, bool _)
			{
				set(key, value.ToString());
				return new DisposableAction(delegate
				{
					remove(key);
				});
			};
		}

		private static Type GetLogManagerType()
		{
			return LogProviderBase.FindType("NLog.LogManager", "NLog");
		}

		private static Func<string, object> GetGetLoggerMethodCall()
		{
			MethodInfo method = GetLogManagerType().GetMethod("GetLogger", typeof(string));
			ParameterExpression parameterExpression = Expression.Parameter(typeof(string), "name");
			return Expression.Lambda<Func<string, object>>(Expression.Call(null, method, parameterExpression), new ParameterExpression[1] { parameterExpression }).Compile();
		}
	}
	internal class SerilogLogProvider : LogProviderBase
	{
		internal class SerilogLogger
		{
			private static object s_debugLevel;

			private static object s_errorLevel;

			private static object s_fatalLevel;

			private static object s_informationLevel;

			private static object s_verboseLevel;

			private static object s_warningLevel;

			private static Func<object, object, bool> s_isEnabled;

			private static Action<object, object, string, object[]> s_write;

			private static Action<object, object, Exception, string, object[]> s_writeException;

			private static readonly Lazy<bool> Initialized = new Lazy<bool>(Initialize);

			private static Exception s_initializeException;

			private readonly object _logger;

			internal SerilogLogger(object logger)
			{
				_logger = logger;
			}

			private static bool Initialize()
			{
				try
				{
					Type type = LogProviderBase.FindType("Serilog.Events.LogEventLevel", "Serilog");
					if (type == null)
					{
						throw new LibLogException("Type Serilog.Events.LogEventLevel was not found.");
					}
					s_debugLevel = Enum.Parse(type, "Debug", ignoreCase: false);
					s_errorLevel = Enum.Parse(type, "Error", ignoreCase: false);
					s_fatalLevel = Enum.Parse(type, "Fatal", ignoreCase: false);
					s_informationLevel = Enum.Parse(type, "Information", ignoreCase: false);
					s_verboseLevel = Enum.Parse(type, "Verbose", ignoreCase: false);
					s_warningLevel = Enum.Parse(type, "Warning", ignoreCase: false);
					Type type2 = LogProviderBase.FindType("Serilog.ILogger", "Serilog");
					if (type2 == null)
					{
						throw new LibLogException("Type Serilog.ILogger was not found.");
					}
					MethodInfo method = type2.GetMethod("IsEnabled", type);
					ParameterExpression parameterExpression = Expression.Parameter(typeof(object));
					UnaryExpression instance = Expression.Convert(parameterExpression, type2);
					ParameterExpression parameterExpression2 = Expression.Parameter(typeof(object));
					UnaryExpression unaryExpression = Expression.Convert(parameterExpression2, type);
					s_isEnabled = Expression.Lambda<Func<object, object, bool>>(Expression.Call(instance, method, unaryExpression), new ParameterExpression[2] { parameterExpression, parameterExpression2 }).Compile();
					MethodInfo method2 = type2.GetMethod("Write", type, typeof(string), typeof(object[]));
					ParameterExpression parameterExpression3 = Expression.Parameter(typeof(string));
					ParameterExpression parameterExpression4 = Expression.Parameter(typeof(object[]));
					s_write = Expression.Lambda<Action<object, object, string, object[]>>(Expression.Call(instance, method2, unaryExpression, parameterExpression3, parameterExpression4), new ParameterExpression[4] { parameterExpression, parameterExpression2, parameterExpression3, parameterExpression4 }).Compile();
					MethodInfo method3 = type2.GetMethod("Write", type, typeof(Exception), typeof(string), typeof(object[]));
					ParameterExpression parameterExpression5 = Expression.Parameter(typeof(Exception));
					s_writeException = Expression.Lambda<Action<object, object, Exception, string, object[]>>(Expression.Call(instance, method3, unaryExpression, parameterExpression5, parameterExpression3, parameterExpression4), new ParameterExpression[5] { parameterExpression, parameterExpression2, parameterExpression5, parameterExpression3, parameterExpression4 }).Compile();
				}
				catch (Exception ex)
				{
					s_initializeException = ex;
					return false;
				}
				return true;
			}

			public bool Log(LogLevel logLevel, Func<string> messageFunc, Exception exception, params object[] formatParameters)
			{
				if (!Initialized.Value)
				{
					throw new LibLogException("Unable to log due to problem initializing the log provider. See inner exception for details.", s_initializeException);
				}
				object obj = TranslateLevel(logLevel);
				if (messageFunc == null)
				{
					return s_isEnabled(_logger, obj);
				}
				if (!s_isEnabled(_logger, obj))
				{
					return false;
				}
				if (exception != null)
				{
					LogException(obj, messageFunc, exception, formatParameters);
				}
				else
				{
					LogMessage(obj, messageFunc, formatParameters);
				}
				return true;
			}

			private void LogMessage(object translatedLevel, Func<string> messageFunc, object[] formatParameters)
			{
				s_write(_logger, translatedLevel, messageFunc(), formatParameters);
			}

			private void LogException(object logLevel, Func<string> messageFunc, Exception exception, object[] formatParams)
			{
				s_writeException(_logger, logLevel, exception, messageFunc(), formatParams);
			}

			private static object TranslateLevel(LogLevel logLevel)
			{
				return logLevel switch
				{
					LogLevel.Fatal => s_fatalLevel, 
					LogLevel.Error => s_errorLevel, 
					LogLevel.Warn => s_warningLevel, 
					LogLevel.Info => s_informationLevel, 
					LogLevel.Trace => s_verboseLevel, 
					_ => s_debugLevel, 
				};
			}
		}

		private readonly Func<string, object> _getLoggerByNameDelegate;

		private static Func<string, object, bool, IDisposable> s_pushProperty;

		public static bool ProviderIsAvailableOverride { get; set; } = true;


		public SerilogLogProvider()
		{
			if (!IsLoggerAvailable())
			{
				throw new LibLogException("Serilog.Log not found");
			}
			_getLoggerByNameDelegate = GetForContextMethodCall();
			s_pushProperty = GetPushProperty();
		}

		public override Logger GetLogger(string name)
		{
			return new SerilogLogger(_getLoggerByNameDelegate(name)).Log;
		}

		internal static bool IsLoggerAvailable()
		{
			if (ProviderIsAvailableOverride)
			{
				return GetLogManagerType() != null;
			}
			return false;
		}

		protected override OpenNdc GetOpenNdcMethod()
		{
			return (string message) => s_pushProperty("NDC", message, arg3: false);
		}

		protected override OpenMdc GetOpenMdcMethod()
		{
			return (string key, object value, bool destructure) => s_pushProperty(key, value, destructure);
		}

		private static Func<string, object, bool, IDisposable> GetPushProperty()
		{
			MethodInfo method = LogProviderBase.FindType("Serilog.Context.LogContext", new string[2] { "Serilog", "Serilog.FullNetFx" }).GetMethod("PushProperty", typeof(string), typeof(object), typeof(bool));
			ParameterExpression parameterExpression = Expression.Parameter(typeof(string), "name");
			ParameterExpression parameterExpression2 = Expression.Parameter(typeof(object), "value");
			ParameterExpression parameterExpression3 = Expression.Parameter(typeof(bool), "destructureObjects");
			MethodCallExpression body = Expression.Call(null, method, parameterExpression, parameterExpression2, parameterExpression3);
			Func<string, object, bool, IDisposable> pushProperty = Expression.Lambda<Func<string, object, bool, IDisposable>>(body, new ParameterExpression[3] { parameterExpression, parameterExpression2, parameterExpression3 }).Compile();
			return (string key, object value, bool destructure) => pushProperty(key, value, destructure);
		}

		private static Type GetLogManagerType()
		{
			return LogProviderBase.FindType("Serilog.Log", "Serilog");
		}

		private static Func<string, object> GetForContextMethodCall()
		{
			MethodInfo method = GetLogManagerType().GetMethod("ForContext", typeof(string), typeof(object), typeof(bool));
			ParameterExpression parameterExpression = Expression.Parameter(typeof(string), "propertyName");
			ParameterExpression parameterExpression2 = Expression.Parameter(typeof(object), "value");
			ParameterExpression parameterExpression3 = Expression.Parameter(typeof(bool), "destructureObjects");
			MethodCallExpression body = Expression.Call(null, method, new Expression[3] { parameterExpression, parameterExpression2, parameterExpression3 });
			Func<string, object, bool, object> func = Expression.Lambda<Func<string, object, bool, object>>(body, new ParameterExpression[3] { parameterExpression, parameterExpression2, parameterExpression3 }).Compile();
			return (string name) => func("SourceContext", name, arg3: false);
		}
	}
	internal static class TraceEventTypeValues
	{
		internal static readonly Type Type;

		internal static readonly int Verbose;

		internal static readonly int Information;

		internal static readonly int Warning;

		internal static readonly int Error;

		internal static readonly int Critical;

		static TraceEventTypeValues()
		{
			Type = typeof(Uri).Assembly.GetType("System.Diagnostics.TraceEventType");
			if (!(Type == null))
			{
				Verbose = (int)Enum.Parse(Type, "Verbose", ignoreCase: false);
				Information = (int)Enum.Parse(Type, "Information", ignoreCase: false);
				Warning = (int)Enum.Parse(Type, "Warning", ignoreCase: false);
				Error = (int)Enum.Parse(Type, "Error", ignoreCase: false);
				Critical = (int)Enum.Parse(Type, "Critical", ignoreCase: false);
			}
		}
	}
	internal static class TypeExtensions
	{
		internal static ConstructorInfo GetConstructorPortable(this Type type, params Type[] types)
		{
			return type.GetConstructor(types);
		}

		internal static MethodInfo GetMethod(this Type type, string name, params Type[] types)
		{
			return type.GetMethod(name, types);
		}
	}
}
namespace Websocket.Client.Validations
{
	internal static class Validations
	{
		public static void ValidateInput(string value, string name)
		{
			if (string.IsNullOrEmpty(value))
			{
				throw new WebsocketBadInputException("Input string parameter '" + name + "' is null or empty. Please correct it.");
			}
		}

		public static void ValidateInput<T>(T value, string name)
		{
			if (object.Equals(value, default(T)))
			{
				throw new WebsocketBadInputException("Input parameter '" + name + "' is null. Please correct it.");
			}
		}

		public static void ValidateInputCollection<T>(IEnumerable<T> collection, string name)
		{
			ValidateInput(collection, name);
			if (!collection.Any())
			{
				throw new WebsocketBadInputException("Input collection '" + name + "' is empty. Please correct it.");
			}
		}

		public static void ValidateInput(int value, string name, int minValue = int.MinValue, int maxValue = int.MaxValue)
		{
			if (value < minValue)
			{
				throw new WebsocketBadInputException($"Input parameter '{name}' is lower than {minValue}. Please correct it.");
			}
			if (value > maxValue)
			{
				throw new WebsocketBadInputException($"Input parameter '{name}' is higher than {maxValue}. Please correct it.");
			}
		}

		public static void ValidateInput(long value, string name, long minValue = long.MinValue, long maxValue = long.MaxValue)
		{
			if (value < minValue)
			{
				throw new WebsocketBadInputException($"Input parameter '{name}' is lower than {minValue}. Please correct it.");
			}
			if (value > maxValue)
			{
				throw new WebsocketBadInputException($"Input parameter '{name}' is higher than {maxValue}. Please correct it.");
			}
		}

		public static void ValidateInput(double value, string name, double minValue = double.MinValue, double maxValue = double.MaxValue)
		{
			if (value < minValue)
			{
				throw new WebsocketBadInputException($"Input parameter '{name}' is lower than {minValue}. Please correct it.");
			}
			if (value > maxValue)
			{
				throw new WebsocketBadInputException($"Input parameter '{name}' is higher than {maxValue}. Please correct it.");
			}
		}
	}
}
namespace Websocket.Client.Threading
{
	public class WebsocketAsyncLock
	{
		private class Releaser : IDisposable
		{
			private readonly SemaphoreSlim _semaphore;

			public Releaser(SemaphoreSlim semaphore)
			{
				_semaphore = semaphore;
			}

			public void Dispose()
			{
				_semaphore.Release();
			}
		}

		private readonly Task<IDisposable> _releaserTask;

		private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1);

		private readonly IDisposable _releaser;

		public WebsocketAsyncLock()
		{
			_releaser = new Releaser(_semaphore);
			_releaserTask = Task.FromResult(_releaser);
		}

		public IDisposable Lock()
		{
			_semaphore.Wait();
			return _releaser;
		}

		public Task<IDisposable> LockAsync()
		{
			Task task = _semaphore.WaitAsync();
			if (!task.IsCompleted)
			{
				return task.ContinueWith((Task _, object? releaser) => (IDisposable)releaser, _releaser, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
			}
			return _releaserTask;
		}
	}
}
namespace Websocket.Client.Models
{
	public class ReconnectionInfo
	{
		public ReconnectionType Type { get; }

		public ReconnectionInfo(ReconnectionType type)
		{
			Type = type;
		}

		public static ReconnectionInfo Create(ReconnectionType type)
		{
			return new ReconnectionInfo(type);
		}
	}
}
namespace Websocket.Client.Exceptions
{
	public class WebsocketBadInputException : WebsocketException
	{
		public WebsocketBadInputException()
		{
		}

		public WebsocketBadInputException(string message)
			: base(message)
		{
		}

		public WebsocketBadInputException(string message, Exception innerException)
			: base(message, innerException)
		{
		}
	}
	public class WebsocketException : Exception
	{
		public WebsocketException()
		{
		}

		public WebsocketException(string message)
			: base(message)
		{
		}

		public WebsocketException(string message, Exception innerException)
			: base(message, innerException)
		{
		}
	}
}