using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;

namespace AwaitPattern
{
    class Examples12_15
    {
        // Listing 18-12
        static async Task UseCustomAsync()
        {
            string result = await CustomAsync();
            Console.WriteLine(result);
        }

        public static MyAwaitableType CustomAsync()
        {
            return new MyAwaitableType();
        }

        // Listing 18-13
        public class MyAwaitableType
        {
            public MinimalAwaiter GetAwaiter()
            {
                return new MinimalAwaiter();
            }

            public class MinimalAwaiter : INotifyCompletion
            {
                public bool IsCompleted { get { return true; } }

                public string GetResult()
                {
                    return "Oto wynik!";
                }

                public void OnCompleted(Action continuation)
                {
                    throw new NotImplementedException();
                }
            }
        }

        // Listing 18-14
        static void ManualUseCustomAsync()
        {
            var awaiter = CustomAsync().GetAwaiter();
            if (awaiter.IsCompleted)
            {
                TheRest(awaiter);
            }
            else
            {
                awaiter.OnCompleted(() => TheRest(awaiter));
            }
        }

        private static void TheRest(MyAwaitableType.MinimalAwaiter awaiter)
        {
            string result = awaiter.GetResult();
            Console.WriteLine(result);
        }


        // Użytko klasy zagnieżdżonej by uniknąć konfliktu nazw z listingiem 18-14
        class Example15
        {
            // Listing 18-15
            private class ManualUseCustomAsyncState
            {
                private int state;
                private MyAwaitableType.MinimalAwaiter awaiter;

                public void MoveNext()
                {
                    if (state == 0)
                    {
                        awaiter = CustomAsync().GetAwaiter();
                        if (!awaiter.IsCompleted)
                        {
                            state = 1;
                            awaiter.OnCompleted(MoveNext);
                            return;
                        }
                    }
                    string result = awaiter.GetResult();
                    Console.WriteLine(result);
                }
            }

            static void ManualUseCustomAsync()
            {
                var s = new ManualUseCustomAsyncState();
                s.MoveNext();
            }
        }
    }
}
