using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace UsingAsync
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        // Listing 18-1
        private async void FetchAndShowHeaders(string url)
        {
            using (var w = new HttpClient())
            {
                var req = new HttpRequestMessage(HttpMethod.Head, url);
                HttpResponseMessage response =
                    await w.SendAsync(req, HttpCompletionOption.ResponseHeadersRead);

                var headerStrings =
                    from header in response.Headers
                    select header.Key + ": " + string.Join(",", header.Value);

                string headerList = string.Join(Environment.NewLine, headerStrings);
                headerListTextBox.Text = headerList;
            }
        }

        // Listing 13-8
        private void fetchHeadersButton_Click(object sender, RoutedEventArgs e)
        {
            FetchAndShowHeaders("http://helion.pl/");
            Debug.WriteLine("Wywołanie metody zostało zakończone.");
        }

        private void Button_Click_2(object sender, RoutedEventArgs e)
        {
            string url = "http://helion.pl/";
            using (var w = new HttpClient())
            {
                var req = new HttpRequestMessage(HttpMethod.Head, url);

                // Listing 18-2
                HttpResponseMessage response =
                    w.SendAsync(req, HttpCompletionOption.ResponseHeadersRead).Result;

                var headerStrings =
                    from header in response.Headers
                    select header.Key + ": " + string.Join(",", header.Value);

                string headerList = string.Join(Environment.NewLine, headerStrings);
                headerListTextBox.Text = headerList;
            }
        }

        // Listing 18-4
        private void OldSchoolFetchHeaders(string url)
        {
            var w = new HttpClient();
            var req = new HttpRequestMessage(HttpMethod.Head, url);

            var uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
            w.SendAsync(req, HttpCompletionOption.ResponseHeadersRead)
                .ContinueWith(sendTask =>
                {
                    try
                    {
                        HttpResponseMessage response = sendTask.Result;
                        var headerStrings =
                            from header in response.Headers
                            select header.Key + ": " + string.Join(",", header.Value);

                        string headerList =
                            string.Join(Environment.NewLine, headerStrings);
                        headerListTextBox.Text = headerList;
                    }
                    finally
                    {
                        w.Dispose();
                    }
                },
                uiScheduler);
        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            OldSchoolFetchHeaders("http://helion.pl/");
        }

        // Listing 18-5
        private async void OnFetchButtonClick(object sender, RoutedEventArgs e)
        {
            using (var w = new HttpClient())
            using (Stream f = File.Create(fileTextBox.Text))
            {
                Task<Stream> getStreamTask = w.GetStreamAsync(urlTextBox.Text);
                Stream getStream = await getStreamTask.ConfigureAwait(false);

                Task copyTask = getStream.CopyToAsync(f);
                await copyTask.ConfigureAwait(false);
            }
        }

        private void Button_Click_3(object sender, RoutedEventArgs e)
        {
            FetchAndShowBody("http://helion.pl/");

        }

        // Listing 18-6
        // lub listing 18-8 jeśli pierwszy wiersz zostanie zastąpiony przez:
        // private async Task FetchAndShowBody(string url)
        private async void FetchAndShowBody(string url)
        {
            using (var w = new HttpClient())
            {
                Stream body = await w.GetStreamAsync(url);
                using (var bodyTextReader = new StreamReader(body))
                {
                    while (!bodyTextReader.EndOfStream)
                    {
                        string line = await bodyTextReader.ReadLineAsync();
                        headerListTextBox.AppendText(line);
                        headerListTextBox.AppendText(Environment.NewLine);
                        await Task.Delay(TimeSpan.FromMilliseconds(10));
                    }
                }
            }
        }

        // Listing 18-7
        private void IncompleteOldSchoolFetchAndShowBody(string url)
        {
            var w = new HttpClient();
            var uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
            w.GetStreamAsync(url).ContinueWith(getStreamTask =>
            {
                Stream body = getStreamTask.Result;
                var bodyTextReader = new StreamReader(body);

                Action startNextIteration = null;
                startNextIteration = () =>
                {
                    if (!bodyTextReader.EndOfStream)
                    {
                        bodyTextReader.ReadLineAsync()
                            .ContinueWith(readLineTask =>
                            {
                                string line = readLineTask.Result;

                                headerListTextBox.AppendText(line);
                                headerListTextBox.AppendText(Environment.NewLine);

                                Task.Delay(TimeSpan.FromMilliseconds(10))
                                    .ContinueWith(delayTask =>
                                        startNextIteration(), uiScheduler);
                            },
                        uiScheduler);
                    }
                };
                startNextIteration();
            },
                uiScheduler);
        }

    }
}
