using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Net;
using System.ServiceProcess;
using System.Threading;
using Tesla.Net;

namespace TeslaConsole;

public class PodInfo : Component
{
	private delegate void ConnectWorkerEventHandler(AsyncOperation asyncOp, SendOrPostCallback completionMethodDelegate);

	private delegate void LaunchAppWorkerEventHandler(Guid appId, AsyncOperation asyncOp, SendOrPostCallback completionMethodDelegate);

	private delegate void KillAppWorkerEventHandler(Guid appId, AsyncOperation asyncOp, SendOrPostCallback completionMethodDelegate);

	private delegate void ShutdownWorkerEventHandler(bool restart, AsyncOperation asyncOp, SendOrPostCallback completionMethodDelegate);

	private delegate void InstallProductWorkerEventHandler(string uncPath, SendOrPostCallback progressCallback, AsyncOperation asyncOp, SendOrPostCallback completionMethodDelegate);

	private delegate void UninstallProductWorkerEventHandler(AsyncOperation asyncOp, SendOrPostCallback completionMethodDelegate);

	private delegate void ServiceWorkerEventHandler(string machineName, AsyncOperation asyncOp, SendOrPostCallback completionMethodDelegate);

	private const int ManagePort = 53290;

	private static Dictionary<Guid, PodInfo> mPods = new Dictionary<Guid, PodInfo>();

	private AsyncDelegates<ConnectWorkerEventHandler> connectDelegates;

	private SendOrPostCallback onLaunchAppCompletedDelegate;

	private SendOrPostCallback launchAppCompletionMethodDelegate;

	private SendOrPostCallback onKillAppCompletedDelegate;

	private SendOrPostCallback killAppCompletionMethodDelegate;

	private AsyncDelegates<InstallProductWorkerEventHandler> installProductDelegates;

	private AsyncDelegates<UninstallProductWorkerEventHandler> uninstallProductDelegates;

	private AsyncDelegates<ServiceWorkerEventHandler> serviceGetDelegates;

	private AsyncDelegates<ServiceWorkerEventHandler> serviceStartDelegates;

	private AsyncDelegates<ServiceWorkerEventHandler> serviceStopDelegates;

	private Pod mPod;

	private IPodManagerConnection mConnection = new PodManagerConnection();

	private object mConnectSyncRoot = new object();

	private AsyncOperation mConnectAsyncOp;

	private Exception mLastConnectionException;

	private Cached<LaunchData[]> mAllApps = new Cached<LaunchData[]>(TimeSpan.FromMinutes(30.0));

	private Cached<List<LaunchedAppData>> mRunningApps = new Cached<List<LaunchedAppData>>(TimeSpan.FromSeconds(60.0));

	private float mVolume = float.NaN;

	private readonly List<Action<PodInfo>> rConnectActions = new List<Action<PodInfo>>();

	private IContainer components;

	public Pod Pod => mPod;

	public bool IsConnecting => mConnectAsyncOp != null;

	public bool IsConnected
	{
		get
		{
			if (!IsConnecting && mConnection != null)
			{
				return mConnection.IsOpen;
			}
			return false;
		}
	}

	public Exception LastConnectionException => mLastConnectionException;

	public LaunchData[] AllApplications
	{
		get
		{
			if (mAllApps.IsExpired && mConnection.IsOpen)
			{
				try
				{
					mAllApps.Item = mConnection.GetInstalledApps();
				}
				catch
				{
					mConnection.Close();
					mAllApps.Expire();
					return new LaunchData[0];
				}
			}
			return mAllApps.Item;
		}
	}

	public LaunchedAppData[] RunningApplications
	{
		get
		{
			if (!mConnection.IsOpen)
			{
				return new LaunchedAppData[0];
			}
			if (mRunningApps.IsExpired)
			{
				try
				{
					lock (mRunningApps.SyncRoot)
					{
						mRunningApps.Item = new List<LaunchedAppData>(mConnection.GetLaunchedApps());
					}
				}
				catch
				{
					mConnection.Close();
					lock (mRunningApps.SyncRoot)
					{
						mRunningApps.Expire();
					}
					return new LaunchedAppData[0];
				}
			}
			if (mRunningApps.Item == null)
			{
				return null;
			}
			return mRunningApps.Item.ToArray();
		}
	}

