using System.Reflection; // Assembly
using System.Runtime.CompilerServices; // to use CompilerGeneratedAttribute
using BibliotekaWspolna; // ProgramistaAttribute

using static System.Console;

WriteLine("Metadane zestawu:");
Assembly? zestaw = Assembly.GetEntryAssembly();
if (zestaw is null)
{
   WriteLine("Nie udało się pobrać zestawu wejściowego.");
   return;
}

WriteLine($"   Nazwa: {zestaw.FullName}");
WriteLine($"   Lokalizacja: {zestaw.Location}");

IEnumerable<Attribute> atrybuty = zestaw.GetCustomAttributes();

WriteLine($"   Atrybuty na poziomie zestawu:");
foreach (Attribute a in atrybuty)
{
   WriteLine($"      {a.GetType()}");
}

AssemblyInformationalVersionAttribute? wersja = zestaw
  .GetCustomAttribute<AssemblyInformationalVersionAttribute>();

WriteLine($"  Wersja: {wersja?.InformationalVersion}");

AssemblyCompanyAttribute? firma = zestaw
  .GetCustomAttribute<AssemblyCompanyAttribute>();

WriteLine($"  Firma: {firma?.Company}");

WriteLine();
WriteLine($"* Typy:");
Type[] typy = zestaw.GetTypes();

foreach (Type typ in typy)
{
   WriteLine();
   WriteLine($" Typ: {typ.FullName}");
   MemberInfo[] elementy = typ.GetMembers();

   foreach (MemberInfo element in elementy)
   {
      WriteLine("   {0}: {1} ({2})",
        arg0: element.MemberType,
        arg1: element.Name,
        arg2: element.DeclaringType?.Name);

      IOrderedEnumerable<ProgramistaAttribute> programisci =
        element.GetCustomAttributes<ProgramistaAttribute>()
        .OrderByDescending(c => c.OstatnioZmienione);

      foreach (ProgramistaAttribute programista in programisci)
      {
         WriteLine($"->   Zmienione przez {0} w dniu {1}",
          programista.Programista,
          programista.OstatnioZmienione.ToShortDateString());
      }
   }
}


class Zwierze
{
   [Programista("Mark Price", "22 sierpnia 2017")]
   [Programista("Jan Radziewicz", "13 maja 2018")]
   public static void PowiedzCos()
   {
      WriteLine("Hau...");
   }
}

