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

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

//**************************************************************************************************
partial class HArray {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

public static bool Find<T>(T[] array,Predicate<T> match,out T element)
{
   return Find( array, match, null, null, false, out element );
}

public static bool Find<T>(T[] array,Predicate<T> match,int? startIdx,out T element)
{
   return Find( array, match, startIdx, null, false, out element );
}

public static bool Find<T>(T[] array,Predicate<T> match,int? startIdx,int? count,out T element)
{
   return Find( array, match, startIdx, count, false, out element );
}

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

public static bool FindLast<T>(T[] array, Predicate<T> match,out T element)
{
   return Find( array, match, null, null, true, out element );
}

public static bool FindLast<T>(T[] array,Predicate<T> match,int? startIdx,out T element)
{
   return Find( array, match, startIdx, null, true, out element );
}

public static bool FindLast<T>(T[] array,Predicate<T> match,int? startIdx,int? count,out T element)
{
   return Find( array, match, startIdx, count, true, out element );
}

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

public static int? FindIndex<T>(T[] array,Predicate<T> match)
{
   return FindIndex( array, match, null, null, false );
}

public static int? FindIndex<T>(T[] array,Predicate<T> match,int? startIdx)
{
   return FindIndex( array, match, startIdx, null, false );
}

public static int? FindIndex<T>(T[] array,Predicate<T> match,int? startIdx,int? count)
{
   return FindIndex( array, match, startIdx, count, false );
}

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

public static int? FindLastIndex<T>(T[] array,Predicate<T> match)
{
   return FindIndex( array, match, null, null, true );
}

public static int? FindLastIndex<T>(T[] array,Predicate<T> match,int? startIdx)
{
   return FindIndex( array, match, startIdx, null, true );
}

public static int? FindLastIndex<T>(T[] array,Predicate<T> match,int? startIdx,int? count)
{
   return FindIndex( array, match, startIdx, count, true );
}

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

public static T[] FindAll<T>(T[] array,Predicate<T> match)
{
   return FindAll( array, match, null, null, false );
}

public static T[] FindAll<T>(T[] array,Predicate<T> match,int? startIdx)
{
   return FindAll( array, match, startIdx, null, false );
}

public static T[] FindAll<T>(T[] array,Predicate<T> match,int? startIdx,int? count)
{
   return FindAll( array, match, startIdx, count, false );
}

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

public static T[] BackwardFindAll<T>(T[] array,Predicate<T> match)
{
   return FindAll( array, match, null, null, true );
}

public static T[] BackwardFindAll<T>(T[] array,Predicate<T> match,int? startIdx)
{
   return FindAll( array, match, startIdx, null, true );
}

public static T[] BackwardFindAll<T>(T[] array,Predicate<T> match,int? startIdx,int? count)
{
   return FindAll( array, match, startIdx, count, true );
}

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

static bool Find<T>( T[] array, Predicate<T> match,
                     int? startIdx, int? count, bool backwardScan,
                     out T element )
{
   int? idx=FindIndex(array,match,startIdx,count,backwardScan);
   if (idx!=null)
   {
      element=array[ idx.Value ];
      return true;
   }
   element=default(T);
   return false;
}

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

static int? FindIndex<T>( T[] array, Predicate<T> match,
                          int? startIdx, int? count, bool backwardScan )
{
   int? idx = null;
   ForEachEx
   (
      array,
      (HContinueEnumerationWithIndexCallback<T>)delegate (T element,int index)
      {
         if (match(element))
         {
            idx = index; return false;
         }
         return true;
      },
      startIdx, count, backwardScan
   );
   return idx;
}

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

static T[] FindAll<T>( T[] array, Predicate<T> match,
                       int? startIdx, int? count, bool backwardScan )
{
   HArgChecking.VerifyNotNull( match );

   var list = new List<T>();

   ForEachEx( array,
      delegate (T element){ list.Add( element ); },
      startIdx, count, backwardScan );

   return list.ToArray();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} // HArray
//**************************************************************************************************

} // CommonHelpers (.WASM)