	public float Volume
	{
		get
		{
			if (float.IsNaN(mVolume) && mConnection.IsOpen)
			{
				try
				{
					mVolume = mConnection.VolumeLevel;
				}
				catch
				{
					mConnection.Close();
					mVolume = float.NaN;
				}
			}
			return mVolume;
		}
		set
		{
			if (mConnection.IsOpen)
			{
				mVolume = value;
				try
				{
					mConnection.VolumeLevel = value;
				}
				catch
				{
					mConnection.Close();
					mVolume = float.NaN;
				}
			}
		}
	}

	public bool IsServiceRunning
	{
		get
		{
			try
			{
				ServiceController serviceController = new ServiceController("TeslaLauncherService", mPod.IPAddress.ToString());
				return serviceController.Status == ServiceControllerStatus.Running;
			}
			catch
			{
				return false;
			}
		}
	}

	public event EventHandler<AsyncCompletedEventArgs> ConnectCompleted;

	public event EventHandler<ApplicationCompletedEventArgs> LaunchApplicationCompleted;

	public event EventHandler<ApplicationCompletedEventArgs> KillApplicationCompleted;

	public event EventHandler<InstallProductProgressEventArgs> InstallProductProgress;

	public event EventHandler<InstallProductCompletedEventArgs> InstallProductCompleted;

	public event EventHandler<AsyncCompletedEventArgs> UninstallProductCompleted;

	public event EventHandler<ServiceStatusEventArgs> ServiceStatusGetCompleted;

	public event EventHandler<AsyncCompletedEventArgs> ServiceStartCompleted;

	public event EventHandler<AsyncCompletedEventArgs> ServiceStopCompleted;

	public PodInfo()
	{
		InitializeComponent();
		InitializeDelegates();
	}

	public PodInfo(IContainer container)
	{
		container.Add(this);
		InitializeComponent();
		InitializeDelegates();
	}

	public PodInfo(Pod pod)
		: this(pod, register: false)
	{
	}

	public PodInfo(Pod pod, bool register)
		: this()
	{
		mPod = pod;
		if (register)
		{
			RegisterPod(this);
		}
	}

	protected virtual void InitializeDelegates()
	{
		connectDelegates = new AsyncDelegates<ConnectWorkerEventHandler>(ConnectCompletedInternal, ConnectCompletionMethod);
		onLaunchAppCompletedDelegate = LaunchAppCompleted;
		launchAppCompletionMethodDelegate = LaunchAppCompletionMethod;
		onKillAppCompletedDelegate = KillAppCompleted;
		killAppCompletionMethodDelegate = KillAppCompletionMethod;
		installProductDelegates = new AsyncDelegates<InstallProductWorkerEventHandler>(InstallProductReportProgress, InstallProductInternalCompleted, InstallProductCompletionMethod);
		uninstallProductDelegates = new AsyncDelegates<UninstallProductWorkerEventHandler>(UninstallProductInternalCompleted, UninstallProductCompletionMethod);
		serviceGetDelegates = new AsyncDelegates<ServiceWorkerEventHandler>(ServiceStatusGetCompletedInternal, ServiceStatusGetCompletionMethod);
		serviceStartDelegates = new AsyncDelegates<ServiceWorkerEventHandler>(ServiceStartCompletedInternal, ServiceStartCompletionMethod);
		serviceStopDelegates = new AsyncDelegates<ServiceWorkerEventHandler>(ServiceStopCompletedInternal, ServiceStopCompletionMethod);
	}

	public static void RegisterPod(PodInfo pod)
	{
		mPods[pod.Pod.ID] = pod;
	}

	public static PodInfo GetPod(Guid id)
	{
		PodInfo value = null;
		if (mPods.TryGetValue(id, out value))
		{
			return value;
		}
		return null;
	}

	public bool EnqueueConnectAction(Action<PodInfo> action)
	{
		if (IsConnected)
		{
			action(this);
			return true;
		}
		rConnectActions.Add(action);
		return false;
	}

	public void Disconnect()
	{
		if (mConnectAsyncOp != null)
		{
			CancelConnectAsync();
		}
		else if (IsConnected)
		{
			mConnection.Close();
		}
		mLastConnectionException = null;
		mAllApps.Expire();
		mRunningApps.Expire();
		mVolume = float.NaN;
	}

