namespace adas_core.Domain.Utils;

/// <summary>
/// Provides static extension methods to augment the functionality of dictionary types.
/// </summary>
public static class DictionaryEx
{
    /// <summary>
    /// Retrieves the value associated with the specified key from the dictionary, or returns the provided default value if the key is not found.
    /// </summary>
    /// <param name="dict">The dictionary to search for the key.</param>
    /// <param name="key">The key whose associated value should be returned.</param>
    /// <param name="defaultValue">The value to return when the key is not present in the dictionary. Defaults to the default value of <typeparamref name="TV"/>.</param>
    /// <returns>The value associated with the key if found; otherwise, <paramref name="defaultValue"/>.</returns>
    public static TV? GetValue<TK, TV>(this IDictionary<TK, TV> dict, TK key, TV? defaultValue = default)
        {
            return dict.TryGetValue(key, out var value) ? value : defaultValue;
        }

    /// <summary>
    /// Converts a dictionary into a formatted string by joining each key-value pair with a key separator and concatenating all pairs with an item separator.
    /// </summary>
    /// <param name="dict">The source dictionary whose entries will be converted to a string.</param>
    /// <param name="itemSeparator">The separator placed between each formatted key-value pair in the resulting string.</param>
    /// <param name="keySeparator">The separator placed between a key and its corresponding value within each pair.</param>
    /// <returns>A single string containing all dictionary entries formatted and joined using the specified separators.</returns>
    public static string ToListString<TK, TV>(this IDictionary<TK, TV> dict, string itemSeparator = ", ",
            string keySeparator = ": ")
        {
            var s = dict.Keys.Select(key => key + keySeparator + dict[key]).ToList();
    
            return string.Join(itemSeparator, s);
        }

    /// <summary>
    /// Attempts to retrieve the value associated with the specified key from the dictionary, returning null if the key is not found.
    /// </summary>
    /// <param name="dictionary">The dictionary to search for the key.</param>
    /// <param name="key">The key whose associated value should be retrieved.</param>
    /// <returns>The value associated with the key, or null if the key was not found in the dictionary.</returns>
    public static TValue? TryGetAndReturn<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key)
            where TKey : notnull where TValue : class
        {
            if (!dictionary.TryGetValue(key, out var retValue)) retValue = null;
            return retValue;
        }
}