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

namespace Delegates
{
    class Examples24_35
    {
        // Listing 9-24
        public static int GetIndexOfFirstNonEmptyBin(int[] bins)
        {
            return Array.FindIndex(
                bins,
                value => value > 0
            );
        }

        public static void VariousFormsOfLambda()
        {
            // Listing 9-25
            Predicate<int> p1 = value => value > 0;
            Predicate<int> p2 = (value) => value > 0;
            Predicate<int> p3 = (int value) => value > 0;
            Predicate<int> p4 = value => { return value > 0; };
            Predicate<int> p5 = (value) => { return value > 0; };
            Predicate<int> p6 = (int value) => { return value > 0; };

            // Listing 9-26
            Func<bool> isAfternoon = () => DateTime.Now.Hour >= 12;
        }

        public static void AnonymousMethod()
        {
            // Listing 9-27
            EventHandler clickHandler = delegate { Debug.WriteLine("Kliknięto przycisk!"); };
        }

        // Listing 9-28
        public static Predicate<int> IsGreaterThan(int threshold)
        {
            return value => value > threshold;
        }

        public static void UseDelegateThatCaptures()
        {
            // Listing 9-29
            Predicate<int> greaterThanTen = IsGreaterThan(10);
            bool result = greaterThanTen(200);

        }

        // Listing 9-31
        static void Calculate(int[] nums)
        {
            int zeroCount = 0;
            int[] nonZeroNums = Array.FindAll(
                nums,
                v =>
                {
                    if (v == 0)
                    {
                        zeroCount += 1;
                        return false;
                    }
                    else
                    {
                        return true;
                    }
                });
            Console.WriteLine(
                "Liczba elementów o wartości 0: {0}, pierwszy element różny od 0: {1}",
                zeroCount,
                nonZeroNums[0]);
        }

        public static void PrematureDisposal()
        {
            // Listing 9-32
            using (var file = new StreamWriter(@"c:\temp\log.txt"))
            {
                var req = WebRequest.Create("http://www.interact-sw.co.uk/");
                req.BeginGetResponse(iar =>
                {
                    var resp = req.EndGetResponse(iar);

                    // BŁĄD! Ten obiekt StreamWriter najprawdopodobniej został 
                    // już wcześniej zwolniony
                    file.WriteLine(resp.ContentType);
                }, null);

            } // Obiekt StreamWriter zostanie najprawdopodobniej zwolniony
              // zanim zostanie wywołana metoda zwrotna. 
        }

        // Listing 9-33
        public static void Caught()
        {
            var greaterThanN = new Predicate<int>[10];
            for (int i = 0; i < greaterThanN.Length; ++i)
            {
                greaterThanN[i] = value => value > i; // Nieprawidłowe użycie zmiennej i
            }

            Console.WriteLine(greaterThanN[5](20));
            Console.WriteLine(greaterThanN[5](6));
        }

        public static void AvoidingCaptureProblems()
        {
            var greaterThanN = new Predicate<int>[10];

            // Listing 9-34
            for (int i = 0; i < greaterThanN.Length; ++i)
            {
                int current = i;
                greaterThanN[i] = value => value > current;
            }
        }

        public static void MultipleCaptures()
        {
            var greaterThanN = new Predicate<int>[10];

            // Listing 9-35
            int offset = 10;
            for (int i = 0; i < greaterThanN.Length; ++i)
            {
                int current = i;
                greaterThanN[i] = value => value > (current + offset);
            }
        }
    }

    // Kod został umieszczony w komentarzach ponieważ reprezentuje kod wygenerowany przez
    // kompilator, który nie jest właściwie prawidłowym kodem C#.
    // Listing 9-30
    //[CompilerGenerated]
    //private sealed class <>c__DisplayClass1
    //{
    //    public int threshold;

    //    public bool <IsGreaterThan>b__0(int value)
    //    {
    //        return (value > this.threshold);
    //    }
    //}
}
