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

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

namespace ex_023_009_HashSet_and_SortedSet
{
    /// <summary>
    /// HashSet<T> et SortedSet<T> sont deux collections génériques introduites respectivement en .NET 3.5 et .NET 4.0.
    /// Les caractéristiques de ces collections sont :
    /// - elles sont très efficaces pour la recherche d'éléments (Contains utilise une méthode de hashage)
    /// - elles ne stockent pas de doublons
    /// - on ne peut pas les utiliser avec un indexeur
    /// De plus, SortedSet ordonne les éléments.
    /// HashSet utilise une hashtable, SortedSet un red/black tree.
    /// Les deux collections implémentent ICollection<T> et ISet<T>
    /// </summary>
    class Program
    {
        static void Display(ISet<string> colors)
        {
            WriteLine("début");
            foreach (string s in colors)
            {
                WriteLine($"\t{s}");
            }
            WriteLine("fin");
        }

        static void Main(string[] args)
        {
            HashSet<string> colorsHashSet = new HashSet<string>(new string[] { "vert", "rouge", "bleu", "orange" });
            SortedSet<string> colorsSortedSet = new SortedSet<string>(new string[] { "vert", "rouge", "bleu", "orange" });
            WriteLine("Add");
            colorsHashSet.Add("rouge");
            colorsHashSet.Add("jaune");
            Display(colorsHashSet);

            colorsSortedSet.Add("rouge");
            colorsSortedSet.Add("jaune");
            Display(colorsSortedSet);


            // Set Operations (destructive methods)
            List<string> colorsList = new List<string> { "rose", "mauve", "noir", "bleu", "jaune" };
            WriteLine("UnionWith");
            colorsHashSet.UnionWith(colorsList); //colorsHashSet est modifié (des éléments sont ajoutés)
            Display(colorsHashSet);
            WriteLine("IntersectWith"); //colorsSortedSet est modifié (des éléments sont enlevés)
            colorsSortedSet.IntersectWith(colorsList);
            Display(colorsSortedSet);
            colorsHashSet = new HashSet<string>(new string[] { "vert", "rouge", "bleu", "orange", "jaune" });
            colorsSortedSet = new SortedSet<string>(new string[] { "vert", "rouge", "bleu", "orange", "jaune" });
            WriteLine("ExceptWith"); //enlève les élements qui sont dans les deux
            colorsHashSet.ExceptWith(colorsList); //colorsHashSet est modifié (des éléments sont enlevés
            Display(colorsHashSet);
            WriteLine("SymmetricExceptWith"); // ne garde que les éléments qui ne sont qu'une seule fois dans l'une ou l'autre des deux collections
            colorsSortedSet.SymmetricExceptWith(colorsList); //colorsSortedSet est modifié (des éléments sont enlevés
            Display(colorsSortedSet);

            // Query methods (non-destructive methods)
            colorsHashSet = new HashSet<string>(new string[] { "vert", "bleu", "jaune" });
            colorsSortedSet = new SortedSet<string>(new string[] { "vert", "rouge", "mauve", "bleu", "rose", "orange", "jaune", "noir" });
            List<string> colorsList2 = new List<string> { "vert", "rouge", "bleu", "orange", "jaune" };
            WriteLine("IsSubsetOf"); //est-ce un sous-ensemble de ...
            WriteLine($"colorsHashSet.IsSubsetOf(colorsList2) ? {colorsHashSet.IsSubsetOf(colorsList2)}");
            WriteLine("IsSupersetOf"); //est-ce un sur-ensemble de ...
            WriteLine($"colorsSortedSet.IsSupersetOf(colorsList2) ? {colorsSortedSet.IsSupersetOf(colorsList2)}");
            WriteLine("Overlaps"); //y a-t-il des éléments en commun avec ...
            WriteLine($"colorsHashSet.Overlaps(colorsList2) ? {colorsHashSet.Overlaps(colorsList2)}");
            WriteLine("SetEquals"); //ont-ils exactement les mêmes éléments
            WriteLine($"colorsHashSet.SetEquals(colorsList2) ? {colorsHashSet.SetEquals(colorsList2)}");

            //méthodes propres à SortedSet
            //un SortedSet peut prendre un IComparer<T> dans son constructeur
            SortedSet<string> colorsSortedSet2 = new SortedSet<string>(StringComparer.CurrentCultureIgnoreCase);
            //un SortedSet peut sortir un sous-ensemble donné entre deux valeurs (inf et sup)
            WriteLine("GetViewBetween"); //y a-t-il des éléments en commun avec ...
            var colorsViewBetweenSortedSet = colorsSortedSet.GetViewBetween("l", "q");
            Display(colorsViewBetweenSortedSet);
            //on peut aussi inverser, obtenir le min et le max
            WriteLine("Min, Max"); //y a-t-il des éléments en commun avec ...
            WriteLine($"Min : {colorsSortedSet.Min}");
            WriteLine($"Max : {colorsSortedSet.Max}");

            WriteLine("Reverse"); //y a-t-il des éléments en commun avec ...
            WriteLine("début");
            foreach (string s in colorsSortedSet.Reverse())
            {
                WriteLine($"\t{s}");
            }
            WriteLine("fin");
        }
    }
}
