#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;
using System.Reflection;

using log4net.Appender;
using log4net.Util;
using log4net.Repository;


namespace log4net.Core
{
	/// <summary>
	/// The implementation of the <see cref="IRepositorySelector"/> interface suitable
	/// for use with the compact framework
	/// </summary>
	/// <remarks>
	/// <para>
	/// This <see cref="IRepositorySelector"/> implementation is a simple
	/// mapping between repository name and <see cref="ILoggerRepository"/>
	/// object.
	/// </para>
	/// <para>
	/// The .NET Compact Framework 1.0 does not support retrieving assembly
	/// level attributes therefore unlike the <c>DefaultRepositorySelector</c>
	/// this selector does not examine the calling assembly for attributes.
	/// </para>
	/// </remarks>
	/// <author>Nicko Cadell</author>
	public class CompactRepositorySelector : IRepositorySelector
	{
		#region Member Variables

		private const string DefaultRepositoryName = "log4net-default-repository";

		private readonly Hashtable m_name2repositoryMap = new Hashtable();
		private readonly Type m_defaultRepositoryType;

		private event LoggerRepositoryCreationEventHandler m_loggerRepositoryCreatedEvent;

		#endregion

		#region Constructors

		/// <summary>
		/// Create a new repository selector
		/// </summary>
		/// <param name="defaultRepositoryType">the type of the repositories to create, must implement <see cref="ILoggerRepository"/></param>
		/// <remarks>
		/// <para>
		/// Create an new compact repository selector.
		/// The default type for repositories must be specified,
		/// an appropriate value would be <see cref="log4net.Repository.Hierarchy.Hierarchy"/>.
		/// </para>
		/// </remarks>
		/// <exception cref="ArgumentNullException">throw if <paramref name="defaultRepositoryType"/> is null</exception>
		/// <exception cref="ArgumentOutOfRangeException">throw if <paramref name="defaultRepositoryType"/> does not implement <see cref="ILoggerRepository"/></exception>
		public CompactRepositorySelector(Type defaultRepositoryType)
		{
			if (defaultRepositoryType == null)
			{
				throw new ArgumentNullException("defaultRepositoryType");
			}

			// Check that the type is a repository
			if (! (typeof(ILoggerRepository).IsAssignableFrom(defaultRepositoryType)) )
			{
				throw log4net.Util.SystemInfo.CreateArgumentOutOfRangeException("defaultRepositoryType", (object)defaultRepositoryType, "Parameter: defaultRepositoryType, Value: ["+defaultRepositoryType+"] out of range. Argument must implement the ILoggerRepository interface");
			}

			m_defaultRepositoryType = defaultRepositoryType;

			LogLog.Debug(declaringType, "defaultRepositoryType ["+m_defaultRepositoryType+"]");
		}

		#endregion

		#region Implementation of IRepositorySelector

		/// <summary>
		/// Get the <see cref="ILoggerRepository"/> for the specified assembly
		/// </summary>
		/// <param name="assembly">not used</param>
		/// <returns>The default <see cref="ILoggerRepository"/></returns>
		/// <remarks>
		/// <para>
		/// The <paramref name="assembly"/> argument is not used. This selector does not create a
		/// separate repository for each assembly.
		/// </para>
		/// <para>
		/// As a named repository is not specified the default repository is
		/// returned. The default repository is named <c>log4net-default-repository</c>.
		/// </para>
		/// </remarks>
		public ILoggerRepository GetRepository(Assembly assembly)
		{
			return CreateRepository(assembly, m_defaultRepositoryType);
		}

		/// <summary>
		/// Get the named <see cref="ILoggerRepository"/>
		/// </summary>
		/// <param name="repositoryName">the name of the repository to lookup</param>
		/// <returns>The named <see cref="ILoggerRepository"/></returns>
		/// <remarks>
		/// <para>
		/// Get the named <see cref="ILoggerRepository"/>. The default
		/// repository is <c>log4net-default-repository</c>. Other repositories
		/// must be created using the <see cref="M:CreateRepository(string, Type)"/>.
		/// If the named repository does not exist an exception is thrown.
		/// </para>
		/// </remarks>
		/// <exception cref="ArgumentNullException">throw if <paramref name="repositoryName"/> is null</exception>
		/// <exception cref="LogException">throw if the <paramref name="repositoryName"/> does not exist</exception>
		public ILoggerRepository GetRepository(string repositoryName)
		{
			if (repositoryName == null)
			{
				throw new ArgumentNullException("repositoryName");
			}

			lock(this)
			{
				// Lookup in map
				ILoggerRepository rep = m_name2repositoryMap[repositoryName] as ILoggerRepository;
				if (rep == null)
				{
					throw new LogException("Repository ["+repositoryName+"] is NOT defined.");
				}
				return rep;
			}
		}

		/// <summary>
		/// Create a new repository for the assembly specified
		/// </summary>
		/// <param name="assembly">not used</param>
		/// <param name="repositoryType">the type of repository to create, must implement <see cref="ILoggerRepository"/></param>
		/// <returns>the repository created</returns>
		/// <remarks>
		/// <para>
		/// The <paramref name="assembly"/> argument is not used. This selector does not create a
		/// separate repository for each assembly.
		/// </para>
		/// <para>
		/// If the <paramref name="repositoryType"/> is <c>null</c> then the
		/// default repository type specified to the constructor is used.
		/// </para>
		/// <para>
		/// As a named repository is not specified the default repository is
		/// returned. The default repository is named <c>log4net-default-repository</c>.
		/// </para>
		/// </remarks>
		public ILoggerRepository CreateRepository(Assembly assembly, Type repositoryType)
		{
			// If the type is not set then use the default type
			if (repositoryType == null)
			{
				repositoryType = m_defaultRepositoryType;
			}

			lock(this)
			{
				// This method should not throw if the default repository already exists.

				// First check that the repository does not exist
				ILoggerRepository rep = m_name2repositoryMap[DefaultRepositoryName] as ILoggerRepository;
				if (rep == null)
				{
					// Must create the repository
					rep = CreateRepository(DefaultRepositoryName, repositoryType);
				}

				return rep;
			}
		}

