// ========================================================================
//
// Copyright (C) 2016-2017 MARC CHEVALDONNE
//                         marc.chevaldonne.free.fr
//
// Module        : Program.cs
// Author        : Marc Chevaldonné
// Creation date : 2016-10-03
//
// ========================================================================

using System;
using System.Collections.Generic;
using static System.Console;
using System.Linq;

namespace ex_031_009_LINQ_element_operators
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Nounours> nounours = new List<Nounours> {
                                      new Nounours("mouton", new DateTime(2009, 09, 16), 1000),
                                      new Nounours("ours", new DateTime(2009, 08, 15), 2000),
                                      new Nounours("chat", new DateTime(2009, 07, 14), 1000),
                                      new Nounours("chien", new DateTime(2009, 06, 13), 500),
                                      new Nounours("lapin", new DateTime(2009, 05, 12), 500),
                                      new Nounours("chat", new DateTime(2009, 07, 14), 2000),
                                      new Nounours("macaque", new DateTime(2009, 04, 11), 500)};

            List<Nounours> nounoursVide = new List<Nounours>();

            /////////////////////
            //Element Operators//
            /////////////////////
            WriteLine("Element Operators");

            //First : lève une exception si aucun élément n'est trouvé ou si la collection est vide
            WriteLine("First");
            WriteLine(nounours.First());
            WriteLine(nounours.First(n => n.Nom.Equals("chat")));
            try
            {
                WriteLine(nounoursVide.First());
            }
            catch (InvalidOperationException exc)
            {
                WriteLine($"{exc.ToString()}");
            }
            WriteLine();

            //First or default : ne lance pas d'exception si aucun élément ne vérifie la condition ou si la collection est vide
            WriteLine("First or default");
            WriteLine(nounours.FirstOrDefault());
            WriteLine(nounours.FirstOrDefault(n => n.Nom.Equals("chat")));
            WriteLine(nounoursVide.FirstOrDefault());
            WriteLine();

            //Last : lève une exception si aucun élément n'est trouvé ou si la collection est vide
            WriteLine("Last");
            WriteLine(nounours.Last());
            WriteLine(nounours.Last(n => n.Nom.Equals("chat")));
            try
            {
                WriteLine(nounoursVide.Last());
            }
            catch (InvalidOperationException exc)
            {
                WriteLine($"{exc.ToString()}");
            }
            WriteLine();

            //Last or default : ne lance pas d'exception si aucun élément ne vérifie la condition
            WriteLine("Last or default");
            WriteLine(nounours.LastOrDefault());
            WriteLine(nounours.LastOrDefault(n => n.Nom.Equals("chat")));
            WriteLine(nounoursVide.LastOrDefault());
            WriteLine();

            //Single : lance une exception s'il n'y a pas un seul élément vérifiant la condition
            WriteLine("Single");
            WriteLine(nounours.Single(n => n.Nom.Equals("ours")));
            try
            {
                WriteLine(nounoursVide.Single());
            }
            catch (InvalidOperationException exc)
            {
                WriteLine($"{exc.ToString()}");
            }
            WriteLine();

            //Single or default : lève une exception si plusieurs éléments vérifient la condition
            WriteLine("Single or default");
            try
            {
                WriteLine(nounours.SingleOrDefault());
            }
            catch (InvalidOperationException exc)
            {
                WriteLine($"{exc.ToString()}");
            }
            WriteLine(nounours.SingleOrDefault(n => n.Nom.Equals("ours")));
            WriteLine(nounoursVide.SingleOrDefault());
            WriteLine();
            WriteLine(nounours.Single(n => n.Nom.Length == nounours.Max(n2 => n2.Nom.Length)));
            WriteLine();

            //ElementAt : lance une exception s'il n'y a pas d'élément à la position demandée
            WriteLine("ElementAt");
            WriteLine(nounours.ElementAt(2));
            try
            {
                WriteLine(nounours.ElementAt(100));
            }
            catch (ArgumentOutOfRangeException exc)
            {
                WriteLine($"{exc.ToString()}");
            }
            WriteLine();

            //ElementAt or default : lève une exception si plusieurs éléments vérifient la condition
            WriteLine("ElementAt or default");
            WriteLine(nounours.ElementAtOrDefault(100));
            WriteLine();
        }
    }
}
