﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Text;

#pragma warning disable 419  // Ambigious cref in XML comment

namespace Hydra.Framework.Collections
{
    /// <summary>
    /// A private class used to implement GetSetEqualityComparer(). This
    /// class implements IEqualityComparer&lt;IEnumerable&lt;T&gt;gt; to compare
    /// two enumerables for equality, where order is not significant.
    /// </summary>
    [Serializable]
    public class SetEqualityComparer<T>
        : IEqualityComparer<IEnumerable<T>>
    {
        #region Member Variables
        /// <summary>
        /// Comparer
        /// </summary>
        private readonly IEqualityComparer<T> equalityComparer;
        #endregion

        #region Constructors
        /// <summary>
        /// Initializes a new instance of the <see cref="SetEqualityComparer&lt;T&gt;"/> class.
        /// </summary>
        /// <param name="equalityComparer">The equality comparer.</param>
        public SetEqualityComparer(IEqualityComparer<T> equalityComparer)
        {
            this.equalityComparer = equalityComparer;
        }
        #endregion

        #region IEqualityComparer Implementation
        /// <summary>
        /// Equalses the specified x.
        /// </summary>
        /// <param name="x">The x.</param>
        /// <param name="y">The y.</param>
        /// <returns></returns>
        public bool Equals(IEnumerable<T> x, IEnumerable<T> y)
        {
            return Algorithms.EqualSets(x, y, equalityComparer);
        }

        /// <summary>
        /// Returns a hash code for this instance.
        /// </summary>
        /// <param name="obj">The obj.</param>
        /// <returns>
        /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash provider. 
        /// </returns>
        public int GetHashCode(IEnumerable<T> obj)
        {
            int hash = 0x624F273C;

            foreach (T t in obj)
            {
                int itemHash = Util.GetHashCode(t, equalityComparer);
                hash += itemHash;
            }

            return hash & 0x7FFFFFFF;
        }
        #endregion
    }
}
