//\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
// UserRTX.NET satellite library | Author: Sergei Y.Kitáev
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
using System;
using System.Reflection;

#if !WASM
namespace user_rtx { using u = user_rtx;
#else
namespace user_rtx.wasm { using u = user_rtx.wasm;
#endif

/// <summary>
/// Assembly info
/// </summary>
public static class assembly {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

[u.calling_assembly]
public static string GetSimpleName() =>
   GetSimpleName( Assembly.GetCallingAssembly() );

public static string GetSimpleName( Assembly assembly ) =>
   assembly.GetName().Name.NN();

//--------------------------------------------------------------------------------------------------

[u.calling_assembly]
public static string GetModuleName() =>
   GetModuleName( Assembly.GetCallingAssembly() );

public static string GetModuleName( Assembly assembly ) =>
   assembly.GetModules()[ 0 ].Name;

//--------------------------------------------------------------------------------------------------

[u.calling_assembly]
public static string? GetConfigurationName() =>
   GetConfigurationName( Assembly.GetCallingAssembly() );

public static string? GetConfigurationName( Assembly assembly ) =>
   GetAttribute<AssemblyConfigurationAttribute>( assembly )?.Configuration;

//==================================================================================================

/// <exception cref="ArgumentException" />
[u.calling_assembly]
public static Attribute? GetAttribute( Type attributeType ) =>
   GetAttribute( Assembly.GetCallingAssembly(), attributeType );

/// <exception cref="ArgumentException" />
public static Attribute? GetAttribute( Assembly assembly, Type attributeType )
{
   u.type_argcheck.TypeOf<Attribute>( attributeType, nameof(attributeType) );

   var attributes =
      (Attribute[])assembly.GetCustomAttributes( attributeType, false );

   switch ( attributes.Length )
   {
   case 0: return null;
   case 1: return attributes[ 0 ];
   default:
      throw e_unexpected.New(
         "Multiple attributes of “{0}” type on “{1}” assembly were found.",
         attributeType, assembly );
   } // switch
}

//--------------------------------------------------------------------------------------------------

[u.calling_assembly]
public static TAttribute? GetAttribute<TAttribute>()
where TAttribute: Attribute =>
   GetAttribute<TAttribute>( Assembly.GetCallingAssembly() );

public static TAttribute? GetAttribute<TAttribute>( Assembly assembly )
where TAttribute: Attribute =>
   (TAttribute?)GetAttribute( assembly, typeof(TAttribute) );

//--------------------------------------------------------------------------------------------------

[u.calling_assembly]
public static bool IsMarkedWithAttribute( Type attributeType ) =>
   IsMarkedWithAttribute( Assembly.GetCallingAssembly(), attributeType );

public static bool IsMarkedWithAttribute( Assembly assembly, Type attributeType ) =>
   GetAttribute( assembly, attributeType ) != null;

//==================================================================================================

[u.calling_assembly]
public static bool IsConfiguredForDebug() =>
   IsConfiguredForDebug( Assembly.GetCallingAssembly() );

public static bool IsConfiguredForDebug( Assembly assembly ) =>
   u.str.Equals( GetConfigurationName(assembly), "Debug", true );


//--------------------------------------------------------------------------------------------------

[u.calling_assembly]
public static bool IsConfiguredForTrace() =>
   IsConfiguredForTrace( Assembly.GetCallingAssembly() );

public static bool IsConfiguredForTrace( Assembly assembly ) =>
   IsMarkedWithAttribute( assembly, typeof(u.TraceConfigurationAttribute) );

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} // assembly

} // user_rtx (.wasm)
