using System;
using System.Text;
using System.Collections.Generic;

namespace ExtensionMethods
{
	/// <summary>
	/// <para>Add extensions to <c>List</c></para>
	/// </summary>
	public static class ListExtensions
	{
		/// <summary>
		/// <para>Adds an item to the <see cref="ICollection&lt;T&gt;"/> if it does not yet exist</para>
		/// </summary>
		/// <typeparam name="T">The type of the <see cref="ICollection&lt;T&gt;"/></typeparam>
		/// <param name="list"></param>
		/// <param name="item">The object to add to the <see cref="ICollection&lt;T&gt;"/></param>
		/// <exception cref="NotSupportedException">Thrown by <see cref="ICollection&lt;T&gt;.Add"/></exception>
		public static void AddUnique<T>(this ICollection<T> list, T item)
		{
			if (!list.Contains(item))
				list.Add(item);
		}

		/// <summary>
		/// <para>Concatenates a speceified separator <see cref="string"/> between each element of a specified <see cref="sbyte"/> array, yielding a single concatenated string</para>
		/// </summary>
		/// <param name="array"></param>
		/// <param name="separator">A <see cref="string"/></param>
		/// <returns>The concatenated <see cref="string"/></returns>
		public static string Join<T>(this ICollection<T> array, string separator)
		{
			StringBuilder concat = new StringBuilder();
			bool notFirst = false;
			foreach (T item in array)
			{
				if (notFirst)
					concat.Append(separator);
				else
					notFirst = true;
				concat.Append(item.ToString());
			}
			return concat.ToString();
		}

		/// <summary>
		/// <para>Intersects to <see cref="ICollection&lt;T&gt;"/>s</para>
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="list1"></param>
		/// <param name="list2"></param>
		/// <returns>A <see cref="List&lt;T&gt;"/> that only contains the items which occur both in <paramref name="list1"/> and <paramref name="list2"/></returns>
		public static List<T> Intersect<T>(this ICollection<T> list1, ICollection<T> list2)
		{
			List<T> inter = new List<T>(list1.Count + list2.Count);
			List<T> merge = new List<T>(list1);
			merge.AddRange(list2);

			foreach (T item in merge)
				if (list1.Contains(item) && list2.Contains(item))
					inter.Add(item);

			return inter;
		}
	}
}