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

#if !WASM
namespace CommonHelpers {
#else
namespace CommonHelpers.WASM {
#endif

//**************************************************************************************************
/// <summary>
/// </summary>
public static partial class HAssembly {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

public static string GetModuleName()
{
   return GetModuleName( Assembly.GetCallingAssembly() );
}

public static string GetModuleName(Assembly assembly)
{
   HArgChecking.VerifyNotNull( assembly );
   return assembly.GetModules()[0].Name;
}

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

public static string GetConfigurationName()
{
   return GetConfigurationName( Assembly.GetCallingAssembly() );
}

public static string GetConfigurationName(Assembly assembly)
{
   var configAttribute =
      GetAttribute<AssemblyConfigurationAttribute>( assembly );
   return configAttribute!=null ?
      configAttribute.Configuration : null;
}

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

public static bool IsConfiguredForDebug()
{
   return IsConfiguredForDebug( Assembly.GetCallingAssembly() );
}

public static bool IsConfiguredForDebug(Assembly assembly)
{
   return HString.Equals(
      GetConfigurationName(assembly),
      "Debug", true );
}

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

public static bool IsConfiguredForTrace()
{
   return IsConfiguredForTrace( Assembly.GetCallingAssembly() );
}

public static bool IsConfiguredForTrace(Assembly assembly)
{
   return IsMarkedWithAttribute( assembly,
      typeof(HTraceConfigurationAttribute) );
}

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

public static Attribute GetAttribute(Type attributeType)
{
   return GetAttribute(
      Assembly.GetCallingAssembly(),
      attributeType );
}

public static Attribute GetAttribute(Assembly assembly,Type attributeType)
{
   HArgChecking.VerifyNotNulls( assembly, attributeType );
   HArgChecking.VerifyTypeOf<Attribute>( attributeType );

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

   switch (attributes.Length)
   {
   case 0: return null;
   case 1: return attributes[0];
   default:
      throw HOpFailedExceptionCreator.Create(
         "Multiple attribute of type \"{0}\" on assembly \"{1}\".",
         attributeType, assembly.GetName().Name );
   }
}

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

public static TAttribute GetAttribute<TAttribute>()
   where TAttribute: Attribute
{
   return GetAttribute<TAttribute>( Assembly.GetCallingAssembly() );
}

public static TAttribute GetAttribute<TAttribute>(Assembly assembly)
   where TAttribute: Attribute
{
   return (TAttribute)GetAttribute( assembly, typeof(TAttribute) );
}

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

public static bool IsMarkedWithAttribute(Type attributeType)
{
   return IsMarkedWithAttribute(
      Assembly.GetCallingAssembly(),
      attributeType );
}

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

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

public static Assembly GetLoadedAssembly([HOptional] string simpleName)
{
   foreach ( var asm in AppDomain.CurrentDomain.GetAssemblies() )
      if ( HString.Equals( asm.GetName().Name, simpleName, true ) )
         return asm;
   return null;
}

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

public static Assembly GetOrLoadAssembly(string simpleName,AssemblyName loadName)
{
   HArgChecking.VerifyNotNulls( simpleName, loadName );
   return GetLoadedAssembly( simpleName ) ?? Assembly.Load( loadName );
}

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

public static Assembly GetOrLoadAssembly(string simpleName,string loadName)
{
   HArgChecking.VerifyNotNulls( simpleName, loadName );
   return GetLoadedAssembly( simpleName ) ?? Assembly.Load( new AssemblyName( loadName ) );
}

public static Assembly GetOrLoadAssembly( string simpleName,
                                          string loadNameFmt,
                                          params object[] parameters )
{
   HArgChecking.VerifyNotNulls( simpleName, loadNameFmt, parameters );
   return GetOrLoadAssembly( simpleName, string.Format( loadNameFmt, parameters ) );
}

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

static HAssembly()
{
   CommonHelpers_Core.Access();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} // HAssembly
//**************************************************************************************************

} // CommonHelpers (.WASM)
