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

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

//**************************************************************************************************
/// <summary>
/// </summary>
public static partial class HOps {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

public static Action Nop { get { return _Nop_; } }

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

public static bool TrueCondition([HOptional] object obj) => true;
public static bool FalseCondition([HOptional] object obj) => false;

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

public static void Repeat(int count,HRepeatCallback procedure)
{
   HArgChecking.VerifyNotNull( procedure );
   for (int i=0; i<count; i++)
      procedure();
}

public static void RepeatWithNo(int count,HRepeatWithNoCallback procedure)
{
   HArgChecking.VerifyNotNull( procedure );
   for (int no=1; no<=count; no++)
      procedure( no );
}

public static void RepeatWithIndex(int count,HRepeatWithIndexCallback procedure)
{
   HArgChecking.VerifyNotNull( procedure );
   for (int idx=0; idx<count; idx++)
      procedure( idx );
}

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

public static bool Repeat(int count,HContinueRepeatCallback procedure)
{
   HArgChecking.VerifyNotNull( procedure );
   for (int i=0; i<count; i++)
      if ( !procedure() ) return false;
   return true;
}

public static bool RepeatWithNo(int count,HContinueRepeatWithNoCallback procedure)
{
   HArgChecking.VerifyNotNull( procedure );
   for (int no=1; no<=count; no++)
      if ( !procedure( no ) ) return false;
   return true;
}

public static bool RepeatWithIndex(int count,HContinueRepeatWithIndexCallback procedure)
{
   HArgChecking.VerifyNotNull( procedure );
   for (int idx=0; idx<count; idx++)
      if ( !procedure( idx ) ) return false;
   return true;
}

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

public static bool IsOneOf([HOptional] object obj,params object[] objects)
{
   return IsOneOf((HEqualsCallback)null,obj,objects);
}

public static int IndexOf([HOptional] object obj,params object[] objects)
{
   return IndexOf((HEqualsCallback)null,obj,objects);
}

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

public static bool IsOneOf( [HOptional] HEqualsCallback equalsCallback,
                            [HOptional] object obj, params object[] objects )
{
   HArgChecking.VerifyNotNull( objects );
   return
      IndexOf(equalsCallback,obj,objects) !=
      HArray.NotFoundElementIndexOf( objects );
}

public static int IndexOf( [HOptional] HEqualsCallback equalsCallback,
                           [HOptional] object obj, params object[] objects )
{
   HArgChecking.VerifyNotNull( objects );
   for (int i=objects.GetLowerBound(0); i<=objects.GetUpperBound(0); i++)
      if ( equalsCallback!=null ?
           equalsCallback(obj,objects[i]) : object.Equals(obj,objects[i]) )
         return i;
   return HArray.NotFoundElementIndexOf( objects );
}

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

public static int StrictIndexOf([HOptional] object obj,params object[] objects)
{
   return StrictIndexOf((HEqualsCallback)null,obj,objects);
}

public static int StrictIndexOf( [HOptional] HEqualsCallback equalsCallback,
                                 [HOptional] object obj, params object[] objects )
{
   int idx = IndexOf(equalsCallback,obj,objects);
   if ( idx == HArray.NotFoundElementIndexOf( objects ) )
      throw new HElementNotFoundException();
   return idx;
}

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

/// <exception cref="ArgumentNullException" />
public static bool CheckNotNulls(params object[] objects)
{
   HArgChecking.VerifyNotNull( objects );
   foreach (object obj in objects)
      if ( obj == null )
         return false;
   return true;
}

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

/// <exception cref="ArgumentNullException" />
public static bool CheckNotZeroPointers(params IntPtr[] pointers)
{
   HArgChecking.VerifyNotNull( pointers );
   foreach (IntPtr ptr in pointers)
      if ( ptr == IntPtr.Zero )
         return false;
   return true;
}
/// <exception cref="ArgumentNullException" />
[CLSCompliant(false)]
public static bool CheckNotZeroPointers(params UIntPtr[] pointers)
{
   HArgChecking.VerifyNotNull( pointers );
   foreach (UIntPtr ptr in pointers)
      if ( ptr == UIntPtr.Zero )
         return false;
   return true;
}

/// <exception cref="ArgumentNullException" />
public static bool CheckNotInvalidPointers(params IntPtr[] pointers)
{
   HArgChecking.VerifyNotNull( pointers );
   foreach (IntPtr ptr in pointers)
      if ( ptr == HIntPtr.MinusOneValue )
         return false;
   return true;
}
/// <exception cref="ArgumentNullException" />
[CLSCompliant(false)]
public static bool CheckNotInvalidPointers(params UIntPtr[] pointers)
{
   HArgChecking.VerifyNotNull( pointers );
   foreach (UIntPtr ptr in pointers)
      if ( ptr == HUIntPtr.AllBitsValue )
         return false;
   return true;
}

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

public static bool? IntToNullableBool(int value)
{
   switch ( value )
   {
   case 0: return false;
   case 1: return true;
   default: return null;
   }
}
public static bool? IntToNullableBool(int value,bool liberalVersion)
{
   return liberalVersion ?
      value < 0 ? (bool?)null : value > 0 :
      IntToNullableBool( value );
}

public static int NullableBoolToInt(bool? value)
{
   return value.HasValue ? value.Value ? 1 : 0 : -1;
}

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

/// <exception cref="ArgumentNullException" />
public static bool Try(Action operation)
{
   HArgChecking.VerifyNotNull( operation );
   try { operation(); }
   catch (Exception) { return false; }
   return true;
}
/// <exception cref="ArgumentNullException" />
public static bool Try(Action operation,out Exception error)
{
   HArgChecking.VerifyNotNull( operation );
   try { operation(); }
   catch (Exception e)
      { error = e; return false; }
   error = null; return true;
}
/// <exception cref="ArgumentNullException" />
public static bool Try(ref Exception err,Action action)
{
   HArgChecking.VerifyNotNull( action );
   try { action(); }
   catch (Exception e) {
      err ??= e;
      return false; }
   return true;
}

/// <exception cref="ArgumentNullException" />
[HOptionalResult]
public static Exception Catch(Action operation)
{
   HArgChecking.VerifyNotNull( operation );
   try { operation(); }
   catch (Exception e) { return e; }
   return null;
}

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

public static void DoIfNotNull(Action operation)
{
   if ( operation != null ) operation();
}

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

static HOps()
{
   CommonHelpers_Core.Access();
}

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

static readonly Action
   _Nop_ = delegate {};

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} // HOps
//**************************************************************************************************

} // CommonHelpers (.WASM)
