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

namespace Howest.SchemaDiscovery.Configuration
{
	public abstract class SchemaDiscoveryConfigurationElementCollection<ConfigurationElementType> : ConfigurationElementCollection where ConfigurationElementType : ConfigurationElement, new()
	{

		private ConfigurationElementCollectionType collectionType;
		private string elementName;

		internal SchemaDiscoveryConfigurationElementCollection()
			: this(ConfigurationElementCollectionType.AddRemoveClearMap, null)
		{
		}

		internal SchemaDiscoveryConfigurationElementCollection(ConfigurationElementCollectionType collectionType, string elementName)
		{
			this.collectionType = collectionType;
			this.elementName = elementName;
			if (!string.IsNullOrEmpty(elementName))
			{
				base.AddElementName = elementName;
			}
		}

		internal SchemaDiscoveryConfigurationElementCollection(ConfigurationElementCollectionType collectionType, string elementName, IComparer comparer)
			: base(comparer)
		{
			this.collectionType = collectionType;
			this.elementName = elementName;
		}

		public void Add(ConfigurationElementType element)
		{
			if (!this.IsReadOnly() && (element == null))
			{
				throw new ArgumentNullException("element");
			}
			this.BaseAdd(element);
		}

		protected override void BaseAdd(ConfigurationElement element)
		{
			if (!this.IsReadOnly() && !this.ThrowOnDuplicate)
			{
				object key = this.GetElementKey(element);
				if (this.ContainsKey(key))
				{
					base.BaseRemove(key);
				}
			}
			base.BaseAdd(element);
		}

		public void Clear()
		{
			base.BaseClear();
		}

		public virtual bool ContainsKey(object key)
		{
			if (key != null)
			{
				return (null != base.BaseGet(key));
			}
			List<string> list = new List<string>();
			foreach (PropertyInformation information in this.CreateNewElement().ElementInformation.Properties)
			{
				if (information.IsKey)
				{
					list.Add(information.Name);
				}
			}
			if (list.Count == 0)
			{
				throw new ArgumentNullException("key");
			}
			if (1 == list.Count)
			{
				// TODO: add error description
				throw new ConfigurationErrorsException("");
			}
			StringBuilder builder = new StringBuilder();
			for (int i = 0; i < (list.Count - 1); i++)
			{
				builder = builder.Append(list[i] + ", ");
			}
			builder = builder.Append(list[list.Count - 1]);
			// TODO: add error description
			throw new ConfigurationErrorsException("");
		}

		public void CopyTo(ConfigurationElementType[] array, int start)
		{
			if (array == null)
			{
				throw new ArgumentNullException("array");
			}
			if ((start < 0) || (start >= array.Length))
			{
				// TODO: add error description
				throw new ArgumentException("", "start");
			}
			this.CopyTo(array, start);
		}

		protected override ConfigurationElement CreateNewElement()
		{
			return Activator.CreateInstance<ConfigurationElementType>();
		}

		public int IndexOf(ConfigurationElementType element)
		{
			if (element == null)
			{
				throw new ArgumentNullException("element");
			}
			return base.BaseIndexOf(element);
		}

		public void Remove(ConfigurationElementType element)
		{
			if (!this.IsReadOnly() && (element == null))
			{
				throw new ArgumentNullException("element");
			}
			base.BaseRemove(this.GetElementKey(element));
		}

		public void RemoveAt(int index)
		{
			base.BaseRemoveAt(index);
		}

		public void RemoveAt(object key)
		{
			if (!this.IsReadOnly() && (key == null))
			{
				throw new ArgumentNullException("key");
			}
			base.BaseRemove(key);
		}

		public override ConfigurationElementCollectionType CollectionType
		{
			get
			{
				return this.collectionType;
			}
		}

		protected override string ElementName
		{
			get
			{
				string elementName = this.elementName;
				if (string.IsNullOrEmpty(elementName))
				{
					elementName = base.ElementName;
				}
				return elementName;
			}
		}

		public ConfigurationElementType this[int index]
		{
			get
			{
				return (ConfigurationElementType)base.BaseGet(index);
			}
			set
			{
				if ((!this.IsReadOnly() && !this.ThrowOnDuplicate) && (base.BaseGet(index) != null))
				{
					base.BaseRemoveAt(index);
				}
				this.BaseAdd(index, value);
			}
		}

		public virtual ConfigurationElementType this[object key]
		{
			get
			{
				if (key == null)
				{
					throw new ArgumentNullException("key");
				}
				ConfigurationElementType local = (ConfigurationElementType)base.BaseGet(key);
				if (local == null)
				{
					// TODO: add error description
					throw new KeyNotFoundException("");
				}
				return local;
			}
			set
			{
				if (this.IsReadOnly())
				{
					this.Add(value);
				}
				if (value == null)
				{
					throw new ArgumentNullException("value");
				}
				if (key == null)
				{
					throw new ArgumentNullException("key");
				}
				if (!this.GetElementKey(value).ToString().Equals((string)key, StringComparison.Ordinal))
				{
					// TODO: add error description
					throw new ArgumentException("");
				}
				if (base.BaseGet(key) != null)
				{
					base.BaseRemove(key);
				}
				this.Add(value);
			}
		}
	}
}
