//\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
// AFXUI auxiliary module for Blazor-application (WASM) | Author: Sergei Y.Kitáev
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;

using CommonHelpers.WASM;

namespace AFXUI {

//**************************************************************************************************
static partial class UCircuit {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

public static bool IsEscapeRequested { get; private set; }

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

public static void SetEscapeRequested()
{
   IsEscapeRequested = true;
   UCircuit.CancelExclusiveOperation();
}
public static void ResetEscapeRequested() =>
   IsEscapeRequested = false;

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

/// <exception cref="ArgumentNullException" />
/// <exception cref="UEscapeException" />
public static void ESC_Check( Type methodType,
                              [CallerMemberName][HRequired] string? methodNameOrSignature=null ) =>
   ESC_Check( methodType.Name, methodNameOrSignature );

/// <exception cref="ArgumentNullException" />
/// <exception cref="UEscapeExceptionTN" />
public static void ESC_Check( string methodTypeName,
                              [CallerMemberName][HRequired] string? methodNameOrSignature=null )
{
   if ( IsEscapeRequested )
      throw new UEscapeExceptionTN( methodTypeName,
         HArgChecking.NN( methodNameOrSignature ) );
}

/// <exception cref="ArgumentNullException" />
/// <exception cref="UEscapeException" />
public static void ESC_Check([HRequired] MethodBase? method)
{
   if ( IsEscapeRequested )
      throw new UEscapeException( method );
}

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

/// <exception cref="UEscapeException" />
public static Task ESC_WaitFor_A( Type methodType,
                                  Func<bool> condition,
                                  [CallerMemberName][HRequired]
                                  string? methodNameOrSignature=null ) =>
   ESC_WaitFor_A( methodType.Name, condition, methodNameOrSignature );

/// <exception cref="UEscapeException" />
public static async Task ESC_WaitFor_A( string methodTypeName,
                                        Func<bool> condition,
                                        [CallerMemberName][HRequired]
                                        string? methodNameOrSignature=null ) =>
   await HAsyncAwait.WaitFor_A(PollInterval,()=>{
      ESC_Check( methodTypeName, methodNameOrSignature );
      return condition();
   });

/// <exception cref="ArgumentNullException" />
/// <exception cref="UEscapeException" />
public static Task ESC_WaitFor_A( [HRequired] MethodBase? method, Func<bool> condition)
{
   method = HArgChecking.NN( method );
   return ESC_WaitFor_A( method.DeclaringType.NN(), condition, method.Name );
}

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

/// <exception cref="ArgumentOutOfRangeException" />
/// <exception cref="InvalidOperationException" />
/// <exception cref="UEscapeException" />
public static Task ESC_WaitExclusiveInterception( int level, Type methodType,
                                                  [CallerMemberName][HRequired]
                                                  string? methodNameOrSignature=null ) =>
   ESC_WaitExclusiveInterception( level, methodType.Name, methodNameOrSignature );

/// <exception cref="ArgumentOutOfRangeException" />
/// <exception cref="InvalidOperationException" />
/// <exception cref="UEscapeException" />
public static async Task ESC_WaitExclusiveInterception( int level, string methodTypeName,
                                                        [CallerMemberName][HRequired]
                                                        string? methodNameOrSignature=null )
{
   HArgChecking.VerifyNotNull( methodNameOrSignature );
   var context = StrictExclusiveContextAt( level );
   context.AwaitInterception = true;
   Trace(0, "* Awaiting interception in: [{0}] {1} ...",
      methodTypeName, methodNameOrSignature );
   await ESC_WaitFor_A( methodTypeName, () => context.Intercepted, methodNameOrSignature );
   Trace(0, "* Interception has been awaited in: [{0}] {1}.",
      methodTypeName, methodNameOrSignature );
}

/// <exception cref="ArgumentNullException" />
/// <exception cref="ArgumentOutOfRangeException" />
/// <exception cref="InvalidOperationException" />
/// <exception cref="UEscapeException" />
public static Task ESC_WaitExclusiveInterception( int level, [HRequired] MethodBase? method )
{
   method = HArgChecking.NN( method );
   return ESC_WaitExclusiveInterception( level, method.DeclaringType.NN(), method.Name );
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} // UCircuit
//**************************************************************************************************

} // AFXUI
