//\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
// CommonHelpers satellite library | Author: Sergei Y.Kitáev
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#nullable enable
using System;
using System.Collections.Generic;

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

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

/// <exception cref="ArgumentNullException" />
public static T FirstOrNull<T>(IEnumerable<T> collection)
where T: class =>
   FirstOrDefaultUnsafe( collection );
/// <exception cref="ArgumentNullException" />
public static T? FirstOrDefault<T>(IEnumerable<T?> collection)
where T: struct =>
   FirstOrDefaultUnsafe( collection );

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

/// <exception cref="ArgumentNullException" />
public static T SecondOrNull<T>(IEnumerable<T> collection)
where T: class =>
   SecondOrDefaultUnsafe( collection );
/// <exception cref="ArgumentNullException" />
public static T? SecondOrDefault<T>(IEnumerable<T?> collection)
where T: struct =>
   SecondOrDefaultUnsafe( collection );

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

public static T FirstOrDefaultUnsafe<T>(IEnumerable<T> collection)
{
   HArgChecking.VerifyNotNull( collection );
   var enumerator = collection.GetEnumerator();
   try
   {
      return enumerator.MoveNext() ? enumerator.Current : default(T)!;
   }
   finally
   {
      if (enumerator is IDisposable)
         ((IDisposable)enumerator).Dispose();
   }
}

public static T SecondOrDefaultUnsafe<T>(IEnumerable<T> collection)
{
   HArgChecking.VerifyNotNull( collection );
   var enumerator = collection.GetEnumerator();
   try
   {
      return enumerator.MoveNext() && enumerator.MoveNext() ?
         enumerator.Current : default(T)!;
   }
   finally
   {
      if (enumerator is IDisposable)
         ((IDisposable)enumerator).Dispose();
   }
}

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

[HOptionalThroughMinusOne]
public static int FindIndex<T>(IEnumerable<T> collection,Predicate<T> predicate)
{
   HArgChecking.VerifyNotNull( collection );
   var enumerator = collection.GetEnumerator();
   try
   {
      int idx = -1;
      while ( enumerator.MoveNext() )
      {
         idx++;
         if ( predicate( enumerator.Current ) )
            return idx;
      }
      return -1;
   }
   finally
   {
      if (enumerator is IDisposable)
         ((IDisposable)enumerator).Dispose();
   }
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} // HCollection
//**************************************************************************************************

} // CommonHelpers (.WASM)
