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

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

//**************************************************************************************************
[Flags]
public enum HEnumParsingOptions
{
   None=0, IgnoreCase=1, SoleValue=2
}
//**************************************************************************************************


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

/// <exception cref="HParseValueException" />
public static EnumType Parse<EnumType>(string src) where EnumType: struct
{
   return Parse<EnumType>(src,null);
}

/// <exception cref="HParseValueException" />
public static EnumType Parse<EnumType>(string src,HEnumParsingOptions options)
   where EnumType: struct
{
   return Parse<EnumType>(src,null,options);
}

/// <exception cref="HParseValueException" />
public static EnumType Parse<EnumType>(string src,EnumType def)
   where EnumType: struct
{
   return Parse<EnumType>(src,null,def);
}

/// <exception cref="HParseValueException" />
public static EnumType Parse<EnumType>(string src,HEnumParsingOptions options,EnumType def)
   where EnumType: struct
{
   return Parse<EnumType>(src,null,options,def);
}

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

/// <exception cref="HParseValueException" />
public static EnumType Parse<EnumType>(string src,char? separator) where EnumType: struct
{
   return Parse<EnumType>(src,separator,HEnumParsingOptions.None,null);
}

/// <exception cref="HParseValueException" />
public static EnumType Parse<EnumType>(string src,char? separator,HEnumParsingOptions options)
   where EnumType: struct
{
   return Parse<EnumType>(src,separator,options,null);
}

/// <exception cref="HParseValueException" />
public static EnumType Parse<EnumType>(string src,char? separator,EnumType def)
   where EnumType: struct
{
   return Parse<EnumType>(src,separator,HEnumParsingOptions.None,def);
}

public static EnumType Parse<EnumType>( string src, char? separator,
                                        HEnumParsingOptions options, EnumType? def )
   where EnumType: struct
{
   Type type = typeof(EnumType);

   HGenericTypeChecking.VerifyEnum( type );
   HArgChecking.VerifyNotNull( src );

   string[] stringValues=HString.Split(src,separator ?? ',');

   if (stringValues.Length==0)
      if (def!=null)
         return def.Value;
      else
         throw new ArgumentException(
            "Enumeration value string is empty." );

   if (stringValues.Length>1)
   {
      if (!IsFlagsEnumeration(type))
         throw new ArgumentException(
            "Flags attribute is required for multiple enumeration value." );
      if ((options & HEnumParsingOptions.SoleValue)!=0)
         throw new ArgumentException(
            "Sole value was expected for enumeration." );
   }

   var list = new List<string>();
   var sb = new StringBuilder();

   foreach (string stringValue in stringValues)
   {
      try
      {
         Enum.Parse( type, stringValue,
            (options & HEnumParsingOptions.IgnoreCase)!=0 );
      }
      catch (ArgumentException e)
      {
         throw new HParseValueException( e.Message );
      }

      foreach (string str in list)
         if (HString.Equals( str, stringValue,
                            (options & HEnumParsingOptions.IgnoreCase)!=0 ))
            throw HParseValueExceptionCreator.Create(
               "Dulplicate flag for enumeration value: \"{0}\".",
               stringValue );

      if (list.Count!=0)
         sb.Append(',');
      sb.Append(stringValue);

      list.Add(stringValue);
   }

   try
   {
      return (EnumType)Enum.Parse( type, sb.ToString(),
         (options & HEnumParsingOptions.IgnoreCase)!=0 );
   }
   catch (ArgumentException e)
   {
      throw HOpFailedExceptionCreator.Create( e );
   }
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} // HEnum
//**************************************************************************************************

} // CommonHelpers (.WASM)
