#region Native Methods
		[DllImport("gmime")]
		static extern int internet_address_list_length (IntPtr list);
		
		[DllImport("gmime")]
		static extern void internet_address_list_clear (IntPtr list);
		
		[DllImport("gmime")]
		static extern int internet_address_list_add (IntPtr list, IntPtr ia);
		
		//[DllImport("gmime")]
		//static extern void internet_address_list_concat (IntPtr list, IntPtr concat);
		
		[DllImport("gmime")]
		static extern void internet_address_list_insert (IntPtr list, int index, IntPtr ia);
		
		[DllImport("gmime")]
		static extern bool internet_address_list_remove (IntPtr list, IntPtr ia);
		
		[DllImport("gmime")]
		static extern bool internet_address_list_remove_at (IntPtr list, int index);
		
		[DllImport("gmime")]
		static extern bool internet_address_list_contains (IntPtr list, IntPtr ia);
		
		[DllImport("gmime")]
		static extern int internet_address_list_index_of (IntPtr list, IntPtr ia);
		
		[DllImport("gmime")]
		static extern IntPtr internet_address_list_get_address (IntPtr list, int index);
		
		[DllImport("gmime")]
		static extern void internet_address_list_set_address (IntPtr list, int index, IntPtr ia);
		
		[DllImport("gmime")]
		static extern IntPtr internet_address_list_to_string (IntPtr list, bool encode);
		
		[DllImport("gmime")]
		static extern IntPtr internet_address_list_parse_string (IntPtr str);
#endregion
		
		Exception CannotAdd (object value)
		{
			if (value == null)
				return new ArgumentNullException ("value");
			
			string message = String.Format ("Cannot add objects of type '{0}' to an InternetAddressList.",
							value.GetType ().ToString ());
			
			return new InvalidOperationException (message);
		}
		
		Exception CannotInsert (object value)
		{
			if (value == null)
				return new ArgumentNullException ("value");
			
			string message = String.Format ("Cannot insert objects of type '{0}' into an InternetAddressList.",
							value.GetType ().ToString ());
			
			return new InvalidOperationException (message);
		}
		
		Exception CannotRemove (object value)
		{
			if (value == null)
				return new ArgumentNullException ("value");
			
			string  message = String.Format ("Cannot remove objects of type '{0}' from an InternetAddressList.",
							 value.GetType ().ToString ());
			
			return new InvalidOperationException (message);
		}
		
		Exception CannotSet (object value)
		{
			if (value == null)
				return new ArgumentNullException ("value");
			
			string message = String.Format ("Cannot set objects of type '{0}' on an InternetAddressList.",
							value.GetType ().ToString ());
			
			return new InvalidOperationException (message);
		}
		
		public int Count {
			get { return internet_address_list_length (Handle); }
		}
		
		public bool IsFixedSize {
			get { return false; }
		}
		
		public bool IsReadOnly {
			get { return false; }
		}
		
		public bool IsSynchronized {
			get { return false; }
		}
		
		public object SyncRoot {
			get { return this; }
		}
		
		public int Add (InternetAddress addr)
		{
			if (addr == null)
				throw CannotAdd (addr);
			
			return internet_address_list_add (Handle, addr.Handle);
		}
		
		int IList.Add (object value)
		{
			InternetAddress addr = value as InternetAddress;
			
			if (addr == null)
				throw CannotAdd (value);
			
			return Add (addr);
		}
		
		public void Clear ()
		{
			internet_address_list_clear (Handle);
		}
		
		public bool Contains (InternetAddress addr)
		{
			if (addr == null)
				return false;
			
			return internet_address_list_contains (Handle, addr.Handle);
		}
		
		bool IList.Contains (object value)
		{
			return Contains (value as InternetAddress);
		}
		
		public void CopyTo (Array array, int index)
		{
			if (array == null)
				throw new ArgumentNullException ("array");
			
			if (index < 0)
				throw new ArgumentOutOfRangeException ("index");
			
			int n = Count;
			
			for (int i = 0; i < n; i++)
				array.SetValue (((IList) this)[i], index + i);
		}
		
		public IEnumerator GetEnumerator ()
		{
			return new InternetAddressListIterator (this);
		}
		
		public int IndexOf (InternetAddress addr)
		{
			if (addr == null)
				return -1;
			
			return internet_address_list_index_of (Handle, addr.Handle);
		}
		
		int IList.IndexOf (object value)
		{
			return IndexOf (value as InternetAddress);
		}
		
		public void Insert (int index, InternetAddress addr)
		{
			if (addr == null)
				throw CannotInsert (addr);
			
			if (index < 0)
				throw new ArgumentOutOfRangeException ("index");
			
			internet_address_list_insert (Handle, index, addr.Handle);
		}
		
		void IList.Insert (int index, object value)
		{
			InternetAddress addr = value as InternetAddress;
			
			if (addr == null)
				throw CannotInsert (value);
			
			Insert (index, addr);
		}
		
		public void Remove (InternetAddress addr)
		{
			if (addr == null)
				throw CannotRemove (addr);
			
			internet_address_list_remove (Handle, addr.Handle);
		}
		
		void IList.Remove (object value)
		{
			InternetAddress addr = value as InternetAddress;
			
			if (addr == null)
				throw CannotRemove (value);
			
			Remove (addr);
		}
		
		public void RemoveAt (int index)
		{
			if (index < 0 || index >= Count)
				throw new ArgumentOutOfRangeException ("index");
			
			internet_address_list_remove_at (Handle, index);
		}
		
		public InternetAddress this[int index] {
			get {
				IntPtr raw = internet_address_list_get_address (Handle, index);
				
				if (raw == IntPtr.Zero)
					return null;
				
				return GLib.Object.GetObject (raw) as InternetAddress;
			}
			
			set {
				if (value == null)
					throw CannotSet (value);
				
				internet_address_list_set_address (Handle, index, value.Handle);
			}
		}
		
		object IList.this[int index] {
			get {
				return this[index];
			}
			
			set {
				this[index] = value as InternetAddress;
			}
		}
		
		public static InternetAddressList Parse (string str)
		{
			IntPtr native_str = GLib.Marshaller.StringToPtrGStrdup (str);
			IntPtr raw = internet_address_list_parse_string (native_str);
			InternetAddressList list = null;
			
			if (raw != IntPtr.Zero)
				list = new InternetAddressList (raw);
			
			GLib.Marshaller.Free (native_str);
			
			return list;
		}
		
		public string ToString (bool encode)
		{
			IntPtr raw = internet_address_list_to_string (Handle, encode);
			
			if (raw == IntPtr.Zero)
				return String.Empty;
			
			return GLib.Marshaller.PtrToStringGFree (raw);
		}
		
		public override string ToString ()
		{
			return ToString (false);
		}
		
		internal class InternetAddressListIterator : IEnumerator {
			InternetAddressList list;
			int index = -1;
			
			public InternetAddressListIterator (InternetAddressList list)
			{
				this.list = list;
			}
			
			public object Current {
				get { return list[index]; }
			}
			
			public void Reset ()
			{
				index = -1;
			}
			
			public bool MoveNext ()
			{
				index++;
				
				return index < list.Count;
			}
		}