	public void Refresh()
	{
		if (!IsConnected)
		{
			throw new InvalidOperationException("Cannot refresh pod info while disconnected.");
		}
		try
		{
			FullUpdateData fullUpdateData = mConnection.FullUpdate();
			mAllApps.Item = fullUpdateData.InstalledApps;
			lock (mRunningApps.SyncRoot)
			{
				mRunningApps.Item = new List<LaunchedAppData>(fullUpdateData.LaunchedApps);
			}
			mVolume = fullUpdateData.VolumeLevel;
		}
		catch
		{
			mConnection.Close();
			mAllApps.Expire();
			lock (mRunningApps.SyncRoot)
			{
				mRunningApps.Expire();
			}
			mVolume = float.NaN;
		}
	}

	public bool IsAppRunning(Guid appId)
	{
		LaunchedAppData[] runningApplications = RunningApplications;
		return Array.Exists(runningApplications, (LaunchedAppData app) => app.LaunchKey == appId);
	}

	public void AddApp(LaunchData appData)
	{
		if (!IsConnected)
		{
			throw new InvalidOperationException("Application cannot be added while disconnected.");
		}
		try
		{
			mConnection.InstallApp(appData);
		}
		catch (Exception ex)
		{
			Program.LogException(ex, "Add Application Failed.");
			mConnection.Close();
		}
	}

	public void Shutdown(bool restart)
	{
		try
		{
			mConnection.Shutdown(restart);
		}
		catch (Exception ex)
		{
			Program.LogExceptionAndShowDialog(ex, "Remote Shutdown Failed.", "Remote Shutdown Failed.");
		}
	}

	public void ClearStore()
	{
		mConnection.ClearStore();
	}

	private void ConnectCompletedInternal(object operationState)
	{
		AsyncCompletedEventArgs e = operationState as AsyncCompletedEventArgs;
		OnConnectCompleted(e);
	}

	protected void OnConnectCompleted(AsyncCompletedEventArgs e)
	{
		if (IsConnected)
		{
			foreach (Action<PodInfo> rConnectAction in rConnectActions)
			{
				rConnectAction(this);
			}
			rConnectActions.Clear();
		}
		if (this.ConnectCompleted != null)
		{
			this.ConnectCompleted(this, e);
		}
	}

	private void ConnectCompletionMethod(object completionState)
	{
		AsyncControlState asyncControlState = completionState as AsyncControlState;
		AsyncCompletedEventArgs asyncCompletedEventArgs = new AsyncCompletedEventArgs(asyncControlState.ex, cancelled: false, asyncControlState.asyncOp.UserSuppliedState);
		mLastConnectionException = asyncCompletedEventArgs.Error;
		lock (mConnectSyncRoot)
		{
			if (mConnectAsyncOp != null)
			{
				mConnectAsyncOp.PostOperationCompleted(connectDelegates.OnCompleted, asyncCompletedEventArgs);
				mConnectAsyncOp = null;
			}
		}
	}

	private void ConnectWorker(AsyncOperation asyncOp, SendOrPostCallback completionMethodDelegate)
	{
		Exception ex = null;
		mAllApps.Expire();
		mRunningApps.Expire();
		mVolume = float.NaN;
		try
		{
			if (!mConnection.IsOpen)
			{
				if (mPod.IPAddress == IPAddress.None)
				{
					throw new ArgumentException("Pod IP address cannot be empty.", "IPAddress");
				}
				if (mPod.Key == null || mPod.Key.Length == 0)
				{
					throw new ArgumentException("Pod encryption key cannot be empty.", "Key");
				}
				mConnection.Open(new IPEndPoint(mPod.IPAddress, 53290), mPod.Key);
			}
		}
		catch (Exception ex2)
		{
			ex = ex2;
		}
		AsyncControlState state = new AsyncControlState(ex, asyncOp);
		completionMethodDelegate(state);
	}

