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

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

static partial class fatal_impl {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

public static void FatalRoutine_0( u.FatalAttributes attr, u.FatalErrorArgs parameters )
{
   TraceError( MakeReportText( attr, parameters, true ) );
   if ( attr.ReportToConsole ) {
      string reportText = MakeReportText( attr, parameters, consoleFormatting: true );
      Try(() => PrintToConsole( reportText ));
   }
   if ( IsWin32 )
      Try(() => w32_core.Beep( 800, 300 ));
   if ( attr.EmergencyCallback_0 != null ) {
      string reportText = MakeReportText( attr, parameters );
      string? reportTextWithStack = HasNN(
         parameters.StackTrace, parameters.DispatcherCallerStack ) ?
            MakeReportText( attr, parameters, true ) :
            null;
      try {
         attr.EmergencyCallback_0( attr, reportText, reportTextWithStack );
      } catch ( Exception e ) {
         TraceError(
            "=== EmergencyCallback_0 has failed: ===\n"+
            MakeExceptionText( e, true ) );
      }
   }
}

public static int? FatalRoutine( u.FatalAttributes attr, u.FatalErrorArgs parameters )
{
   string? filePath = null;
   try {
      filePath = MakeHtmlReport( attr, parameters );
      if ( attr.ReportToConsole )
         Try(() => PrintToConsole( false,
            $"(Report-file: “{filePath}”.)" ));
      TraceReportFilePath( filePath );
      if ( attr.UseMessageDialog && MessageDialog( attr, parameters ) ||
           !attr.UseMessageDialog && attr.ShowHtmlReport )
         ShowHtmlReport( filePath );
   }
   catch ( Exception e ) {
      string exceptionText = MakeExceptionText( e );
      TraceError( exceptionText );
      if ( attr.UseMessageDialog ) {
         string errorText = attr.ReportText != null ?
            attr.ReportText + "\n\n" + exceptionText :
            exceptionText;
         Try(() => ShowError( attr, errorText ));
      }
   }
   string reportText = MakeReportText( attr, parameters );
   string? reportTextWithStack = HasNN(
      parameters.StackTrace, parameters.DispatcherCallerStack ) ?
         MakeReportText( attr, parameters, true ) :
         null;
   int? terminationCode = attr.DefaultTerminationCode;
   if ( attr.EmergencyCallback != null )
      try {
         attr.EmergencyCallback( attr, reportText, reportTextWithStack, ref terminationCode );
      } catch ( Exception e ) {
         TraceError(
            "=== EmergencyCallback has failed: ===\n"+
            MakeExceptionText( e, true ) );
      }
   return terminationCode;
}

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

[u.doesnt_return]
[MethodImpl( MethodImplOptions.NoInlining )]
public static void ProcessUnhandledException( Exception? e )
{
   var cfg = fatal.Settings;
   string causeOrCategory = cfg.MainThread != null ?
      cfg.MainThread == Thread.CurrentThread ?
         "Unhandled exception has occured in main program thread." :
         "Unhandled exception has occured in secondary program thread." :
      "Unhandled exception has occured in the program.";
   if ( e != null )
      fatal.RaiseError( causeOrCategory, e );
   else
      fatal.RaiseError( causeOrCategory,
         "Exception object of unhandled exception event arguments is not of "+
         "“System.Exception” type." );
   u.assertion_fail.DEAD_BRANCH();
}

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

[u.doesnt_return]
[MethodImpl( MethodImplOptions.NoInlining )]
internal static void AppDomainUnhandledException_Handler( object sender,
                                                          UnhandledExceptionEventArgs ea ) =>
   ProcessUnhandledException( ea.ExceptionObject as Exception );

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} // fatal_impl

} // user_rtx (.wasm)
