using System;
using System.IO;
using System.Net;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApp1
{
	class Program
	{
		static Task<WebResponse> GetResponseMyAsync(WebRequest request)
		{
			return Task.Factory.FromAsync(
				request.BeginGetResponse,
				request.EndGetResponse,
				null);
		}

		static Task<int> FooBar()
		{
			var tcs = new TaskCompletionSource<int>();
			ThreadPool.QueueUserWorkItem(_ =>
			{
				Thread.Sleep(5000);
				tcs.TrySetResult(6);
			});
			return tcs.Task;
		}

		static async Task Main(string[] args)
		{
			var result = await FooBar();
			Console.WriteLine(result);
			return;

			//for (var i = 0; i < 1; i++)
			//{
			//	//ThreadPool.QueueUserWorkItem(_ =>
			//	//{
			//	//	var x = 0;
			//	//	for (int i = 0; i < 200; i++)
			//	//	{
			//	//		x *= 20;
			//	//	}
			//	//});
			//	//Task.Run(() =>
			//	//{

			//	//});
			//	Console.WriteLine(i);
			//}
			ServicePointManager.DefaultConnectionLimit = int.MaxValue;
			Console.ReadLine();
			var tasks = new Task[1];
			for (var i = 0; i < 1; i++)
			{
				static async Task Do()
				{
					var request = WebRequest.CreateHttp("https://www.tabsoverspaces.com");
					using (var response = await request.GetResponseAsync())
					{
						using (var source = response.GetResponseStream())
						{
							using (var destination = new MemoryStream())
							{
								await ReadStreamAsync(source, destination);
							}
						}
					}
				}
				tasks[i] = Do();
				//request.BeginGetResponse(ar =>
				//{
				//	var response = request.EndGetResponse(ar);
				//	var source = response.GetResponseStream();
				//	var destination = new MemoryStream();
				//	ReadStream(source, destination, () =>
				//	{
				//		destination.Dispose();
				//		source.Dispose();
				//		response.Dispose();
				//	},
				//	ex =>
				//	{
				//		destination.Dispose();
				//		source.Dispose();
				//		response.Dispose();
				//	});
				//}, null);
				//Console.WriteLine(i);
			}
			await Task.WhenAll(tasks);
			Console.WriteLine("Done");
			Console.ReadLine();
		}

		static async Task ReadStreamAsync(Stream source, Stream destination)
		{
			var buffer = new byte[32 * 1024];
			while (true)
			{
				try
				{
					var read = await source.ReadAsync(buffer, 0, buffer.Length);
					if (read == 0)
					{
						break;
					}
					await destination.WriteAsync(buffer, 0, read);
				}
				catch (IOException ex)
				{

				}
			}
		}

		static void ReadStream(Stream source, Stream destination, Action onDone, Action<Exception> onError)
		{
			var buffer = new byte[32 * 1024];
			source.BeginRead(buffer, 0, buffer.Length, ar =>
			{
				int read;
				try
				{
					read = source.EndRead(ar);
				}
				catch (IOException ex)
				{
					onError(ex);
					return;
				}
				if (read == 0)
				{
					onDone();
					return;
				}
				destination.BeginWrite(buffer, 0, read, ar2 =>
				{
					try
					{
						destination.EndWrite(ar2);
					}
					catch (IOException ex)
					{
						onError(ex);
						return;
					}
					ReadStream(source, destination, onDone, onError);
				}, null);
			}, null);
		}

		//async Task Test()
		//{
		//	Console.WriteLine();
		//	await Task.CompletedTask;
		//	Console.WriteLine();
		//	await Task.CompletedTask;
		//	Console.WriteLine();
		//	await Task.CompletedTask;
		//	Console.WriteLine();
		//}
	}
}