	public void ConnectAsync(object userState)
	{
		AsyncOperation asyncOp = AsyncOperationManager.CreateOperation(userState);
		lock (mConnectSyncRoot)
		{
			if (mConnectAsyncOp != null)
			{
				throw new InvalidOperationException("Already connecting. Cannot connect again.");
			}
			mConnectAsyncOp = asyncOp;
		}
		ThreadPool.QueueUserWorkItem(delegate
		{
			ConnectWorker(asyncOp, connectDelegates.CompletionMethod);
		});
	}

	public void CancelConnectAsync()
	{
		lock (mConnectSyncRoot)
		{
			if (mConnectAsyncOp != null)
			{
				AsyncCompletedEventArgs arg = new AsyncCompletedEventArgs(null, cancelled: true, mConnectAsyncOp.UserSuppliedState);
				mConnectAsyncOp.PostOperationCompleted(connectDelegates.OnCompleted, arg);
				mConnectAsyncOp = null;
			}
		}
	}

	private void LaunchAppCompleted(object operationState)
	{
		ApplicationCompletedEventArgs e = operationState as ApplicationCompletedEventArgs;
		OnLaunchApplicationCompleted(e);
	}

	protected void OnLaunchApplicationCompleted(ApplicationCompletedEventArgs e)
	{
		if (this.LaunchApplicationCompleted != null)
		{
			this.LaunchApplicationCompleted(this, e);
		}
	}

	private void LaunchAppCompletionMethod(object completionState)
	{
		AsyncControlState<Guid> asyncControlState = completionState as AsyncControlState<Guid>;
		ApplicationCompletedEventArgs arg = new ApplicationCompletedEventArgs(asyncControlState.state, asyncControlState.ex, canceled: false, asyncControlState.asyncOp.UserSuppliedState);
		asyncControlState.asyncOp.PostOperationCompleted(onLaunchAppCompletedDelegate, arg);
	}

	private void LaunchAppWorker(Guid appId, AsyncOperation asyncOp, SendOrPostCallback completionMethodDelegate)
	{
		Exception ex = null;
		try
		{
			int processId = mConnection.LaunchApp(appId);
			lock (mRunningApps.SyncRoot)
			{
				if (mRunningApps.Item == null)
				{
					mRunningApps.Item = new List<LaunchedAppData>();
				}
				mRunningApps.Item.Add(new LaunchedAppData
				{
					ProcessId = processId,
					LaunchKey = appId
				});
			}
		}
		catch (Exception ex2)
		{
			ex = ex2;
		}
		completionMethodDelegate(new AsyncControlState<Guid>(appId, ex, asyncOp));
	}

	public void LaunchApplicationAsync(Guid appId, object userState)
	{
		if (!IsConnected)
		{
			throw new InvalidOperationException("Cannot launch application while disconnected.");
		}
		AsyncOperation asyncOp = AsyncOperationManager.CreateOperation(userState);
		ThreadPool.QueueUserWorkItem(delegate
		{
			LaunchAppWorker(appId, asyncOp, launchAppCompletionMethodDelegate);
		});
	}

	private void KillAppCompleted(object operationState)
	{
		ApplicationCompletedEventArgs e = operationState as ApplicationCompletedEventArgs;
		OnKillApplicationCompleted(e);
	}

	protected void OnKillApplicationCompleted(ApplicationCompletedEventArgs e)
	{
		if (this.KillApplicationCompleted != null)
		{
			this.KillApplicationCompleted(this, e);
		}
	}

	private void KillAppCompletionMethod(object completionState)
	{
		AsyncControlState<Guid> asyncControlState = completionState as AsyncControlState<Guid>;
		ApplicationCompletedEventArgs arg = new ApplicationCompletedEventArgs(asyncControlState.state, asyncControlState.ex, canceled: false, asyncControlState.asyncOp.UserSuppliedState);
		asyncControlState.asyncOp.PostOperationCompleted(onKillAppCompletedDelegate, arg);
	}

	private void KillAppWorker(Guid appId, AsyncOperation asyncOp, SendOrPostCallback completionMethodDelegate)
	{
		Exception ex = null;
		try
		{
			mConnection.KillAllOfType(appId);
			lock (mRunningApps.SyncRoot)
			{
				if (mRunningApps.Item != null)
				{
					for (int num = mRunningApps.Item.Count - 1; num >= 0; num--)
					{
						if (mRunningApps.Item[num].LaunchKey == appId)
						{
							mRunningApps.Item.RemoveAt(num);
						}
					}
				}
			}
		}
		catch (Exception ex2)
		{
			ex = ex2;
		}
		AsyncControlState<Guid> state = new AsyncControlState<Guid>(appId, ex, asyncOp);
		completionMethodDelegate(state);
	}

