using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;

using BS.Shared.Core;

namespace BS.Shared.Extensions
{
    public static class IEnumerableTExtensions
    {
        public static bool ContainsSameItemsAs<T>(this IEnumerable<T> p1, IEnumerable<T> pList)
        {
            if ((p1 == null || p1.Count() == 0) && (pList == null || pList.Count() == 0))
            {
                return true;
            }

            if (p1 == null || pList == null || p1.Count() != pList.Count())
            {
                return false;
            }

            foreach (T iT in p1)
            {
                bool lFound = false;
                foreach (T iT2 in pList)
                {
                    if (iT.Equals(iT2))
                    {
                        lFound = true;
                        break;
                    }
                }

                if (!lFound)
                {
                    return false;
                }
            }

            return true;
        }

        public static IEnumerable<T> DoForEach<T>(this IEnumerable<T> pList, Action<T> pAction)
        {
            var list = pList as IList<T> ?? pList.ToList();
            foreach (var t in list)
            {
                pAction(t);
            }

            return list;
        }

        public static IEnumerable<T> FlatOut<T>(this IEnumerable<T> source, Func<T, IEnumerable<T>> childListSelector)
        {
            var flattened = new List<T>();

            flattened.AddRange(source);

            while (flattened.Count > 0)
            {
                T current = flattened[0];
                flattened.RemoveAt(0);

                IEnumerable<T> childList = childListSelector(current);

                if (childList != null)
                {
                    flattened.AddRange(childList);
                }

                yield return current;
            }
        }

        public static int IndexOf<T>(this IEnumerable<T> pList, T pItem)
        {
            int i = 0;
            foreach (T iT in pList)
            {
                if (iT.Equals(pItem))
                {
                    return i;
                }

                i++;
            }

            return -1;
        }

        public static ObservableCollection<T> ToObservableCollection<T>(this IEnumerable<T> pList)
        {
            return new ObservableCollection<T>(pList.ToList());
        }

        public static ObservableSortCollection<T> ToObservableSortCollection<T>(this IEnumerable<T> pList)
        {
            return new ObservableSortCollection<T>(pList);
        }

		public static ObservableDictionary<T, U> ToObservableDictionary<T, U>(this Dictionary<T, U> pList)
		{
			return new ObservableDictionary<T, U>(pList);
		}

        public static ObservableSortCollection<T> ToObservableSortCollection<T>(this IEnumerable<T> pList, Comparison<T> pComparer)
        {
            return pComparer != null ? new ObservableSortCollection<T>(pList, pComparer) : new ObservableSortCollection<T>(pList);
        }

        public static string ToSeparatedString<T>(this IEnumerable<T> pList, string seperator)
        {
            var result = new StringBuilder();
            var tmp = pList.ToArray();

            for (var i = 0; i < tmp.Length; i++)
            {
                result.Append(tmp[i]);

                if (i < tmp.Length - 1)
                {
                    result.Append(seperator);
                }
            }

            return result.ToString();
        }

	    public static HashSet<T> ToHashSet<T>(this IEnumerable<T> pList)
	    {
		    return new HashSet<T>(pList);
	    }

        public static bool ContainsItems<T>(this IEnumerable<T> pList, IEnumerable<T> pList2)
        {
            foreach (var item in pList2)
            {
                if (!pList.Contains(item))
                {
                    return false;
                }
            }

            return true;
        }
    }
}