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

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

//**************************************************************************************************
/// <summary>
/// </summary>
partial class DictionaryWrapper<TKey,TValue>: Dictionary<TKey,TValue> {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

[HOptionalValue]
public new TValue this[TKey key]
{
   get
   {
      TValue value;
      base.TryGetValue( key, out value );
      return value;
   }
   set
   {
      base[ key ] = value;
   }
}

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

public DictionaryWrapper()
{}

public DictionaryWrapper(IEqualityComparer<TKey> comparer)
   :base ( comparer )
{}

public DictionaryWrapper(IDictionary<TKey,TValue> initialContent)
   :base ( initialContent )
{}
public DictionaryWrapper(IDictionary<TKey,TValue> initialContent,IEqualityComparer<TKey> comparer)
   :base ( initialContent, comparer )
{}

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

/// <exception cref="KeyNotFoundException" />
public TValue StrictGetValue(TKey key)
{
   return base[ key ];
}

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

/// <exception cref="HGenericTypeException" />
public List<TKey> GetKeyList(bool ordered)
{
   if ( ordered && !HType.ImplementsInterface<IComparable>( typeof(TKey) ) )
      throw HGenericTypeExceptionCreator.Create(
         "Dictionary key type \"{0}\" is not subclass of \"IComparable\" interface.",
         typeof(TKey) );
   var keys = new List<TKey>( Count );
   foreach (TKey key in Keys)
      keys.Add( key );
   if ( ordered )
      keys.Sort( (TKey k1,TKey k2) => ((IComparable)k1).CompareTo( k2 ) );
   return keys;
}

/// <exception cref="HGenericTypeException" />
public List<TValue> GetValueList(bool orderedByKey)
{
   var values = new List<TValue>( Count );
   if ( orderedByKey )
      foreach (var keyValuePair in ToList(true))
         values.Add( keyValuePair.Value );
   else
      foreach (TValue value in Values)
         values.Add( value );
   return values;
}

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

/// <exception cref="HGenericTypeException" />
public List<TValue> GetOrderedValueList()
{
   if ( !HType.ImplementsInterface<IComparable>( typeof(TValue) ) )
      throw HGenericTypeExceptionCreator.Create(
         "Dictionary value type \"{0}\" is not subclass of \"IComparable\" interface.",
         typeof(TValue) );
   var values = GetValueList( true );
   values.Sort( (TValue v1,TValue v2) => ((IComparable)v1).CompareTo( v2 ) );
   return values;
}

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

public KeyValuePair<TKey,TValue>[] ToArray(bool orderedByKey)
{
   return ToList( orderedByKey ).ToArray();
}

public KeyValuePair<TKey,TValue>[] ToArray([HOptional] Comparison<TKey> keyComparison)
{
   return ToList( keyComparison ).ToArray();
}

public KeyValuePair<TKey,TValue>[] ToArray([HOptional] IComparer<TKey> keyComparer)
{
   return ToList( keyComparer ).ToArray();
}

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

public List<KeyValuePair<TKey,TValue>> ToList(bool orderedByKey)
{
   Comparison<TKey> keyComparison = null;
   if ( orderedByKey && typeof(IComparable).IsAssignableFrom( typeof(TKey) ) )
      keyComparison = (TKey k1,TKey k2) => ((IComparable)k1).CompareTo( k2 );
   return ToList( keyComparison );
}

public List<KeyValuePair<TKey,TValue>> ToList([HOptional] Comparison<TKey> keyComparison)
{
   var list = new List<KeyValuePair<TKey,TValue>>( Count );
   foreach (var keyValuePair in this)
      list.Add( keyValuePair );
   if ( keyComparison != null )
      list.Sort( (KeyValuePair<TKey,TValue> r1,KeyValuePair<TKey,TValue> r2) =>
         keyComparison( r1.Key, r2.Key ) );
   return list;
}

public List<KeyValuePair<TKey,TValue>> ToList([HOptional] IComparer<TKey> keyComparer)
{
   return ToList( keyComparer != null ?
      (TKey k1,TKey k2) => keyComparer.Compare( k1, k2 ) :
      (Comparison<TKey>)null );
}

public List<KeyValuePair<TKey,TValue>> ToList([HOptional] IComparer keyComparer)
{
   return ToList( keyComparer != null ?
      (TKey k1,TKey k2) => keyComparer.Compare( k1, k2 ) :
      (Comparison<TKey>)null );
}

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

public void AddKeyValuePair(KeyValuePair<TKey,TValue> keyValuePair)
{
   HArgChecking.VerifyNotNull( keyValuePair );
   Add( keyValuePair.Key, keyValuePair.Value );
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} // DictionaryWrapper<TKey,TValue>
//**************************************************************************************************

} // CommonHelpers (.WASM)