	public void KillApplicationAsync(Guid appId, object userState)
	{
		if (!IsConnected)
		{
			throw new InvalidOperationException("Cannot kill application while disconnected.");
		}
		AsyncOperation asyncOp = AsyncOperationManager.CreateOperation(userState);
		ThreadPool.QueueUserWorkItem(delegate
		{
			KillAppWorker(appId, asyncOp, killAppCompletionMethodDelegate);
		});
	}

	private void InstallProductInternalCompleted(object operationState)
	{
		InstallProductCompletedEventArgs e = operationState as InstallProductCompletedEventArgs;
		OnInstallProductCompleted(e);
	}

	private void InstallProductReportProgress(object state)
	{
		InstallProductProgressEventArgs e = state as InstallProductProgressEventArgs;
		OnInstallProductProgress(e);
	}

	protected void OnInstallProductCompleted(InstallProductCompletedEventArgs e)
	{
		if (this.InstallProductCompleted != null)
		{
			this.InstallProductCompleted(this, e);
		}
	}

	protected void OnInstallProductProgress(InstallProductProgressEventArgs e)
	{
		if (this.InstallProductProgress != null)
		{
			this.InstallProductProgress(this, e);
		}
	}

	private void InstallProductCompletionMethod(object completionState)
	{
		AsyncControlState<string> asyncControlState = completionState as AsyncControlState<string>;
		InstallProductCompletedEventArgs arg = new InstallProductCompletedEventArgs(asyncControlState.state, asyncControlState.ex, canceled: false, asyncControlState.asyncOp.UserSuppliedState);
		asyncControlState.asyncOp.PostOperationCompleted(installProductDelegates.OnCompleted, arg);
	}

	private void InstallProductWorker(string filePath, SendOrPostCallback progressCallback, AsyncOperation asyncOp, SendOrPostCallback completionMethodDelegate)
	{
		Exception ex = null;
		try
		{
			for (int i = 0; i < 3; i++)
			{
				if (!mConnection.IsOpen)
				{
					mConnection.Open(new IPEndPoint(mPod.IPAddress, 53290), mPod.Key);
				}
				Guid guid = mConnection.InstallProduct(filePath);
				if (guid == Guid.Empty)
				{
					throw new Exception($"'{filePath}' is an invalid install file.");
				}
				OutOfBandProgress outOfBandProgress;
				do
				{
					Thread.Sleep(250);
					outOfBandProgress = mConnection.GetOutOfBandProgress(guid);
					InstallProductProgressEventArgs arg = new InstallProductProgressEventArgs(outOfBandProgress.Status, outOfBandProgress.PercentComplete, asyncOp.UserSuppliedState);
					asyncOp.Post(installProductDelegates.OnProgressReport, arg);
					if (progressCallback != null)
					{
						asyncOp.Post(progressCallback, arg);
					}
				}
				while (!outOfBandProgress.IsCompleted);
				if (outOfBandProgress.PercentComplete == 99)
				{
					mAllApps.Expire();
					break;
				}
			}
		}
		catch (Exception ex2)
		{
			Program.LogException(ex2, "Installation Failed");
			ex = ex2;
		}
		AsyncControlState<string> state = new AsyncControlState<string>(filePath, ex, asyncOp);
		completionMethodDelegate(state);
	}

	public void InstallProductAsync(string uncPath, object userState)
	{
		InstallProductAsync(uncPath, userState, null);
	}

	public void InstallProductAsync(string uncPath, object userState, Action<InstallProductProgressEventArgs> progressCallback)
	{
		if (!IsConnected)
		{
			throw new InvalidOperationException("Cannot install application while disconnected.");
		}
		AsyncOperation asyncOp = AsyncOperationManager.CreateOperation(userState);
		ThreadPool.QueueUserWorkItem(delegate
		{
			InstallProductWorker(uncPath, delegate(object e)
			{
				progressCallback((InstallProductProgressEventArgs)e);
			}, asyncOp, installProductDelegates.CompletionMethod);
		});
	}

