using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Npoi.Mapper;

namespace JiaZhiQuan.Common.Utils.Extend {
    public static class DistinctExtensions {
        public static IEnumerable<T> Distinct<T, V>(this IEnumerable<T> source, Func<T, V> keySelector) => 
            source.Distinct(new CommonEqualityComparer<T, V>(keySelector));
    }

    public static class IEnumerableExtension {        

        public static List<T> BlockDeal<S, T>(this IEnumerable<S> source, Func<IEnumerable<S>, T> deal,
            int startBlockNum = 0, int blockSize = 100) {
            List<T> result = new List<T>();
            if (source == null || source.Count() == 0) return result;
            int startNum = startBlockNum * blockSize;
            int count = source.Count();
            while (startNum < count) {
                int size = count - startNum > blockSize ? blockSize : count - startNum;
                IEnumerable<S> dealList = source.Skip(startNum).Take(size);
                result.Add(deal(dealList));
                startNum += size;
            }
            return result;
        }

        public static async Task<List<T>> BlockDealAsync<S, T>(this IEnumerable<S> source, 
            Func<IEnumerable<S>, Task<T>> deal, int startBlockNum = 0, int blockSize = 100) {
            List<T> result = new List<T>();
            if (source == null || source.Count() == 0) return result;
            int startNum = startBlockNum * blockSize;
            int count = source.Count();
            while (startNum < count) {
                int size = count - startNum > blockSize ? blockSize : count - startNum;
                IEnumerable<S> dealList = source.Skip(startNum).Take(size);
                result.Add(await deal(dealList));
                startNum += size;
            }
            return result;
        }
    }

    public class CommonEqualityComparer<T, V> : IEqualityComparer<T> {
        private readonly Func<T, V> keySelector;

        public CommonEqualityComparer(Func<T, V> keySelector) {
            this.keySelector = keySelector;
        }

        public bool Equals(T x, T y) {
            return EqualityComparer<V>.Default.Equals(keySelector(x), keySelector(y));
        }

        public int GetHashCode(T obj) {
            return EqualityComparer<V>.Default.GetHashCode(keySelector(obj));
        }
    }
}
