using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ExtensionMethods {
  public static class IEquatableExtensions {
    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="item1"></param>
    /// <param name="item2"></param>
    /// <returns></returns>
    public static bool Eq<T>(this IEquatable<T>? item1, T? item2) {
      if ((item1 == null && item2 != null) || (item1 != null && item2 == null))
        return false;

      if (item1 == null && item2 == null)
        return true;

      if (item1 != null && item2 != null) {
        var result = item1.Equals(item2);

        return result;
      }

      return false;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="list1"></param>
    /// <param name="list2"></param>
    /// <returns></returns>
    public static bool EnumerableEq<T>(this IEnumerable<IEquatable<T>>? list1, IEnumerable<IEquatable<T>>? list2) {
      if ((list1 == null && list2 != null) || (list1 != null && list2 == null))
        return false;

      if (list1 == null && list2 == null)
        return true;

      if (list1 != null && list2 != null && list1.Count() == list2.Count()) {

        var diffDic = list2.GroupBy(x => x.GetHashCode()).ToDictionary(g => g.Key, g => g.Count());

        for (int i = 0; i < list1.Count(); i++) {
          var obj = (T)list1.ElementAt(i);
          var objHash = obj.GetHashCode();

          if (diffDic.ContainsKey(objHash))
            diffDic[objHash] = diffDic[objHash] - 1;
          else
            diffDic.Add(objHash, -1);
        }

        return !diffDic.Any(x => x.Value != 0);
      }

      return false;
    }
  }
}