	private void UninstallProductInternalCompleted(object operationState)
	{
		AsyncCompletedEventArgs e = operationState as AsyncCompletedEventArgs;
		OnUninstallProductCompleted(e);
	}

	protected void OnUninstallProductCompleted(AsyncCompletedEventArgs e)
	{
		if (this.UninstallProductCompleted != null)
		{
			this.UninstallProductCompleted(this, e);
		}
	}

	private void UninstallProductCompletionMethod(object completionState)
	{
		AsyncControlState asyncControlState = completionState as AsyncControlState;
		AsyncCompletedEventArgs arg = new AsyncCompletedEventArgs(asyncControlState.ex, cancelled: false, asyncControlState.asyncOp.UserSuppliedState);
		asyncControlState.asyncOp.PostOperationCompleted(uninstallProductDelegates.OnCompleted, arg);
	}

	private void UninstallProductWorker(Guid launchKey, AsyncOperation asyncOp, SendOrPostCallback completionMethodDelegate)
	{
		Exception ex = null;
		try
		{
			if (!mConnection.IsOpen)
			{
				mConnection.Open(new IPEndPoint(mPod.IPAddress, 53290), mPod.Key);
			}
			mConnection.UninstallApp(launchKey);
			mAllApps.Expire();
		}
		catch (Exception ex2)
		{
			Program.LogException(ex2, "Uninstallation Failed");
			ex = ex2;
		}
		AsyncControlState state = new AsyncControlState(ex, asyncOp);
		completionMethodDelegate(state);
	}

	public void UninstallProductAsync(Guid launchKey, object userState)
	{
		if (!IsConnected)
		{
			throw new InvalidOperationException("Cannot uninstall application while disconnected.");
		}
		AsyncOperation asyncOp = AsyncOperationManager.CreateOperation(userState);
		ThreadPool.QueueUserWorkItem(delegate
		{
			UninstallProductWorker(launchKey, asyncOp, uninstallProductDelegates.CompletionMethod);
		});
	}

	private void ServiceStatusGetCompletedInternal(object operationState)
	{
		ServiceStatusEventArgs e = operationState as ServiceStatusEventArgs;
		OnServiceStatusGetCompleted(e);
	}

	protected void OnServiceStatusGetCompleted(ServiceStatusEventArgs e)
	{
		if (this.ServiceStatusGetCompleted != null)
		{
			this.ServiceStatusGetCompleted(this, e);
		}
	}

	private void ServiceStatusGetCompletionMethod(object completionState)
	{
		AsyncControlState<ServiceControllerStatus> asyncControlState = completionState as AsyncControlState<ServiceControllerStatus>;
		ServiceStatusEventArgs arg = new ServiceStatusEventArgs(asyncControlState.state, asyncControlState.ex, canceled: false, asyncControlState.asyncOp.UserSuppliedState);
		asyncControlState.asyncOp.PostOperationCompleted(serviceGetDelegates.OnCompleted, arg);
	}

	private void ServiceStatusWorker(string machineName, AsyncOperation asyncOp, SendOrPostCallback completionMethodDelegate)
	{
		Exception ex = null;
		ServiceControllerStatus state = ServiceControllerStatus.Stopped;
		try
		{
			if (IPAddress.TryParse(machineName, out var address))
			{
				IPHostEntry hostEntry = Dns.GetHostEntry(address);
				machineName = hostEntry.HostName;
			}
			using ServiceController serviceController = new ServiceController("TeslaLauncherService", machineName);
			state = serviceController.Status;
		}
		catch (Exception ex2)
		{
			ex = ex2;
		}
		AsyncControlState<ServiceControllerStatus> state2 = new AsyncControlState<ServiceControllerStatus>(state, ex, asyncOp);
		completionMethodDelegate(state2);
	}

	public void GetServiceStatusAsync(string machineName, object userState)
	{
		AsyncOperation asyncOp = AsyncOperationManager.CreateOperation(userState);
		ThreadPool.QueueUserWorkItem(delegate
		{
			ServiceStatusWorker(machineName, asyncOp, serviceGetDelegates.CompletionMethod);
		});
	}

