using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Concurrency;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Text;
using System.Threading.Tasks;

namespace Timing
{
    class Examples49_50
    {
        private static IConnectableObservable<char> GetKeySource()
        {
            return Observable.Create(
            (Func<IObserver<char>, IDisposable>) (obs =>
            {
                while (true)
                {
                    ConsoleKeyInfo k = Console.ReadKey(true);
                    obs.OnNext(k.KeyChar);
                    Scheduler.Default.Yield();
                    if (k.Key == ConsoleKey.Escape)
                    {
                        obs.OnCompleted();
                        return Disposable.Empty;
                    }
                }
            })).Publish();
        }

        public static void TimedBuffers()
        {
            IConnectableObservable<char> keySource = GetKeySource();

            IObservable<IList<char>> wordWindows = keySource.Buffer(
                () => keySource.FirstAsync(char.IsWhiteSpace));

            IObservable<string> words = from wordWindow in wordWindows
                                        select new string(wordWindow.ToArray()).Trim();

            // Listing 11-49
            IObservable<int> wordGroupCounts =
                from wordGroup in words.Buffer(TimeSpan.FromSeconds(6))
                select wordGroup.Count * 10;
            wordGroupCounts.Subscribe(c => Console.WriteLine("Liczba słów na minutę: " + c));


            Console.WriteLine("Szybkość wpisywania - naciśnij Esc by skończyć. (Komunikat będzie wyświetlany co 6 sekund)");
            keySource.Connect().Dispose();
        }

        public static void TimedBuffersWithOverlappingWindows()
        {
            IConnectableObservable<char> keySource = GetKeySource();

            IObservable<IList<char>> wordWindows = keySource.Buffer(
                () => keySource.FirstAsync(char.IsWhiteSpace));

            IObservable<string> words = from wordWindow in wordWindows
                                        select new string(wordWindow.ToArray()).Trim();

            // Listing 11-50
            IObservable<int> wordGroupCounts =
                from wordGroup in words.Buffer(TimeSpan.FromSeconds(6),
                                               TimeSpan.FromSeconds(1))
                select wordGroup.Count * 10;

            wordGroupCounts.Subscribe(c => Console.WriteLine("Liczba słów na minutę: " + c));


            Console.WriteLine("Szybkość wpisywania - naciśnij Esc by skończyć. (Zaczeka 6 sekund, a następnie komunikaty będą wyświetlane co sekundę)");
            keySource.Connect().Dispose();
        }
    }
}
