#region Apache License
//
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to you under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#endregion

using System;
using System.Collections;

namespace log4net.Core
{
	/// <summary>
	/// A strongly-typed collection of <see cref="Level"/> objects.
	/// </summary>
	/// <author>Nicko Cadell</author>
	public class LevelCollection : ICollection, IList, IEnumerable
#if !NETSTANDARD1_3
		, ICloneable
#endif
	{
		#region Interfaces

		/// <summary>
		/// Supports type-safe iteration over a <see cref="LevelCollection"/>.
		/// </summary>
		public interface ILevelCollectionEnumerator
		{
			/// <summary>
			/// Gets the current element in the collection.
			/// </summary>
			Level Current { get; }

			/// <summary>
			/// Advances the enumerator to the next element in the collection.
			/// </summary>
			/// <returns>
			/// <c>true</c> if the enumerator was successfully advanced to the next element;
			/// <c>false</c> if the enumerator has passed the end of the collection.
			/// </returns>
			/// <exception cref="InvalidOperationException">
			/// The collection was modified after the enumerator was created.
			/// </exception>
			bool MoveNext();

			/// <summary>
			/// Sets the enumerator to its initial position, before the first element in the collection.
			/// </summary>
			void Reset();
		}

		#endregion

		private const int DEFAULT_CAPACITY = 16;

		#region Implementation (data)

		private Level[] m_array;
		private int m_count = 0;
		private int m_version = 0;

		#endregion

		#region Static Wrappers

		/// <summary>
		/// Creates a read-only wrapper for a <c>LevelCollection</c> instance.
		/// </summary>
		/// <param name="list">list to create a readonly wrapper arround</param>
		/// <returns>
		/// A <c>LevelCollection</c> wrapper that is read-only.
		/// </returns>
		public static LevelCollection ReadOnly(LevelCollection list)
		{
			if(list==null) throw new ArgumentNullException("list");

			return new ReadOnlyLevelCollection(list);
		}

		#endregion

		#region Constructors

		/// <summary>
		/// Initializes a new instance of the <c>LevelCollection</c> class
		/// that is empty and has the default initial capacity.
		/// </summary>
		public LevelCollection()
		{
			m_array = new Level[DEFAULT_CAPACITY];
		}

		/// <summary>
		/// Initializes a new instance of the <c>LevelCollection</c> class
		/// that has the specified initial capacity.
		/// </summary>
		/// <param name="capacity">
		/// The number of elements that the new <c>LevelCollection</c> is initially capable of storing.
		/// </param>
		public LevelCollection(int capacity)
		{
			m_array = new Level[capacity];
		}

		/// <summary>
		/// Initializes a new instance of the <c>LevelCollection</c> class
		/// that contains elements copied from the specified <c>LevelCollection</c>.
		/// </summary>
		/// <param name="c">The <c>LevelCollection</c> whose elements are copied to the new collection.</param>
		public LevelCollection(LevelCollection c)
		{
			m_array = new Level[c.Count];
			AddRange(c);
		}

		/// <summary>
		/// Initializes a new instance of the <c>LevelCollection</c> class
		/// that contains elements copied from the specified <see cref="Level"/> array.
		/// </summary>
		/// <param name="a">The <see cref="Level"/> array whose elements are copied to the new list.</param>
		public LevelCollection(Level[] a)
		{
			m_array = new Level[a.Length];
			AddRange(a);
		}

		/// <summary>
		/// Initializes a new instance of the <c>LevelCollection</c> class
		/// that contains elements copied from the specified <see cref="Level"/> collection.
		/// </summary>
		/// <param name="col">The <see cref="Level"/> collection whose elements are copied to the new list.</param>
		public LevelCollection(ICollection col)
		{
			m_array = new Level[col.Count];
			AddRange(col);
		}

		/// <summary>
		/// Type visible only to our subclasses
		/// Used to access protected constructor
		/// </summary>
		protected internal enum Tag
		{
			/// <summary>
			/// A value
			/// </summary>
			Default
		}

		/// <summary>
		/// Allow subclasses to avoid our default constructors
		/// </summary>
		/// <param name="tag"></param>
		protected internal LevelCollection(Tag tag)
		{
			m_array = null;
		}
		#endregion

		#region Operations (type-safe ICollection)

		/// <summary>
		/// Gets the number of elements actually contained in the <c>LevelCollection</c>.
		/// </summary>
		public virtual int Count
		{
			get { return m_count; }
		}

		/// <summary>
		/// Copies the entire <c>LevelCollection</c> to a one-dimensional
		/// <see cref="Level"/> array.
		/// </summary>
		/// <param name="array">The one-dimensional <see cref="Level"/> array to copy to.</param>
		public virtual void CopyTo(Level[] array)
		{
			this.CopyTo(array, 0);
		}

		/// <summary>
		/// Copies the entire <c>LevelCollection</c> to a one-dimensional
		/// <see cref="Level"/> array, starting at the specified index of the target array.
		/// </summary>
		/// <param name="array">The one-dimensional <see cref="Level"/> array to copy to.</param>
		/// <param name="start">The zero-based index in <paramref name="array"/> at which copying begins.</param>
		public virtual void CopyTo(Level[] array, int start)
		{
			if (m_count > array.GetUpperBound(0) + 1 - start)
			{
				throw new System.ArgumentException("Destination array was not long enough.");
			}

			Array.Copy(m_array, 0, array, start, m_count);
		}

		/// <summary>
		/// Gets a value indicating whether access to the collection is synchronized (thread-safe).
		/// </summary>
		/// <returns>false, because the backing type is an array, which is never thread-safe.</returns>
		public virtual bool IsSynchronized
		{
			get { return false; }
		}

		/// <summary>
		/// Gets an object that can be used to synchronize access to the collection.
		/// </summary>
		public virtual object SyncRoot
		{
			get { return m_array; }
		}

		#endregion

		#region Operations (type-safe IList)

		/// <summary>
		/// Gets or sets the <see cref="Level"/> at the specified index.
		/// </summary>
		/// <param name="index">The zero-based index of the element to get or set.</param>
		/// <exception cref="ArgumentOutOfRangeException">
		/// <para><paramref name="index"/> is less than zero</para>
		/// <para>-or-</para>
		/// <para><paramref name="index"/> is equal to or greater than <see cref="LevelCollection.Count"/>.</para>
		/// </exception>
		public virtual Level this[int index]
		{
			get
			{
				ValidateIndex(index); // throws
				return m_array[index];
			}
			set
			{
				ValidateIndex(index); // throws
				++m_version;
				m_array[index] = value;
			}
		}

		/// <summary>
		/// Adds a <see cref="Level"/> to the end of the <c>LevelCollection</c>.
		/// </summary>
		/// <param name="item">The <see cref="Level"/> to be added to the end of the <c>LevelCollection</c>.</param>
		/// <returns>The index at which the value has been added.</returns>
		public virtual int Add(Level item)
		{
			if (m_count == m_array.Length)
			{
				EnsureCapacity(m_count + 1);
			}

			m_array[m_count] = item;
			m_version++;

			return m_count++;
		}

		/// <summary>
		/// Removes all elements from the <c>LevelCollection</c>.
		/// </summary>
		public virtual void Clear()
		{
			++m_version;
			m_array = new Level[DEFAULT_CAPACITY];
			m_count = 0;
		}

		/// <summary>
		/// Creates a shallow copy of the <see cref="LevelCollection"/>.
		/// </summary>
		/// <returns>A new <see cref="LevelCollection"/> with a shallow copy of the collection data.</returns>
		public virtual object Clone()
		{
			LevelCollection newCol = new LevelCollection(m_count);
			Array.Copy(m_array, 0, newCol.m_array, 0, m_count);
			newCol.m_count = m_count;
			newCol.m_version = m_version;

			return newCol;
		}

		/// <summary>
		/// Determines whether a given <see cref="Level"/> is in the <c>LevelCollection</c>.
		/// </summary>
		/// <param name="item">The <see cref="Level"/> to check for.</param>
		/// <returns><c>true</c> if <paramref name="item"/> is found in the <c>LevelCollection</c>; otherwise, <c>false</c>.</returns>
		public virtual bool Contains(Level item)
		{
			for (int i=0; i != m_count; ++i)
			{
				if (m_array[i].Equals(item))
				{
					return true;
				}
			}
			return false;
		}

		/// <summary>
		/// Returns the zero-based index of the first occurrence of a <see cref="Level"/>
		/// in the <c>LevelCollection</c>.
		/// </summary>
		/// <param name="item">The <see cref="Level"/> to locate in the <c>LevelCollection</c>.</param>
		/// <returns>
		/// The zero-based index of the first occurrence of <paramref name="item"/>
		/// in the entire <c>LevelCollection</c>, if found; otherwise, -1.
		///	</returns>
		public virtual int IndexOf(Level item)
		{
			for (int i=0; i != m_count; ++i)
			{
				if (m_array[i].Equals(item))
				{
					return i;
				}
			}
			return -1;
		}

		/// <summary>
		/// Inserts an element into the <c>LevelCollection</c> at the specified index.
		/// </summary>
		/// <param name="index">The zero-based index at which <paramref name="item"/> should be inserted.</param>
		/// <param name="item">The <see cref="Level"/> to insert.</param>
		/// <exception cref="ArgumentOutOfRangeException">
		/// <para><paramref name="index"/> is less than zero</para>
		/// <para>-or-</para>
		/// <para><paramref name="index"/> is equal to or greater than <see cref="LevelCollection.Count"/>.</para>
		/// </exception>
		public virtual void Insert(int index, Level item)
		{
			ValidateIndex(index, true); // throws

			if (m_count == m_array.Length)
			{
				EnsureCapacity(m_count + 1);
			}

			if (index < m_count)
			{
				Array.Copy(m_array, index, m_array, index + 1, m_count - index);
			}

			m_array[index] = item;
			m_count++;
			m_version++;
		}

		/// <summary>
		/// Removes the first occurrence of a specific <see cref="Level"/> from the <c>LevelCollection</c>.
		/// </summary>
		/// <param name="item">The <see cref="Level"/> to remove from the <c>LevelCollection</c>.</param>
		/// <exception cref="ArgumentException">
		/// The specified <see cref="Level"/> was not found in the <c>LevelCollection</c>.
		/// </exception>
		public virtual void Remove(Level item)
		{
			int i = IndexOf(item);
			if (i < 0)
			{
				throw new System.ArgumentException("Cannot remove the specified item because it was not found in the specified Collection.");
			}

			++m_version;
			RemoveAt(i);
		}

		/// <summary>
		/// Removes the element at the specified index of the <c>LevelCollection</c>.
		/// </summary>
		/// <param name="index">The zero-based index of the element to remove.</param>
		/// <exception cref="ArgumentOutOfRangeException">
		/// <para><paramref name="index"/> is less than zero</para>
		/// <para>-or-</para>
		/// <para><paramref name="index"/> is equal to or greater than <see cref="LevelCollection.Count"/>.</para>
		/// </exception>
		public virtual void RemoveAt(int index)
		{
			ValidateIndex(index); // throws

			m_count--;

			if (index < m_count)
			{
				Array.Copy(m_array, index + 1, m_array, index, m_count - index);
			}

			// We can't set the deleted entry equal to null, because it might be a value type.
			// Instead, we'll create an empty single-element array of the right type and copy it
			// over the entry we want to erase.
			Level[] temp = new Level[1];
			Array.Copy(temp, 0, m_array, m_count, 1);
			m_version++;
		}

		/// <summary>
		/// Gets a value indicating whether the collection has a fixed size.
		/// </summary>
		/// <value>true if the collection has a fixed size; otherwise, false. The default is false</value>
		public virtual bool IsFixedSize
		{
			get { return false; }
		}

		/// <summary>
		/// Gets a value indicating whether the IList is read-only.
		/// </summary>
		/// <value>true if the collection is read-only; otherwise, false. The default is false</value>
		public virtual bool IsReadOnly
		{
			get { return false; }
		}

		#endregion

		#region Operations (type-safe IEnumerable)

		/// <summary>
		/// Returns an enumerator that can iterate through the <c>LevelCollection</c>.
		/// </summary>
		/// <returns>An <see cref="Enumerator"/> for the entire <c>LevelCollection</c>.</returns>
		public virtual ILevelCollectionEnumerator GetEnumerator()
		{
			return new Enumerator(this);
		}

		#endregion

		#region Public helpers (just to mimic some nice features of ArrayList)

		/// <summary>
		/// Gets or sets the number of elements the <c>LevelCollection</c> can contain.
		/// </summary>
		public virtual int Capacity
		{
			get
			{
				return m_array.Length;
			}
			set
			{
				if (value < m_count)
				{
					value = m_count;
				}

				if (value != m_array.Length)
				{
					if (value > 0)
					{
						Level[] temp = new Level[value];
						Array.Copy(m_array, 0, temp, 0, m_count);
						m_array = temp;
					}
					else
					{
						m_array = new Level[DEFAULT_CAPACITY];
					}
				}
			}
		}

		/// <summary>
		/// Adds the elements of another <c>LevelCollection</c> to the current <c>LevelCollection</c>.
		/// </summary>
		/// <param name="x">The <c>LevelCollection</c> whose elements should be added to the end of the current <c>LevelCollection</c>.</param>
		/// <returns>The new <see cref="LevelCollection.Count"/> of the <c>LevelCollection</c>.</returns>
		public virtual int AddRange(LevelCollection x)
		{
			if (m_count + x.Count >= m_array.Length)
			{
				EnsureCapacity(m_count + x.Count);
			}

			Array.Copy(x.m_array, 0, m_array, m_count, x.Count);
			m_count += x.Count;
			m_version++;

			return m_count;
		}

		/// <summary>
		/// Adds the elements of a <see cref="Level"/> array to the current <c>LevelCollection</c>.
		/// </summary>
		/// <param name="x">The <see cref="Level"/> array whose elements should be added to the end of the <c>LevelCollection</c>.</param>
		/// <returns>The new <see cref="LevelCollection.Count"/> of the <c>LevelCollection</c>.</returns>
		public virtual int AddRange(Level[] x)
		{
			if (m_count + x.Length >= m_array.Length)
			{
				EnsureCapacity(m_count + x.Length);
			}

			Array.Copy(x, 0, m_array, m_count, x.Length);
			m_count += x.Length;
			m_version++;

			return m_count;
		}

		/// <summary>
		/// Adds the elements of a <see cref="Level"/> collection to the current <c>LevelCollection</c>.
		/// </summary>
		/// <param name="col">The <see cref="Level"/> collection whose elements should be added to the end of the <c>LevelCollection</c>.</param>
		/// <returns>The new <see cref="LevelCollection.Count"/> of the <c>LevelCollection</c>.</returns>
		public virtual int AddRange(ICollection col)
		{
			if (m_count + col.Count >= m_array.Length)
			{
				EnsureCapacity(m_count + col.Count);
			}

			foreach(object item in col)
			{
				Add((Level)item);
			}

			return m_count;
		}

		/// <summary>
		/// Sets the capacity to the actual number of elements.
		/// </summary>
		public virtual void TrimToSize()
		{
			this.Capacity = m_count;
		}

		#endregion

		#region Implementation (helpers)

		/// <exception cref="ArgumentOutOfRangeException">
		/// <para><paramref name="i"/> is less than zero</para>
		/// <para>-or-</para>
		/// <para><paramref name="i"/> is equal to or greater than <see cref="LevelCollection.Count"/>.</para>
		/// </exception>
		private void ValidateIndex(int i)
		{
			ValidateIndex(i, false);
		}

		/// <exception cref="ArgumentOutOfRangeException">
		/// <para><paramref name="i"/> is less than zero</para>
		/// <para>-or-</para>
		/// <para><paramref name="i"/> is equal to or greater than <see cref="LevelCollection.Count"/>.</para>
		/// </exception>
		private void ValidateIndex(int i, bool allowEqualEnd)
		{
			int max = (allowEqualEnd) ? (m_count) : (m_count-1);
			if (i < 0 || i > max)
			{
				throw log4net.Util.SystemInfo.CreateArgumentOutOfRangeException("i", (object)i, "Index was out of range. Must be non-negative and less than the size of the collection. [" + (object)i + "] Specified argument was out of the range of valid values.");
			}
		}

		private void EnsureCapacity(int min)
		{
			int newCapacity = ((m_array.Length == 0) ? DEFAULT_CAPACITY : m_array.Length * 2);
			if (newCapacity < min)
			{
				newCapacity = min;
			}

			this.Capacity = newCapacity;
		}

		#endregion

		#region Implementation (ICollection)

		void ICollection.CopyTo(Array array, int start)
		{
			Array.Copy(m_array, 0, array, start, m_count);
		}

		#endregion

		#region Implementation (IList)

		object IList.this[int i]
		{
			get { return (object)this[i]; }
			set { this[i] = (Level)value; }
		}

		int IList.Add(object x)
		{
			return this.Add((Level)x);
		}

		bool IList.Contains(object x)
		{
			return this.Contains((Level)x);
		}

		int IList.IndexOf(object x)
		{
			return this.IndexOf((Level)x);
		}

		void IList.Insert(int pos, object x)
		{
			this.Insert(pos, (Level)x);
		}

		void IList.Remove(object x)
		{
			this.Remove((Level)x);
		}

		void IList.RemoveAt(int pos)
		{
			this.RemoveAt(pos);
		}

		#endregion

		#region Implementation (IEnumerable)

		IEnumerator IEnumerable.GetEnumerator()
		{
			return (IEnumerator)(this.GetEnumerator());
		}

		#endregion

		#region Nested enumerator class

		/// <summary>
		/// Supports simple iteration over a <see cref="LevelCollection"/>.
		/// </summary>
		private sealed class Enumerator : IEnumerator, ILevelCollectionEnumerator
		{
			#region Implementation (data)

			private readonly LevelCollection m_collection;
			private int m_index;
			private int m_version;

			#endregion

			#region Construction

			/// <summary>
			/// Initializes a new instance of the <c>Enumerator</c> class.
			/// </summary>
			/// <param name="tc"></param>
			internal Enumerator(LevelCollection tc)
			{
				m_collection = tc;
				m_index = -1;
				m_version = tc.m_version;
			}

			#endregion

			#region Operations (type-safe IEnumerator)

			/// <summary>
			/// Gets the current element in the collection.
			/// </summary>
			public Level Current
			{
				get { return m_collection[m_index]; }
			}

			/// <summary>
			/// Advances the enumerator to the next element in the collection.
			/// </summary>
			/// <returns>
			/// <c>true</c> if the enumerator was successfully advanced to the next element;
			/// <c>false</c> if the enumerator has passed the end of the collection.
			/// </returns>
			/// <exception cref="InvalidOperationException">
			/// The collection was modified after the enumerator was created.
			/// </exception>
			public bool MoveNext()
			{
				if (m_version != m_collection.m_version)
				{
					throw new System.InvalidOperationException("Collection was modified; enumeration operation may not execute.");
				}

				++m_index;
				return (m_index < m_collection.Count);
			}

			/// <summary>
			/// Sets the enumerator to its initial position, before the first element in the collection.
			/// </summary>
			public void Reset()
			{
				m_index = -1;
			}

			#endregion

			#region Implementation (IEnumerator)

			object IEnumerator.Current
			{
				get { return this.Current; }
			}

			#endregion
		}

		#endregion

		#region Nested Read Only Wrapper class

		private sealed class ReadOnlyLevelCollection : LevelCollection
		{
			#region Implementation (data)

			private readonly LevelCollection m_collection;

			#endregion

			#region Construction

			internal ReadOnlyLevelCollection(LevelCollection list) : base(Tag.Default)
			{
				m_collection = list;
			}

			#endregion

			#region Type-safe ICollection

			public override void CopyTo(Level[] array)
			{
				m_collection.CopyTo(array);
			}

			public override void CopyTo(Level[] array, int start)
			{
				m_collection.CopyTo(array,start);
			}
			public override int Count
			{
				get { return m_collection.Count; }
			}

			public override bool IsSynchronized
			{
				get { return m_collection.IsSynchronized; }
			}

			public override object SyncRoot
			{
				get { return this.m_collection.SyncRoot; }
			}

			#endregion

			#region Type-safe IList

			public override Level this[int i]
			{
				get { return m_collection[i]; }
				set { throw new NotSupportedException("This is a Read Only Collection and can not be modified"); }
			}

			public override int Add(Level x)
			{
				throw new NotSupportedException("This is a Read Only Collection and can not be modified");
			}

			public override void Clear()
			{
				throw new NotSupportedException("This is a Read Only Collection and can not be modified");
			}

			public override bool Contains(Level x)
			{
				return m_collection.Contains(x);
			}

			public override int IndexOf(Level x)
			{
				return m_collection.IndexOf(x);
			}

			public override void Insert(int pos, Level x)
			{
				throw new NotSupportedException("This is a Read Only Collection and can not be modified");
			}

			public override void Remove(Level x)
			{
				throw new NotSupportedException("This is a Read Only Collection and can not be modified");
			}

			public override void RemoveAt(int pos)
			{
				throw new NotSupportedException("This is a Read Only Collection and can not be modified");
			}

			public override bool IsFixedSize
			{
				get { return true; }
			}

			public override bool IsReadOnly
			{
				get { return true; }
			}

			#endregion

			#region Type-safe IEnumerable

			public override ILevelCollectionEnumerator GetEnumerator()
			{
				return m_collection.GetEnumerator();
			}

			#endregion

			#region Public Helpers

			// (just to mimic some nice features of ArrayList)
			public override int Capacity
			{
				get { return m_collection.Capacity; }
				set { throw new NotSupportedException("This is a Read Only Collection and can not be modified"); }
			}

			public override int AddRange(LevelCollection x)
			{
				throw new NotSupportedException("This is a Read Only Collection and can not be modified");
			}

			public override int AddRange(Level[] x)
			{
				throw new NotSupportedException("This is a Read Only Collection and can not be modified");
			}

			#endregion
		}

		#endregion
	}

}