	private void ServiceStartCompletedInternal(object operationState)
	{
		ServiceStatusEventArgs e = operationState as ServiceStatusEventArgs;
		OnServiceStartCompleted(e);
	}

	protected void OnServiceStartCompleted(ServiceStatusEventArgs e)
	{
		if (this.ServiceStartCompleted != null)
		{
			this.ServiceStartCompleted(this, e);
		}
	}

	private void ServiceStartCompletionMethod(object completionState)
	{
		AsyncControlState<ServiceControllerStatus> asyncControlState = completionState as AsyncControlState<ServiceControllerStatus>;
		ServiceStatusEventArgs arg = new ServiceStatusEventArgs(asyncControlState.state, asyncControlState.ex, canceled: false, asyncControlState.asyncOp.UserSuppliedState);
		asyncControlState.asyncOp.PostOperationCompleted(serviceGetDelegates.OnCompleted, arg);
	}

	private void ServiceStartWorker(string machineName, AsyncOperation asyncOp, SendOrPostCallback completionMethodDelegate)
	{
		Exception ex = null;
		try
		{
			if (IPAddress.TryParse(machineName, out var address))
			{
				IPHostEntry hostEntry = Dns.GetHostEntry(address);
				machineName = hostEntry.HostName;
			}
			using ServiceController serviceController = new ServiceController("TeslaLauncherService", machineName);
			serviceController.Start();
			serviceController.WaitForStatus(ServiceControllerStatus.Running, TimeSpan.FromSeconds(30.0));
		}
		catch (Exception ex2)
		{
			ex = ex2;
		}
		AsyncControlState state = new AsyncControlState(ex, asyncOp);
		completionMethodDelegate(state);
	}

	public void ServiceStartAsync(string machineName, object userState)
	{
		AsyncOperation asyncOp = AsyncOperationManager.CreateOperation(userState);
		ThreadPool.QueueUserWorkItem(delegate
		{
			ServiceStartWorker(machineName, asyncOp, serviceStartDelegates.CompletionMethod);
		});
	}

	private void ServiceStopCompletedInternal(object operationState)
	{
		ServiceStatusEventArgs e = operationState as ServiceStatusEventArgs;
		OnServiceStopCompleted(e);
	}

	protected void OnServiceStopCompleted(ServiceStatusEventArgs e)
	{
		if (this.ServiceStopCompleted != null)
		{
			this.ServiceStopCompleted(this, e);
		}
	}

	private void ServiceStopCompletionMethod(object completionState)
	{
		AsyncControlState<ServiceControllerStatus> asyncControlState = completionState as AsyncControlState<ServiceControllerStatus>;
		ServiceStatusEventArgs arg = new ServiceStatusEventArgs(asyncControlState.state, asyncControlState.ex, canceled: false, asyncControlState.asyncOp.UserSuppliedState);
		asyncControlState.asyncOp.PostOperationCompleted(serviceGetDelegates.OnCompleted, arg);
	}

	private void ServiceStopWorker(string machineName, AsyncOperation asyncOp, SendOrPostCallback completionMethodDelegate)
	{
		Exception ex = null;
		try
		{
			if (IPAddress.TryParse(machineName, out var address))
			{
				IPHostEntry hostEntry = Dns.GetHostEntry(address);
				machineName = hostEntry.HostName;
			}
			using ServiceController serviceController = new ServiceController("TeslaLauncherService", machineName);
			serviceController.Stop();
			serviceController.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(30.0));
		}
		catch (Exception ex2)
		{
			ex = ex2;
		}
		AsyncControlState state = new AsyncControlState(ex, asyncOp);
		completionMethodDelegate(state);
	}

	public void ServiceStopAsync(string machineName, object userState)
	{
		AsyncOperation asyncOp = AsyncOperationManager.CreateOperation(userState);
		ThreadPool.QueueUserWorkItem(delegate
		{
			ServiceStopWorker(machineName, asyncOp, serviceStopDelegates.CompletionMethod);
		});
	}

	protected override void Dispose(bool disposing)
	{
		if (disposing && components != null)
		{
			components.Dispose();
		}
		base.Dispose(disposing);
	}

	private void InitializeComponent()
	{
		components = new Container();
	}
}
