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

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

static partial class vtask {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

[u.fatal_error_on_failure]
public static void AsCritical( Func<ValueTask> actionA ) =>
   RunAsCritical( actionA ).AsTask().Wait();

[u.fatal_error_on_failure]
public static R AsCritical<R>( Func<ValueTask<R>> functionA ) =>
   RunAsCritical<R>( functionA ).Result;

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

[u.fatal_error_on_failure]
public static bool AsCritical( bool allowCancellation, Func<ValueTask> actionA ) =>
   RunAsCritical( allowCancellation, actionA ).Result;

[u.fatal_error_on_failure]
public static R? AsCritical<R>( bool allowCancellation, Func<ValueTask<R>> functionA )
where R: class =>
   RunAsCritical<R>( allowCancellation, functionA ).Result;

[u.fatal_error_on_failure]
public static R? AsCriticalV<R>( bool allowCancellation, Func<ValueTask<R>> functionA )
where R: struct =>
   RunAsCriticalV<R>( allowCancellation, functionA ).Result;

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

[u.fatal_error_on_failure]
public static ValueTask RunAsCritical( Action action ) =>
   new ValueTask( Task.Run( () => u.critical.Do( action )));

[u.fatal_error_on_failure]
public static ValueTask<R> RunAsCritical<R>( Func<R> function ) =>
   new ValueTask<R>( Task.Run( () => u.critical.Do( function )));

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

[u.fatal_error_on_failure]
public static ValueTask RunAsCritical( Func<ValueTask> actionA ) =>
   new ValueTask( Task.Run( () => u.critical.Do_A( actionA )));

[u.fatal_error_on_failure]
public static ValueTask<R> RunAsCritical<R>( Func<ValueTask<R>> functionA ) =>
   new ValueTask<R>( Task<R>.Run( () => u.critical.Do_A( functionA ).AsTask() ));

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

[u.fatal_error_on_failure]
public static ValueTask<bool> RunAsCritical( bool allowCancellation, Action action ) =>
   new ValueTask<bool>(Task<bool>.Run(() => {
      try {
         action();
      }
      catch ( Exception e ) {
         if ( allowCancellation && e is TaskCanceledException )
            return false;
         throw u.critical.RaiseError( e );
      }
      return true;
   }));

[u.fatal_error_on_failure]
public static ValueTask<R?> RunAsCritical<R>( bool allowCancellation, Func<R> function )
where R: class =>
   new ValueTask<R?>(Task<R?>.Run(() => {
      try {
         return function();
      }
      catch ( Exception e ) {
         if ( allowCancellation && e is TaskCanceledException )
            return null;
         throw u.critical.RaiseError( e );
      }
   }));

[u.fatal_error_on_failure]
public static ValueTask<R?> RunAsCriticalV<R>( bool allowCancellation, Func<R> function )
where R: struct =>
   new ValueTask<R?>(Task<R?>.Run(() => {
      try {
         return (R?)function();
      }
      catch ( Exception e ) {
         if ( allowCancellation && e is TaskCanceledException )
            return null;
         throw u.critical.RaiseError( e );
      }
   }));

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

[u.fatal_error_on_failure]
public static ValueTask<bool> RunAsCritical( bool allowCancellation, Func<ValueTask> actionA ) =>
   new ValueTask<bool>(Task<bool>.Run(async() => {
      try {
         await actionA();
      }
      catch ( Exception e ) {
         if ( allowCancellation && e is TaskCanceledException )
            return false;
         throw u.critical.RaiseError( e );
      }
      return true;
   }));

[u.fatal_error_on_failure]
public static ValueTask<R?> RunAsCritical<R>( bool allowCancellation, Func<ValueTask<R>> functionA )
where R: class =>
   new ValueTask<R?>(Task<R?>.Run(async() => {
      try {
         return await functionA();
      }
      catch ( Exception e ) {
         if ( allowCancellation && e is TaskCanceledException )
            return null;
         throw u.critical.RaiseError( e );
      }
   }));

[u.fatal_error_on_failure]
public static ValueTask<R?> RunAsCriticalV<R>( bool allowCancellation,
                                               Func<ValueTask<R>> functionA )
where R: struct =>
   new ValueTask<R?>(Task<R?>.Run(async() => {
      try {
         return (R?)(await functionA());
      }
      catch ( Exception e ) {
         if ( allowCancellation && e is TaskCanceledException )
            return null;
         throw u.critical.RaiseError( e );
      }
   }));

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} // vtask

} // user_rtx (.wasm)
