using System;
using System.Threading;
using System.Threading.Tasks;

namespace Websocket.Client.Threading
{
	public class WebsocketAsyncLock
	{
		public WebsocketAsyncLock()
		{
			this._releaser = new WebsocketAsyncLock.Releaser(this._semaphore);
			this._releaserTask = Task.FromResult<IDisposable>(this._releaser);
		}

		public IDisposable Lock()
		{
			this._semaphore.Wait();
			return this._releaser;
		}

		public Task<IDisposable> LockAsync()
		{
			Task task = this._semaphore.WaitAsync();
			if (!task.IsCompleted)
			{
				return task.ContinueWith<IDisposable>((Task _, object releaser) => (IDisposable)releaser, this._releaser, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
			}
			return this._releaserTask;
		}

		private readonly Task<IDisposable> _releaserTask;

		private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1);

		private readonly IDisposable _releaser;

		private class Releaser : IDisposable
		{
			public Releaser(SemaphoreSlim semaphore)
			{
				this._semaphore = semaphore;
			}

			public void Dispose()
			{
				this._semaphore.Release();
			}

			private readonly object _semaphore;
		}
	}
}
