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

#if !WASM
namespace user_rtx { using u = user_rtx;
#else
namespace user_rtx.wasm { using u = user_rtx.wasm;
#endif

/// <summary>
/// String support
/// </summary>
public static partial class str {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

/// <summary>
/// Wrapper of “System.String.IsNullOrWhiteSpace” (simply shorter name)
/// </summary>
/// <remarks>
/// Sometimes IsNullOrWhiteSpace is better in aspect of nullable warnings, because it is integrated with C# compiler.
/// </remarks>
public static bool IsNLWS( string? str ) =>
   string.IsNullOrWhiteSpace( str );

/// <summary>
/// Checking for whitespace and not null (is based on “System.String.IsNullOrWhiteSpace”)
/// </summary>
/// <remarks>
/// Sometimes “System.String.IsNullOrWhiteSpace” is better in aspect of nullable warnings, because it is integrated with C# compiler.
/// </remarks>
/// <exception cref="ArgumentNullException" />
public static bool IsWS( string str ) =>
   IsNLWS( u.arg_check.NN( str, nameof(str) ) );

/// <summary>
/// Checking for whitespace and not null (is based on “System.String.IsNullOrWhiteSpace”)
/// </summary>
/// <remarks>
/// Sometimes “System.String.IsNullOrWhiteSpace” is better in aspect of nullable warnings, because it is integrated with C# compiler.
/// </remarks>
public static bool IsWSNN( string? str ) =>
   str != null && IsNLWS( str );

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

public static bool Equals( string? str_1, string? str_2 ) =>
   Equals( str_1, str_2, false );

public static bool Equals( string? str_1, string? str_2, bool ignoreCase ) =>
   CompareOrdinal( str_1, str_2, ignoreCase ) == 0;

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

public static int CompareOrdinal( string? str_1, string? str_2 ) =>
   CompareOrdinal( str_1, str_2, false );

public static int CompareOrdinal( string? str_1, string? str_2, bool ignoreCase ) =>
   string.Compare( str_1, str_2, ignoreCase ?
      StringComparison.OrdinalIgnoreCase :
      StringComparison.Ordinal );

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

public static int CompareInvariant( string? str_1, string? str_2 ) =>
   CompareInvariant( str_1, str_2, false );

public static int CompareInvariant( string? str_1, string? str_2, bool ignoreCase ) =>
   string.Compare( str_1, str_2, ignoreCase ?
      StringComparison.InvariantCultureIgnoreCase :
      StringComparison.InvariantCulture );

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

public static int CompareCC( string? str_1, string? str_2 ) =>
   CompareCC( str_1, str_2, false );

public static int CompareCC( string? str_1, string? str_2, bool ignoreCase ) =>
   string.Compare( str_1, str_2, ignoreCase ?
      StringComparison.CurrentCultureIgnoreCase :
      StringComparison.CurrentCulture );

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

public static string Join( char separator, params string[] values ) =>
   Join( separator.ToString(), values );

public static string JoinN( char separator, params string?[] values ) =>
   JoinN( separator.ToString(), values );

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

public static string Join( string separator, params string[] values )
{
   var sb = new StringBuilder();
   for ( int i=0; i<values.Length; i++ ) {
      if ( i > 0 )
         sb.Append( separator );
      sb.Append( values[ i ] );
   }
   return sb.ToString();
}

public static string JoinN( string separator, params string?[] values )
{
   var sb = new StringBuilder();
   for ( int i=0; i<values.Length; i++ ) {
      if ( i > 0 )
         sb.Append( separator );
      string? value = values[ i ];
      if ( value != null )
         sb.Append( value );
   }
   return sb.ToString();
}

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

/// <exception cref="ArgumentOutOfRangeException" />
public static string Repeat( string str, int count )
{
   u.arg_check.NotNegative( count, nameof(count) );
   var sb = new StringBuilder();
   for ( int i=0; i<count; i++ )
      sb.Append( str );
   return sb.ToString();
}

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

/// <exception cref="ArgumentException" />
[u.strict_result]
public static char StrictHeadChar( [u.not_empty] string str ) =>
   HeadCharOrNull( str ) ?? throw new ArgumentException(
      "Can not extract head character from empty string." );

public static char? HeadCharOrNull( string str ) =>
   str != "" ? str[ 0 ] : (char?)null;

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

/// <exception cref="ArgumentException" />
[u.strict_result]
public static char StrictLastChar( [u.not_empty] string str ) =>
   LastCharOrNull( str ) ?? throw new ArgumentException(
      "Can not extract last character from empty string." );

public static char? LastCharOrNull( string str ) =>
   str != "" ? str[ str.Length-1 ] : (char?)null;

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

public static string Or( string? str, params string?[] substs )
{
   if ( !string.IsNullOrEmpty( str ) )
      return str;
   foreach ( string? s in substs )
      if ( !string.IsNullOrEmpty( s ) )
         return s;
   return "";
}
public static string WSOr( string? str, params string?[] substs )
{
   if ( !string.IsNullOrWhiteSpace( str ) )
      return str;
   foreach ( string? s in substs )
      if ( !string.IsNullOrWhiteSpace( s ) )
         return s;
   return "";
}

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

public static string? EmptyAsNull( string? str ) =>
   str == "" ? null : str;

public static string? WSAsNull( string? str ) =>
   IsNLWS( str ) ? null : str;

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

public static string Trim( ref string str ) =>
   str = str.Trim();

public static string TrimStart( ref string str ) =>
   str = str.TrimStart();

public static string TrimEnd( ref string str ) =>
   str = str.TrimEnd();

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

public static string NullAsEmpty( ref string? str )
{
   str ??= ""; return str;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} // str

} // user_rtx (.wasm)
