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

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

//**************************************************************************************************
public delegate bool HOverwriteExitCodeCallback(int oldValue,int newValue);
//**************************************************************************************************


//**************************************************************************************************
partial class HProgram {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

public const int
   SuccessfulExitCodeDefault =  0,
   FailureExitCodeDefault    =  1,
   BreakdownExitCodeDefault  = -1;

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

[DefaultValue(SuccessfulExitCodeDefault)]
public static int SuccessfulExitCode
{
   get { return _SuccessfulExitCode_; }
   set { lock (_SyncRoot_) _SuccessfulExitCode_ = value; }
}

[DefaultValue(FailureExitCodeDefault)]
public static int FailureExitCode
{
   get { return _FailureExitCode_; }
   set { lock (_SyncRoot_) _FailureExitCode_ = value; }
}

[DefaultValue(BreakdownExitCodeDefault)]
public static int BreakdownExitCode
{
   get { return _BreakdownExitCode_; }
   set { lock (_SyncRoot_) _BreakdownExitCode_ = value; }
}

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

public static HOverwriteExitCodeCallback OverwriteExitCodeCallback
{
   get { return _OverwriteExitCodeCallback_; }
   set { lock (_SyncRoot_) _OverwriteExitCodeCallback_ = value; }
}

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

/// <exception cref="HOperationFailedException" />
public static int ExitCode
{
   get
   {
      return _ExitCode_;
   }
   set
   {
      lock (_ExitSyncObject_)
         if (value!=_ExitCode_)
         {
            _ExitCode_ = value;
            if (!HAppDomain.IsInDefaultAppDomain)
               throw new HOperationFailedException(
                  "Can not set program exit code in non-default application domain." );
            Environment.ExitCode = _ExitCode_;
         }
   }
}

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

public static void SetSuccessfulExitCode()
{
   ExitCode = SuccessfulExitCode;
}

public static void SetFailureExitCode()
{
   ExitCode = FailureExitCode;
}

public static void SetBreakdownExitCode()
{
   ExitCode = BreakdownExitCode;
}

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

public static bool OverwriteExitCode(int value)
{
   lock (_ExitSyncObject_)
   {
      var overwriteCallback =
         _OverwriteExitCodeCallback_;
      if ( overwriteCallback!=null && overwriteCallback(_ExitCode_,value) ||
           overwriteCallback==null && value!=_ExitCode_ )
      {
         ExitCode = value;
         return true;
      }
      return false;
   }
}

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

public static int PrepareToExit()
{
   return PrepareToExit(_ExitCode_);
}

public static int PrepareToExit(int exitCode)
{
   if ( HAppDomain.IsInDefaultAppDomain )
      ExitCode = exitCode;
   HGC.CollectAndWait();
   return exitCode;
}

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

static volatile int
   _SuccessfulExitCode_ = SuccessfulExitCodeDefault,
   _FailureExitCode_    = FailureExitCodeDefault,
   _BreakdownExitCode_  = BreakdownExitCodeDefault,
   _ExitCode_           = SuccessfulExitCodeDefault;

static volatile HOverwriteExitCodeCallback
   _OverwriteExitCodeCallback_;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} // HProgram
//**************************************************************************************************

} // CommonHelpers (.WASM)
