using System.Collections.Immutable;

using static System.Console;

PracaZListami();
// PracaZeSlownikami();
// PracaZKolejkami();
// PracaZKolejkamiPriorytetowymi();

static void Wypisz(string tytul, IEnumerable<string> kolekcja)
{
   WriteLine(tytul);
   foreach (string element in kolekcja)
   {
      WriteLine($"  {element}");
   }
}

static void PracaZListami()
{
   // Proste instrukcje tworząca listę i dodające do niej trzy elementy
   List<string> miasta = new();
   miasta.Add("Londyn");
   miasta.Add("Paryż");
   miasta.Add("Mediolan");

   /* Inna składnia, którą kompilator zamienia w trzy wywołania
      metody Add, takie jak powyżej
   List<string> miasta = new()
     { "Londyn", "Paryż", "Mediolan" };
   */

   /* Inna składnia, w której przekazujemy tablicę wartości
      typu string do metody AddRange.
   List<string> miasta = new();
   miasta.AddRange( new[] { "Londyn", "Paryż", "Mediolan" });
   */

   Wypisz("Początkowa lista", miasta);

   WriteLine($"Pierwszym miastem jest {miasta[0]}.");
   WriteLine($"Ostatnim miastem jest {miasta[miasta.Count - 1]}.");

   miasta.Insert(0, "Sydney");

   Wypisz("Po dodaniu Sydney pod indeksem 0", miasta);

   miasta.RemoveAt(1);
   miasta.Remove("Mediolan");

   Wypisz("Po usunięciu dwóch miast", miasta);
}


static void PracaZeSlownikami()
{
   Dictionary<string, string> slowaKluczowe = new();

   // Dodanie elementu przy wykorzystaniu parametrów nazywanych
   slowaKluczowe.Add(key: "int", value: "typ liczb całkowitych (32 bity)");

   // Dodanie elementów przy wykorzystaniu parametrów pozycyjnych
   slowaKluczowe.Add("long", "typ liczb całkowitych (64 bity)");
   slowaKluczowe.Add("float", "liczby zmiennoprzecinkowe pojedynczej precyzji");

   /* Inna składnia. Kompilator przekształci ją w wywołania metody Add
   Dictionary<string, string> slowaKluczowe = new()
   {
     { "int", "typ liczb całkowitych (32 bity)},
     { "long", "typ liczb całkowitych (64 bity)" },
     { "float", "liczby zmiennoprzecinkowe pojedynczej precyzji" },
   }; */

   /* Inna składnia. Kompilator przekształci ją w wywołania metody Add
   Dictionary<string, string> slowaKluczowe = new()
   {
     ["int"] = "typ liczb całkowitych (32 bity)",
     ["long"] = "typ liczb całkowitych (64 bity)",
     ["float"] = "liczby zmiennoprzecinkowe pojedynczej precyzji", // ostatni przecinek jest opcjonalny
   }; */

   Wypisz("Klucze słownika:", slowaKluczowe.Keys);
   Wypisz("Wartości słownika:", slowaKluczowe.Values);

   WriteLine("Słowa kluczowe i ich definicje");
   foreach (KeyValuePair<string, string> element in slowaKluczowe)
   {
      WriteLine($"  {element.Key}: {element.Value}");
   }

   // Wyszukiwanie wartości za pomocą klucza
   WriteLine($"Definicja słowa kluczowego 'long' to: {slowaKluczowe["long"]}");
}


static void PracaZKolejkami()
{
   Queue<string> kawa = new();

   kawa.Enqueue("Damian"); // początek kolejki
   kawa.Enqueue("Andrzej");
   kawa.Enqueue("Romuald");
   kawa.Enqueue("Adam");
   kawa.Enqueue("Irena"); // koniec kolejki

   Wypisz("Początkowa kolejka, od końca, do początku", kawa);

   // serwer obsługuje pierwszą osobę z kolejki
   string obsluzona = kawa.Dequeue();
   WriteLine($"Obsłużono: {obsluzona}");

   // Serwer obsługuje kolejną osobę z kolejki
   obsluzona = kawa.Dequeue();
   WriteLine($"Obsłużono: {obsluzona}");

   Wypisz("Aktualna kolejka, od końca, do początku", kawa);

   WriteLine($"Następna osoba w kolejce to {kawa.Peek()}.");

   Wypisz("Aktualna kolejka, od końca, do początku", kawa);
}

static void WypiszKolejkePriorytetowa<TElement, TPriorytet>(string tytul,
  IEnumerable<(TElement Element, TPriorytet Priorytet)> kolekcja)
{
   WriteLine(tytul);
   foreach ((TElement, TPriorytet) element in kolekcja)
   {
      WriteLine($" {element.Item1}: {element.Item2}");
   }
}

static void PracaZKolejkamiPriorytetowymi()
{
  PriorityQueue<string, int> szczepionka = new();

  // dodaj kilka osób
  // 1 = wysoki priorytet – osoby po 70. roku życia albo o słabym zdrowiu
  // 2 = średni priorytet – osoby w średnim wieku
  // 3 = niski priorytet – nastolatki i dwudziestolatkowie
  szczepionka.Enqueue("Pamela", 1); // moja mama (70 lat)
  szczepionka.Enqueue("Renata", 3); // moja siostrzenica (nastolatka)
  szczepionka.Enqueue("Julia", 2);  // moja siostra (40 lat)
  szczepionka.Enqueue("Jan", 1);    // mój tato (70 lat)

  WypiszKolejkePriorytetowa("Aktualna kolejka do szczepienia:", szczepionka.UnorderedItems);

  WriteLine($"Zaszczepiono {szczepionka.Dequeue()}");
  WriteLine($"Zaszczepiono {szczepionka.Dequeue()}");

  WypiszKolejkePriorytetowa("Aktualna kolejka do szczepienia:", szczepionka.UnorderedItems);

  WriteLine($"Zaszczepiono {szczepionka.Dequeue()}");

  szczepionka.Enqueue("Mark", 2); // ja (40 lat)
  WriteLine($"Zaraz zaszczepimy {szczepionka.Peek()}");

  WypiszKolejkePriorytetowa("Aktualna kolejka do szczepienia:", szczepionka.UnorderedItems);
}

