using System.Reflection; // Assembly
using System.Runtime.CompilerServices; // CompilerGeneratedAttribute
using Packt.Shared; // CoderAttribute

WriteLine("Metadane zestawu:"); 
Assembly? assembly = Assembly.GetEntryAssembly();

if (assembly is null)
{
  WriteLine("Błąd podczas odczytu wejścia do zestawu.");
  return;
}

WriteLine($"  Pełna nazwa: {assembly.FullName}");
WriteLine($"  Lokalizacja: {assembly.Location}");
WriteLine($"  Punkt wejścia: {assembly.EntryPoint?.Name}");

IEnumerable<Attribute> attributes = assembly.GetCustomAttributes();
WriteLine($"  Atrybuty zestawu:"); 
foreach (Attribute a in attributes)
{
  WriteLine($"   {a.GetType()}");
}

AssemblyInformationalVersionAttribute? version = assembly
  .GetCustomAttribute<AssemblyInformationalVersionAttribute>();

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

AssemblyCompanyAttribute? company = assembly
  .GetCustomAttribute<AssemblyCompanyAttribute>();

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

WriteLine();
WriteLine($"* Typy:");
Type[] types = assembly.GetTypes();

foreach (Type type in types)
{
  // Opcjonalne zadanie. Pominięcie kodu utworzonego przez generator.
  CompilerGeneratedAttribute? compilerGenerated =
    type.GetCustomAttribute<CompilerGeneratedAttribute>();
  if (compilerGenerated is not null) continue; // Przejście do nastęnego elementu.

  WriteLine();
  WriteLine($"Typ: {type.FullName}");
  MemberInfo[] members = type.GetMembers();

  foreach (MemberInfo member in members)
  {
    ObsoleteAttribute? obsolete =
      member.GetCustomAttribute<ObsoleteAttribute>();

    WriteLine("{0}: {1} ({2}) {3}",
      member.MemberType, member.Name,
      member.DeclaringType?.Name,
      obsolete is null ? "" : $"Przestarzała metoda! {obsolete.Message}");

    IOrderedEnumerable<CoderAttribute> coders =
      member.GetCustomAttributes<CoderAttribute>()
      .OrderByDescending(c => c.LastModified);

    foreach (CoderAttribute coder in coders)
    {
      WriteLine("-> Zmodyfikował {0} w dniu {1}",
        coder.Coder, coder.LastModified.ToShortDateString());
    }
  }
}
