//\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
// CommonHelpers satellite library | Author: Sergei Y.Kitáev
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#nullable enable
using System;
using System.Runtime.CompilerServices;

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

//**************************************************************************************************
/// <summary>
/// Non-nullable property support (strict access to underlying value)
/// </summary>
public static class HPropertyNN {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

/// <exception cref="ArgumentNullException" />
/// <exception cref="NullReferenceException" />
[HStrictResult]
public static T Get<T>( object obj, T? value,
                        [CallerMemberName] string? getMethodName=null )
where T: class
{
   HArgChecking.VerifyNotNull( obj );
   return value ?? throw new NullReferenceException(string.Format(
      "Reference property was not initialized: \"{0}.{1}\".",
      obj.GetType(), PropertyName( getMethodName ) ));
}

/// <exception cref="ArgumentNullException" />
/// <exception cref="HNullValueException" />
[HStrictResult]
public static T Value<T>( object obj, T? nullableValue,
                          [CallerMemberName] string? getMethodName=null )
where T: struct
{
   HArgChecking.VerifyNotNull( obj );
   if ( nullableValue.HasValue )
      return nullableValue.Value;
   throw HNullValueExceptionCreator.Create(
      "Value property was not initialized: \"{0}.{1}\".",
      obj.GetType(), PropertyName( getMethodName ) );
}

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

/// <exception cref="ArgumentNullException" />
/// <exception cref="ArgumentException" />
public static string NameAuto( [CallerMemberName] string? propertyName=null )
{
   propertyName = HArgChecking.NN( propertyName );
   if ( propertyName == "" )
      throw new ArgumentException( "Property name is empty.", nameof(propertyName) );
   return propertyName;
}

/// <exception cref="ArgumentNullException" />
/// <exception cref="ArgumentException" />
public static string NameAutoN( [CallerMemberName] string? propertyName=null )
{
   propertyName = HArgChecking.NN( propertyName );
   if ( propertyName == "" )
      throw new ArgumentException( "Property name is empty.", nameof(propertyName) );
   if ( !propertyName.StartsWith( "N" ) )
      throw new ArgumentException(
         "Property name must start with \"N\" (case sensitive).",
         nameof(propertyName) );
   if ( propertyName == "N" )
      throw new ArgumentException( "Property name must not be \"N\".", nameof(propertyName) );
   return propertyName.Substring( 1 );
}

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

static string PropertyName(string? getMethodName) =>
   getMethodName ?? "???";

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} // HPropertyNN
//**************************************************************************************************

} // CommonHelpers (.WASM)
