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

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

//**************************************************************************************************
public static partial class HArray {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

public static T[] Concatenate<T>(params T[][] arrays)
{
   HArgChecking.VerifyNotNulls( arrays );
   int length = 0;
   foreach (T[] array in arrays)
      length += array.Length;
   T[] result = new T[ length ];
   int count = 0;
   foreach (T[] array in arrays)
   {
      int len = array.Length;
      array.CopyTo( result, result.GetLowerBound(0)+count );
      count += len;
   }
   return result;
}

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

public static T[] Append<T>(T[] array,params T[] values)
{
   return Concatenate( array, values );
}

public static void Append<T>(ref T[] array,params T[] values)
{
   HArgChecking.VerifyNotNull( array );
   HArgChecking.VerifyNotNull( values );

   if (values.Length>0)
      array = Append( array, values );
}

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

public static T[] Insert<T>(T[] array,int index,params T[] values)
{
   HArgChecking.VerifyNotNull( array );
   if (index!=array.GetUpperBound(0))
      HArrayArgChecking.VerifyIndex( array, index );
   HArgChecking.VerifyNotNull( values );

   int
      len          = array.Length,
      insLen       = values.Length,
      sumLen       = len + insLen,
      lb           = array.GetLowerBound(0),
      headElemCount= index - lb;
   var
      result = new T[ sumLen ];

   Array.Copy( array, result, headElemCount );
   values.CopyTo( result, lb+headElemCount );

   int remainedElemCount =
      sumLen-headElemCount-insLen;

   if (remainedElemCount>0)
      Array.Copy(
         array, lb+headElemCount,
         result, headElemCount+insLen,
         remainedElemCount );

   return result;
}

public static void Insert<T>(ref T[] array,int index,params T[] values)
{
   array = Insert( array, index, values );
}

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

public static T[] Prefix<T>(T[] array,T value)
{
   return Concatenate( new T[]{ value }, array );
}

public static void Prefix<T>(ref T[] array,T value)
{
   array = Prefix( array, value );
}

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

public static T[] Delete<T>(T[] array,int index)
{
   return Delete( array, index, 1 );
}

public static T[] Delete<T>(T[] array,int fromIdx,int count)
{
   HArgChecking.VerifyNotNull( array );
   HArrayArgChecking.VerifyIndex( array, fromIdx );
   if (count<0)
      throw new ArgumentOutOfRangeException();
   if (count==0)
      return array;
   HArrayArgChecking.VerifyIndex( array, fromIdx+count-1 );

   int
      lb           = array.GetLowerBound(0),
      headElemCount= fromIdx - lb,
      len          = array.Length;
   var
      result = new T[ len-1 ];

   Array.Copy( array, result,
               headElemCount );

   int remainedElemCount=
      len-headElemCount-1;

   if (remainedElemCount>0)
      Array.Copy(
         array, lb+headElemCount+1,
         result, headElemCount+1,
         remainedElemCount );

   return result;
}

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

public static void Delete<T>(ref T[] array,int index)
{
   array = Delete( array, index );
}

public static void Delete<T>(ref T[] array,int fromIdx,int count)
{
   array = Delete( array, fromIdx, count );
}

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

public static T[] Truncate<T>(T[] array,int fromIdx)
{
   HArgChecking.VerifyNotNull( array );
   HArrayArgChecking.VerifyIndex( array, fromIdx );
   return Delete( array, fromIdx,
      array.GetUpperBound(0)-fromIdx+1 );
}

public static void Truncate<T>(ref T[] array,int fromIdx)
{
   array = Truncate( array, fromIdx );
}

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

} // CommonHelpers (.WASM)
