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

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

/// <summary>
/// Argument checking for type
/// </summary>
public static partial class type_argcheck {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

/// <exception cref="ArgumentException" />
[u.returns_source]
public static Type TypeOf<TComparand>( object argument, string paramName ) =>
   TypeOf( argument.GetType(), typeof(TComparand), paramName );

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

/// <exception cref="ArgumentException" />
[u.returns_source]
public static Type TypeOf<TComparand>( Type type, string paramName ) =>
   TypeOf( type, typeof(TComparand), paramName );

/// <exception cref="ArgumentException" />
[u.returns_source]
public static Type TypeOf( Type type, Type comparandType, string paramName ) =>
   u.type.IsTypeOf( type, comparandType ) ? type :
      throw u.type_argcheck_errors.TYPE_IS_NOT( comparandType, paramName );

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

/// <exception cref="ArgumentException" />
[u.returns_source]
public static T ValueOf<T>( T value, Type comparandType, string paramName )
where T: notnull
{
   VerifyValueOf( value, comparandType, paramName );
   return value;
}

/// <exception cref="ArgumentException" />
[u.returns_source]
public static TComparand ValueOf<TComparand>( object value, string paramName )
where TComparand: notnull
{
   VerifyValueOf<TComparand>( value, paramName );
   return (TComparand)value;
}

/// <exception cref="ArgumentException" />
public static void VerifyValueOf<TComparand>( object value, string paramName ) =>
   VerifyValueOf( value, typeof(TComparand), paramName );

/// <exception cref="ArgumentException" />
public static void VerifyValueOf( object value, Type comparandType, string paramName )
{
   if ( !u.type.IsValueOf( value, comparandType ) )
      throw u.type_argcheck_errors.VALUE_IS_NOT_OF( comparandType, paramName );
}

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

/// <exception cref="ArgumentException" />
[u.returns_source]
public static Type ByRef( Type type, string paramName ) =>
   type.IsByRef ? type :
      throw u.type_argcheck_errors.TYPE_IS_NOT_REFERENCE_TYPE( type, paramName );

/// <exception cref="ArgumentException" />
[u.returns_source]
public static Type ValueType( Type type, string paramName ) =>
   type.IsValueType ? type :
      throw u.type_argcheck_errors.TYPE_IS_NOT_VALUE_TYPE( type, paramName );

/// <exception cref="ArgumentException" />
[u.returns_source]
public static Type Enum( Type type, string paramName ) =>
   type.IsEnum ? type :
      throw u.type_argcheck_errors.TYPE_IS_NOT_ENUMERATION( type, paramName );

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

/// <exception cref="ArgumentException" />
[u.returns_source]
public static Type StdValue( Type type, string paramName ) =>
   u.type.IsStdValue( type ) ? type :
      throw u.type_argcheck_errors.TYPE_IS_NOT_STD_VALUE_TYPE( type, paramName );

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

/// <exception cref="ArgumentException" />
[u.returns_source]
public static Type Integral( Type type, string paramName ) =>
   u.type.IsIntegralNumber( type ) ? type :
      throw u.type_argcheck_errors.TYPE_IS_NOT_INTEGRAL_TYPE( type, paramName );

/// <exception cref="ArgumentException" />
[u.returns_source]
public static Type IntegralSignedlNumber( Type type, string paramName ) =>
   u.type.IsIntegralSignedNumber( type ) ? type :
      throw u.type_argcheck_errors.TYPE_IS_NOT_INTEGRAL_SIGNED_NUMBER_TYPE( type, paramName );

/// <exception cref="ArgumentException" />
[u.returns_source]
public static Type IntegralUnsignedNumber( Type type, string paramName ) =>
   u.type.IsIntegralUnsignedNumber( type ) ? type :
      throw u.type_argcheck_errors.TYPE_IS_NOT_INTEGRAL_UNSIGNED_NUMBER_TYPE( type, paramName );

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} // type_argcheck

} // user_rtx (.wasm)