		/// <summary>
		/// Create a new repository for the repository specified
		/// </summary>
		/// <param name="repositoryName">the repository to associate with the <see cref="ILoggerRepository"/></param>
		/// <param name="repositoryType">the type of repository to create, must implement <see cref="ILoggerRepository"/>.
		/// If this param is null then the default repository type is used.</param>
		/// <returns>the repository created</returns>
		/// <remarks>
		/// <para>
		/// The <see cref="ILoggerRepository"/> created will be associated with the repository
		/// specified such that a call to <see cref="M:GetRepository(string)"/> with the
		/// same repository specified will return the same repository instance.
		/// </para>
		/// <para>
		/// If the named repository already exists an exception will be thrown.
		/// </para>
		/// <para>
		/// If <paramref name="repositoryType"/> is <c>null</c> then the default
		/// repository type specified to the constructor is used.
		/// </para>
		/// </remarks>
		/// <exception cref="ArgumentNullException">throw if <paramref name="repositoryName"/> is null</exception>
		/// <exception cref="LogException">throw if the <paramref name="repositoryName"/> already exists</exception>
		public ILoggerRepository CreateRepository(string repositoryName, Type repositoryType)
		{
			if (repositoryName == null)
			{
				throw new ArgumentNullException("repositoryName");
			}

			// If the type is not set then use the default type
			if (repositoryType == null)
			{
				repositoryType = m_defaultRepositoryType;
			}

			lock(this)
			{
				ILoggerRepository rep = null;

				// First check that the repository does not exist
				rep = m_name2repositoryMap[repositoryName] as ILoggerRepository;
				if (rep != null)
				{
					throw new LogException("Repository ["+repositoryName+"] is already defined. Repositories cannot be redefined.");
				}
				else
				{
					LogLog.Debug(declaringType, "Creating repository ["+repositoryName+"] using type ["+repositoryType+"]");

					// Call the no arg constructor for the repositoryType
					rep = (ILoggerRepository)Activator.CreateInstance(repositoryType);

					// Set the name of the repository
					rep.Name = repositoryName;

					// Store in map
					m_name2repositoryMap[repositoryName] = rep;

					// Notify listeners that the repository has been created
					OnLoggerRepositoryCreatedEvent(rep);
				}

				return rep;
			}
		}

		/// <summary>
		/// Test if a named repository exists
		/// </summary>
		/// <param name="repositoryName">the named repository to check</param>
		/// <returns><c>true</c> if the repository exists</returns>
		/// <remarks>
		/// <para>
		/// Test if a named repository exists. Use <see cref="M:CreateRepository(string, Type)"/>
		/// to create a new repository and <see cref="M:GetRepository(string)"/> to retrieve
		/// a repository.
		/// </para>
		/// </remarks>
		public bool ExistsRepository(string repositoryName)
		{
			lock(this)
			{
				return m_name2repositoryMap.ContainsKey(repositoryName);
			}
		}

		/// <summary>
		/// Gets a list of <see cref="ILoggerRepository"/> objects
		/// </summary>
		/// <returns>an array of all known <see cref="ILoggerRepository"/> objects</returns>
		/// <remarks>
		/// <para>
		/// Gets an array of all of the repositories created by this selector.
		/// </para>
		/// </remarks>
		public ILoggerRepository[] GetAllRepositories()
		{
			lock(this)
			{
				ICollection reps = m_name2repositoryMap.Values;
				ILoggerRepository[] all = new ILoggerRepository[reps.Count];
				reps.CopyTo(all, 0);
				return all;
			}
		}

		#endregion

		#region Private Static Fields

		/// <summary>
		/// The fully qualified type of the CompactRepositorySelector class.
		/// </summary>
		/// <remarks>
		/// Used by the internal logger to record the Type of the
		/// log message.
		/// </remarks>
		private readonly static Type declaringType = typeof(CompactRepositorySelector);

		#endregion Private Static Fields

		/// <summary>
		/// Event to notify that a logger repository has been created.
		/// </summary>
		/// <value>
		/// Event to notify that a logger repository has been created.
		/// </value>
		/// <remarks>
		/// <para>
		/// Event raised when a new repository is created.
		/// The event source will be this selector. The event args will
		/// be a <see cref="LoggerRepositoryCreationEventArgs"/> which
		/// holds the newly created <see cref="ILoggerRepository"/>.
		/// </para>
		/// </remarks>
		public event LoggerRepositoryCreationEventHandler LoggerRepositoryCreatedEvent
		{
			add { m_loggerRepositoryCreatedEvent += value; }
			remove { m_loggerRepositoryCreatedEvent -= value; }
		}

		/// <summary>
		/// Notify the registered listeners that the repository has been created
		/// </summary>
		/// <param name="repository">The repository that has been created</param>
		/// <remarks>
		/// <para>
		/// Raises the <event cref="LoggerRepositoryCreatedEvent">LoggerRepositoryCreatedEvent</event>
		/// event.
		/// </para>
		/// </remarks>
		protected virtual void OnLoggerRepositoryCreatedEvent(ILoggerRepository repository)
		{
			LoggerRepositoryCreationEventHandler handler = m_loggerRepositoryCreatedEvent;
			if (handler != null)
			{
				handler(this, new LoggerRepositoryCreationEventArgs(repository));
			}
		}
	}
}
