using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace IRaCIS.Core.Infrastructure.Extention
{
    public static class IDictionaryExtensions
    {
        /// 
        /// 添加或更新键值对
        /// 
        /// 
        /// 
        /// 
        /// 另一个字典集
        /// 
        public static void AddOrUpdate(this IDictionary @this, IDictionary that)
        {
            foreach (var item in that)
            {
                @this[item.Key] = item.Value;
            }
        }
        /// 
        /// 添加或更新键值对
        /// 
        /// 
        /// 
        /// 
        /// 另一个字典集
        /// 
        public static void AddOrUpdateTo(this IDictionary @this, IDictionary that)
        {
            foreach (var item in @this)
            {
                that[item.Key] = item.Value;
            }
        }
        /// 
        /// 添加或更新键值对
        /// 
        /// 
        /// 
        /// 
        /// 键
        /// 添加时的值
        /// 更新时的操作
        /// 
        public static TValue AddOrUpdate(this IDictionary @this, TKey key, TValue addValue, Func updateValueFactory)
        {
            if (!@this.ContainsKey(key))
            {
                @this.Add(key, addValue);
            }
            else
            {
                @this[key] = updateValueFactory(key, @this[key]);
            }
            return @this[key];
        }
        /// 
        /// 添加或更新键值对
        /// 
        /// 
        /// 
        /// 
        /// 键
        /// 添加时的值
        /// 更新时的操作
        /// 
        public static async Task AddOrUpdateAsync(this IDictionary @this, TKey key, TValue addValue, Func> updateValueFactory)
        {
            if (!@this.ContainsKey(key))
            {
                @this.Add(key, addValue);
            }
            else
            {
                @this[key] = await updateValueFactory(key, @this[key]);
            }
            return @this[key];
        }
        /// 
        /// 添加或更新键值对
        /// 
        /// 
        /// 
        /// 
        /// 键
        /// 添加时的值
        /// 更新时的值
        /// 
        public static TValue AddOrUpdate(this IDictionary @this, TKey key, TValue addValue, TValue updateValue)
        {
            if (!@this.ContainsKey(key))
            {
                @this.Add(key, addValue);
            }
            else
            {
                @this[key] = updateValue;
            }
            return @this[key];
        }
        /// 
        /// 添加或更新键值对
        /// 
        /// 
        /// 
        /// 
        /// 另一个字典集
        /// 更新时的操作
        /// 
        public static void AddOrUpdate(this IDictionary @this, IDictionary that, Func updateValueFactory)
        {
            foreach (var item in that)
            {
                AddOrUpdate(@this, item.Key, item.Value, updateValueFactory);
            }
        }
        /// 
        /// 添加或更新键值对
        /// 
        /// 
        /// 
        /// 
        /// 另一个字典集
        /// 更新时的操作
        /// 
        public static Task AddOrUpdateAsync(this IDictionary @this, IDictionary that, Func> updateValueFactory)
        {
            return that.ForeachAsync(item => AddOrUpdateAsync(@this, item.Key, item.Value, updateValueFactory));
        }
        /// 
        /// 添加或更新键值对
        /// 
        /// 
        /// 
        /// 
        /// 另一个字典集
        /// 更新时的操作
        /// 
        public static void AddOrUpdateTo(this IDictionary @this, IDictionary that, Func updateValueFactory)
        {
            foreach (var item in @this)
            {
                AddOrUpdate(that, item.Key, item.Value, updateValueFactory);
            }
        }
        /// 
        /// 添加或更新键值对
        /// 
        /// 
        /// 
        /// 
        /// 另一个字典集
        /// 更新时的操作
        /// 
        public static Task AddOrUpdateAsyncTo(this IDictionary @this, IDictionary that, Func> updateValueFactory)
        {
            return @this.ForeachAsync(item => AddOrUpdateAsync(that, item.Key, item.Value, updateValueFactory));
        }
        /// 
        /// 添加或更新键值对
        /// 
        /// 
        /// 
        /// 
        /// 键
        /// 添加时的操作
        /// 更新时的操作
        /// 
        public static TValue AddOrUpdate(this IDictionary @this, TKey key, Func addValueFactory, Func updateValueFactory)
        {
            if (!@this.ContainsKey(key))
            {
                @this.Add(key, addValueFactory(key));
            }
            else
            {
                @this[key] = updateValueFactory(key, @this[key]);
            }
            return @this[key];
        }
        /// 
        /// 添加或更新键值对
        /// 
        /// 
        /// 
        /// 
        /// 键
        /// 添加时的操作
        /// 更新时的操作
        /// 
        public static async Task AddOrUpdateAsync(this IDictionary @this, TKey key, Func> addValueFactory, Func> updateValueFactory)
        {
            if (!@this.ContainsKey(key))
            {
                @this.Add(key, await addValueFactory(key));
            }
            else
            {
                @this[key] = await updateValueFactory(key, @this[key]);
            }
            return @this[key];
        }
        /// 
        /// 获取或添加
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        public static TValue GetOrAdd(this IDictionary @this, TKey key, Func addValueFactory)
        {
            if (!@this.ContainsKey(key))
            {
                @this.Add(key, addValueFactory());
            }
            return @this[key];
        }
        /// 
        /// 获取或添加
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        public static async Task GetOrAddAsync(this IDictionary @this, TKey key, Func> addValueFactory)
        {
            if (!@this.ContainsKey(key))
            {
                @this.Add(key, await addValueFactory());
            }
            return @this[key];
        }
        /// 
        /// 获取或添加
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        public static TValue GetOrAdd(this IDictionary @this, TKey key, TValue addValue)
        {
            if (!@this.ContainsKey(key))
            {
                @this.Add(key, addValue);
            }
            return @this[key];
        }
        /// 
        /// 遍历IEnumerable
        /// 
        /// 
        /// 回调方法
        public static void ForEach(this IDictionary dic, Action action)
        {
            foreach (var item in dic)
            {
                action(item.Key, item.Value);
            }
        }
        /// 
        /// 遍历IDictionary
        /// 
        /// 
        /// 回调方法
        public static Task ForEachAsync(this IDictionary dic, Func action)
        {
            return dic.ForeachAsync(x => action(x.Key, x.Value));
        }
        /// 
        /// 安全的转换成字典集
        /// 
        /// 
        /// 
        /// 
        /// 键选择器
        /// 
        public static Dictionary ToDictionarySafety(this IEnumerable source, Func keySelector)
        {
            var dic = new Dictionary();
            foreach (var item in source)
            {
                dic[keySelector(item)] = item;
            }
            return dic;
        }
        /// 
        /// 安全的转换成字典集
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 键选择器
        /// 值选择器
        /// 
        public static Dictionary ToDictionarySafety(this IEnumerable source, Func keySelector, Func elementSelector)
        {
            var dic = new Dictionary();
            foreach (var item in source)
            {
                dic[keySelector(item)] = elementSelector(item);
            }
            return dic;
        }
        /// 
        /// 安全的转换成字典集
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 键选择器
        /// 值选择器
        /// 
        public static async Task> ToDictionarySafetyAsync(this IEnumerable source, Func keySelector, Func> elementSelector)
        {
            var dic = new ConcurrentDictionary();
            await source.ForeachAsync(async item => dic[keySelector(item)] = await elementSelector(item));
            return dic;
        }
        /// 
        /// 安全的转换成字典集
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 键选择器
        /// 
        public static ConcurrentDictionary ToConcurrentDictionary(this IEnumerable source, Func keySelector)
        {
            var dic = new ConcurrentDictionary();
            foreach (var item in source)
            {
                dic[keySelector(item)] = item;
            }
            return dic;
        }
        /// 
        /// 安全的转换成字典集
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 键选择器
        /// 值选择器
        /// 
        public static ConcurrentDictionary ToConcurrentDictionary(this IEnumerable source, Func keySelector, Func elementSelector)
        {
            var dic = new ConcurrentDictionary();
            foreach (var item in source)
            {
                dic[keySelector(item)] = elementSelector(item);
            }
            return dic;
        }
        /// 
        /// 安全的转换成字典集
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 键选择器
        /// 值选择器
        /// 
        public static async Task> ToConcurrentDictionaryAsync(this IEnumerable source, Func keySelector, Func> elementSelector)
        {
            var dic = new ConcurrentDictionary();
            await source.ForeachAsync(async item => dic[keySelector(item)] = await elementSelector(item));
            return dic;
        }
        /// 
        /// 转换成并发字典集合
        /// 
        /// 
        /// 
        /// 
        /// 
        public static ConcurrentDictionary AsConcurrentDictionary(this Dictionary dic) => new(dic);
        /// 
        /// 转换成普通字典集合
        /// 
        /// 
        /// 
        /// 
        /// 
        public static Dictionary AsDictionary(this ConcurrentDictionary dic) => new(dic);
    }
}