//\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
// 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 task {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

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

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

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

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

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

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

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

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

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

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

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

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

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

[u.fatal_error_on_failure]
public static Task<bool> RunAsCritical( bool allowCancellation, Action action ) =>
   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 Task<R?> RunAsCritical<R>( bool allowCancellation, Func<R> function )
where R: class =>
   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 Task<R?> RunAsCriticalV<R>( bool allowCancellation, Func<R> function )
where R: struct =>
   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 Task<bool> RunAsCritical( bool allowCancellation, Func<Task> actionA ) =>
   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 Task<R?> RunAsCritical<R>( bool allowCancellation, Func<Task<R>> functionA )
where R: class =>
   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 Task<R?> RunAsCriticalV<R>( bool allowCancellation, Func<Task<R>> functionA )
where R: struct =>
   Task<R?>.Run(async() => {
      try {
         return (R?)(await functionA());
      }
      catch ( Exception e ) {
         if ( allowCancellation && e is TaskCanceledException )
            return null;
         throw u.critical.RaiseError( e );
      }
   });

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} // task

} // user_rtx (.wasm)
