/// <summary>
		/// Returns the zero-based index of the first occurrence of the specified
		/// <see cref="Site"/> in the <see cref="SiteCollection"/>.
		/// </summary>
		/// <param name="value">The <see cref="Site"/> object
		/// to locate in the <see cref="SiteCollection"/>.
		/// This argument can be a null reference.
		/// </param>
		/// <returns>
		/// The zero-based index of the first occurrence of <paramref name="value"/>
		/// in the <see cref="SiteCollection"/>, if found; otherwise, -1.
		/// </returns>
		/// <remarks>Please refer to <see cref="ArrayList.IndexOf"/> for details.</remarks>

		public virtual int IndexOf(Site value)
		{
			return Array.IndexOf(this._array, value, 0, this._count);
		}
		/// <summary>
		/// Adds the elements of a <see cref="Site"/> array
		/// to the end of the <see cref="SiteCollection"/>.
		/// </summary>
		/// <param name="array">An <see cref="Array"/> of <see cref="Site"/> elements
		/// that should be added to the end of the <see cref="SiteCollection"/>.</param>
		/// <exception cref="ArgumentNullException">
		/// <paramref name="array"/> is a null reference.</exception>
		/// <exception cref="NotSupportedException">
		/// <para>The <see cref="SiteCollection"/> is read-only.</para>
		/// <para>-or-</para>
		/// <para>The <b>SiteCollection</b> has a fixed size.</para>
		/// <para>-or-</para>
		/// <para>The <b>SiteCollection</b> already contains one or more elements
		/// in the specified <paramref name="array"/>, and the <b>SiteCollection</b>
		/// ensures that all elements are unique.</para></exception>
		/// <remarks>Please refer to <see cref="ArrayList.AddRange"/> for details.</remarks>

		public virtual void AddRange(Site[] array)
		{
			if (array == null)
				throw new ArgumentNullException("array");

			if (array.Length == 0) return;
			if (this._count + array.Length > this._array.Length)
				EnsureCapacity(this._count + array.Length);

			++this._version;
			Array.Copy(array, 0, this._array, this._count, array.Length);
			this._count += array.Length;
		}
		/// <summary>
		/// Determines whether the <see cref="SiteCollection"/>
		/// contains the specified <see cref="Site"/> element.
		/// </summary>
		/// <param name="value">The <see cref="Site"/> object
		/// to locate in the <see cref="SiteCollection"/>.
		/// This argument can be a null reference.
		/// </param>
		/// <returns><c>true</c> if <paramref name="value"/> is found in the
		/// <see cref="SiteCollection"/>; otherwise, <c>false</c>.</returns>
		/// <remarks>Please refer to <see cref="ArrayList.Contains"/> for details.</remarks>

		public bool Contains(Site value)
		{
			return (IndexOf(value) >= 0);
		}
			private void CheckUnique(Site value)
			{
				if (IndexOf(value) >= 0)
					throw new NotSupportedException(
						"Unique collections cannot contain duplicate elements.");
			}
		/// <summary>
		/// Initializes a new instance of the <see cref="SiteCollection"/> class
		/// that contains elements copied from the specified <see cref="Site"/>
		/// array and that has the same initial capacity as the number of elements copied.
		/// </summary>
		/// <param name="array">An <see cref="Array"/> of <see cref="Site"/>
		/// elements that are copied to the new collection.</param>
		/// <exception cref="ArgumentNullException">
		/// <paramref name="array"/> is a null reference.</exception>
		/// <remarks>Please refer to <see cref="ArrayList(ICollection)"/> for details.</remarks>

		public SiteCollection(Site[] array)
		{
			if (array == null)
				throw new ArgumentNullException("array");

			this._array = new Site[array.Length];
			AddRange(array);
		}
			public override void CopyTo(Site[] array, int arrayIndex)
			{
				this._collection.CopyTo(array, arrayIndex);
			}
			public override void Insert(int index, Site value)
			{
				CheckUnique(value);
				this._collection.Insert(index, value);
			}
			public override void Remove(Site value)
			{
				throw new NotSupportedException(
					"Read-only collections cannot be modified.");
			}
			public override int Add(Site value)
			{
				lock (this._root) return this._collection.Add(value);
			}
			public override void AddRange(Site[] array)
			{
				throw new NotSupportedException(
					"Read-only collections cannot be modified.");
			}
			public override void Insert(int index, Site value)
			{
				throw new NotSupportedException(
					"Read-only collections cannot be modified.");
			}
		/// <summary>
		/// Copies the elements of the <see cref="SiteCollection"/> to a new
		/// <see cref="Array"/> of <see cref="Site"/> elements.
		/// </summary>
		/// <returns>A one-dimensional <see cref="Array"/> of <see cref="Site"/>
		/// elements containing copies of the elements of the <see cref="SiteCollection"/>.</returns>
		/// <remarks>Please refer to <see cref="ArrayList.ToArray"/> for details.</remarks>

		public virtual Site[] ToArray()
		{
			Site[] array = new Site[this._count];
			Array.Copy(this._array, array, this._count);
			return array;
		}
		/// <summary>
		/// Removes the first occurrence of the specified <see cref="Site"/>
		/// from the <see cref="SiteCollection"/>.
		/// </summary>
		/// <param name="value">The <see cref="Site"/> object
		/// to remove from the <see cref="SiteCollection"/>.
		/// This argument can be a null reference.
		/// </param>
		/// <exception cref="NotSupportedException">
		/// <para>The <see cref="SiteCollection"/> is read-only.</para>
		/// <para>-or-</para>
		/// <para>The <b>SiteCollection</b> has a fixed size.</para></exception>
		/// <remarks>Please refer to <see cref="ArrayList.Remove"/> for details.</remarks>

		public virtual void Remove(Site value)
		{
			int index = IndexOf(value);
			if (index >= 0) RemoveAt(index);
		}
		/// <summary>
		/// Inserts a <see cref="Site"/> element into the
		/// <see cref="SiteCollection"/> at the specified index.
		/// </summary>
		/// <param name="index">The zero-based index at which <paramref name="value"/>
		/// should be inserted.</param>
		/// <param name="value">The <see cref="Site"/> object
		/// to insert into the <see cref="SiteCollection"/>.
		/// This argument can be a null reference.
		/// </param>
		/// <exception cref="ArgumentOutOfRangeException">
		/// <para><paramref name="index"/> is less than zero.</para>
		/// <para>-or-</para>
		/// <para><paramref name="index"/> is greater than <see cref="Count"/>.</para>
		/// </exception>
		/// <exception cref="NotSupportedException">
		/// <para>The <see cref="SiteCollection"/> is read-only.</para>
		/// <para>-or-</para>
		/// <para>The <b>SiteCollection</b> has a fixed size.</para>
		/// <para>-or-</para>
		/// <para>The <b>SiteCollection</b> already contains the specified
		/// <paramref name="value"/>, and the <b>SiteCollection</b>
		/// ensures that all elements are unique.</para></exception>
		/// <remarks>Please refer to <see cref="ArrayList.Insert"/> for details.</remarks>

		public virtual void Insert(int index, Site value)
		{
			if (index < 0)
				throw new ArgumentOutOfRangeException("index",
					index, "Argument cannot be negative.");

			if (index > this._count)
				throw new ArgumentOutOfRangeException("index",
					index, "Argument cannot exceed Count.");

			if (this._count == this._array.Length)
				EnsureCapacity(this._count + 1);

			++this._version;
			if (index < this._count)
				Array.Copy(this._array, index,
					this._array, index + 1, this._count - index);

			this._array[index] = value;
			++this._count;
		}
			public override int BinarySearch(Site value)
			{
				return this._collection.BinarySearch(value);
			}
			public override void AddRange(Site[] array)
			{
				lock (this._root) this._collection.AddRange(array);
			}
			public override void CopyTo(Site[] array)
			{
				this._collection.CopyTo(array);
			}
			public override void CopyTo(Site[] array)
			{
				lock (this._root) this._collection.CopyTo(array);
			}
			public override int IndexOf(Site value)
			{
				return this._collection.IndexOf(value);
			}
			public override int IndexOf(Site value)
			{
				lock (this._root) return this._collection.IndexOf(value);
			}
			public override void Remove(Site value)
			{
				this._collection.Remove(value);
			}
			public override void Insert(int index, Site value)
			{
				lock (this._root) this._collection.Insert(index, value);
			}
			private void CheckUnique(int index, Site value)
			{
				int existing = IndexOf(value);
				if (existing >= 0 && existing != index)
					throw new NotSupportedException(
						"Unique collections cannot contain duplicate elements.");
			}
			public override void Remove(Site value)
			{
				lock (this._root) this._collection.Remove(value);
			}
		/// <summary>
		/// Adds a <see cref="Site"/> to the end of the <see cref="SiteCollection"/>.
		/// </summary>
		/// <param name="value">The <see cref="Site"/> object
		/// to be added to the end of the <see cref="SiteCollection"/>.
		/// This argument can be a null reference.
		/// </param>
		/// <returns>The <see cref="SiteCollection"/> index at which the
		/// <paramref name="value"/> has been added.</returns>
		/// <exception cref="NotSupportedException">
		/// <para>The <see cref="SiteCollection"/> is read-only.</para>
		/// <para>-or-</para>
		/// <para>The <b>SiteCollection</b> has a fixed size.</para>
		/// <para>-or-</para>
		/// <para>The <b>SiteCollection</b> already contains the specified
		/// <paramref name="value"/>, and the <b>SiteCollection</b>
		/// ensures that all elements are unique.</para></exception>
		/// <remarks>Please refer to <see cref="ArrayList.Add"/> for details.</remarks>

		public virtual int Add(Site value)
		{
			if (this._count == this._array.Length)
				EnsureCapacity(this._count + 1);

			++this._version;
			this._array[this._count] = value;
			return this._count++;
		}
			public override int Add(Site value)
			{
				CheckUnique(value);
				return this._collection.Add(value);
			}
		/// <summary>
		/// Searches the entire sorted <see cref="SiteCollection"/> for an
		/// <see cref="Site"/> element using the default comparer
		/// and returns the zero-based index of the element.
		/// </summary>
		/// <param name="value">The <see cref="Site"/> object
		/// to locate in the <see cref="SiteCollection"/>.
		/// This argument can be a null reference.
		/// </param>
		/// <returns>The zero-based index of <paramref name="value"/> in the sorted
		/// <see cref="SiteCollection"/>, if <paramref name="value"/> is found;
		/// otherwise, a negative number, which is the bitwise complement of the index
		/// of the next element that is larger than <paramref name="value"/> or, if there
		/// is no larger element, the bitwise complement of <see cref="Count"/>.</returns>
		/// <exception cref="InvalidOperationException">
		/// Neither <paramref name="value"/> nor the elements of the <see cref="SiteCollection"/>
		/// implement the <see cref="IComparable"/> interface.</exception>
		/// <remarks>Please refer to <see cref="ArrayList.BinarySearch"/> for details.</remarks>

		public virtual int BinarySearch(Site value)
		{
			return Array.BinarySearch(this._array, 0, this._count, value);
		}
			public override void AddRange(Site[] array)
			{
				foreach (Site value in array)
					CheckUnique(value);

				this._collection.AddRange(array);
			}
		/// <summary>
		/// Get the Freedb sites
		/// </summary>
		/// <param name="protocol"></param>
		/// <param name="sites">SiteCollection that is populated with the site information</param>
		/// <returns>Response Code</returns>
		/// 
		public string GetSites(string protocol, out SiteCollection sites)
		{
			if (protocol != Site.PROTOCOLS.CDDBP && protocol != Site.PROTOCOLS.HTTP)
				protocol = Site.PROTOCOLS.ALL;

			StringCollection coll;

			try
			{
				coll = Call(Commands.CMD_SITES, m_mainSite.GetUrl());
			}

			catch (Exception ex)
			{
				Debug.WriteLine("Error retrieving Sites." + ex.Message);
				Exception newEx = new Exception("FreedbHelper.GetSites: Error retrieving Sites.", ex);
				throw newEx;
			}

			sites = null;

			// check if results came back
			if (coll.Count < 0)
			{
				string msg = "No results returned from sites request.";
				Exception ex = new Exception(msg, null);
				throw ex;
			}

			string code = GetCode(coll[0]);
			if (code == ResponseCodes.CODE_INVALID)
			{
				string msg = "Unable to process results Sites Request. Returned Data: " + coll[0];
				Exception ex = new Exception(msg, null);
				throw ex;
			}

			switch (code)
			{
				case ResponseCodes.CODE_500:
					return ResponseCodes.CODE_500;

				case ResponseCodes.CODE_401:
					return ResponseCodes.CODE_401;

				case ResponseCodes.CODE_210:
					{
						coll.RemoveAt(0);
						sites = new SiteCollection();
						foreach (String line in coll)
						{
							Debug.WriteLine("line: " + line);
							Site site = new Site(line);
							if (protocol == Site.PROTOCOLS.ALL)
								sites.Add(new Site(line));
							else if (site.Protocol == protocol)
								sites.Add(new Site(line));
						}

						return ResponseCodes.CODE_210;
					}

				default:
					return ResponseCodes.CODE_500;
			}

		}
		/// <summary>
		/// Copies the entire <see cref="SiteCollection"/> to a one-dimensional <see cref="Array"/>
		/// of <see cref="Site"/> elements, starting at the specified index of the target array.
		/// </summary>
		/// <param name="array">The one-dimensional <see cref="Array"/> that is the destination of the
		/// <see cref="Site"/> elements copied from the <see cref="SiteCollection"/>.
		/// The <b>Array</b> must have zero-based indexing.</param>
		/// <param name="arrayIndex">The zero-based index in <paramref name="array"/>
		/// at which copying begins.</param>
		/// <exception cref="ArgumentNullException">
		/// <paramref name="array"/> is a null reference.</exception>
		/// <exception cref="ArgumentOutOfRangeException">
		/// <paramref name="arrayIndex"/> is less than zero.</exception>
		/// <exception cref="ArgumentException"><para>
		/// <paramref name="arrayIndex"/> is equal to or greater than the length of <paramref name="array"/>.
		/// </para><para>-or-</para><para>
		/// The number of elements in the source <see cref="SiteCollection"/> is greater than the
		/// available space from <paramref name="arrayIndex"/> to the end of the destination
		/// <paramref name="array"/>.</para></exception>
		/// <remarks>Please refer to <see cref="ArrayList.CopyTo"/> for details.</remarks>

		public virtual void CopyTo(Site[] array, int arrayIndex)
		{
			CheckTargetArray(array, arrayIndex);
			Array.Copy(this._array, 0, array, arrayIndex, this._count);
		}