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

namespace Timing
{
    class Examples43_46
    {
        public static void UseInterval()
        {
            // Przykłady są nieco inne niż w tekście książki, aby można było zrezygnować z subskrypcji.

            // Listing 11-43
            IObservable<long> src = Observable.Interval(TimeSpan.FromSeconds(1));
            IDisposable sub1 = src.Subscribe(i => Console.WriteLine("Zdarzenie {0} o godzinie {1:T}", i, DateTime.Now));

            // Listing 11-44
            Thread.Sleep(2500);
            IDisposable sub2 = src.Subscribe(i => Console.WriteLine("Zdarzenie {0} o godzinie {1:T} (2-gi subskrybent)",
                                     i, DateTime.Now));

            Thread.Sleep(4200);
            sub1.Dispose();
            sub2.Dispose();
        }

        public static void CalculateWordRateWithInterval()
        {
            IObservable<char> singularHotSource = Observable.Create(
                (Func<IObserver<char>, IDisposable>) (obs =>
                {
                    while (true)
                    {
                        ConsoleKeyInfo k = Console.ReadKey(true);
                        obs.OnNext(k.KeyChar);
                        if (k.Key == ConsoleKey.Escape)
                        {
                            obs.OnCompleted();
                            return Disposable.Empty;
                        }
                    }
                }));

            IConnectableObservable<char> keySource = singularHotSource.Publish();
            IObservable<IObservable<char>> wordWindows = keySource.Window(
                () => keySource.FirstAsync(char.IsWhiteSpace));

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

            // Listing 11-45
            // (Zmodyfikowany, by można było zrezygnować z subskrypcji)
            IObservable<long> ticks = Observable.Interval(TimeSpan.FromSeconds(6));
            IObservable<int> wordGroupCounts = from tick in ticks
                                               join word in words
                                                 on ticks equals words into wordsInTick
                                               from count in wordsInTick.Count()
                                               select count * 10;

            IDisposable sub = 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();
            sub.Dispose();
        }

        public static void UseTimer()
        {
            // Listing 11-46
            IObservable<long> src = Observable.Timer(TimeSpan.FromSeconds(1));
            src.Subscribe(i => Console.WriteLine("Zdarzenie {0} o godzinie {1:T}", i, DateTime.Now));

            Thread.Sleep(1500);
        }
    }
}
