using Lucene.Net.Support.Threading;
using Lucene.Net.Util;
using System;
using System.Collections.Generic;
using System.Reflection;

namespace Lucene.Net.Codecs
{
    /*
     * 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.
     */

    /// <summary>
    /// Implements the default functionality of <see cref="ICodecFactory"/>.
    /// <para/>
    /// To replace the <see cref="DefaultCodecFactory"/> instance, call
    /// <see cref="Codec.SetCodecFactory(ICodecFactory)"/> at application start up.
    /// <see cref="DefaultCodecFactory"/> can be subclassed or passed additional parameters to register
    /// additional codecs, inject dependencies, or change caching behavior, as shown in the following examples.
    /// Alternatively, <see cref="ICodecFactory"/> can be implemented to provide complete control over
    /// codec creation and lifetimes.
    /// <para/>
    /// <h4>Register Additional Codecs</h4>
    /// <para/>
    /// Additional codecs can be added by initializing the instance of <see cref="DefaultCodecFactory"/> and
    /// passing an array of <see cref="Codec"/>-derived types.
    /// <code>
    /// // Register the factory at application start up.
    /// Codec.SetCodecFactory(new DefaultCodecFactory {
    ///     CustomCodecTypes = new Type[] { typeof(MyCodec), typeof(AnotherCodec) }
    /// });
    /// </code>
    /// <para/>
    /// <h4>Only Use Explicitly Defined Codecs</h4>
    /// <para/>
    /// <see cref="PutCodecType(Type)"/> can be used to explicitly add codec types. In this example,
    /// the call to <c>base.Initialize()</c> is excluded to skip the built-in codec registration.
    /// Since <c>AnotherCodec</c> doesn't have a default constructor, the <see cref="NewCodec(Type)"/>
    /// method is overridden to supply the required parameters.
    /// <code>
    /// public class ExplicitCodecFactory : DefaultCodecFactory
    /// {
    ///     protected override void Initialize()
    ///     {
    ///         // Load specific codecs in a specific order.
    ///         PutCodecType(typeof(MyCodec));
    ///         PutCodecType(typeof(AnotherCodec));
    ///     }
    ///
    ///     protected override Codec NewCodec(Type type)
    ///     {
    ///         // Special case: AnotherCodec has a required dependency
    ///         if (typeof(AnotherCodec).Equals(type))
    ///             return new AnotherCodec(new SomeDependency());
    ///
    ///         return base.NewCodec(type);
    ///     }
    /// }
    ///
    /// // Register the factory at application start up.
    /// Codec.SetCodecFactory(new ExplicitCodecFactory());
    /// </code>
    /// See the <see cref="Lucene.Net.Codecs"/> namespace documentation for more examples of how to
    /// inject dependencies into <see cref="Codec"/> subclasses.
    /// <para/>
    /// <h4>Use Reflection to Scan an Assembly for Codecs</h4>
    /// <para/>
    /// <see cref="ScanForCodecs(Assembly)"/> or <see cref="ScanForCodecs(IEnumerable{Assembly})"/> can be used
    /// to scan assemblies using .NET Reflection for codec types and add all subclasses that are found automatically.
    /// This example calls <c>base.Initialize()</c> to load the default codecs prior to scanning for additional codecs.
    /// <code>
    /// public class ScanningCodecFactory : DefaultCodecFactory
    /// {
    ///     protected override void Initialize()
    ///     {
    ///         // Load all default codecs
    ///         base.Initialize();
    ///
    ///         // Load all of the codecs inside of the same assembly that MyCodec is defined in
    ///         ScanForCodecs(typeof(MyCodec).Assembly);
    ///     }
    /// }
    ///
    /// // Register the factory at application start up.
    /// Codec.SetCodecFactory(new ScanningCodecFactory());
    /// </code>
    /// Codecs in the target assemblie(s) can be excluded from the scan by decorating them with
    /// the <see cref="ExcludeCodecFromScanAttribute"/>.
    /// </summary>
    /// <seealso cref="ICodecFactory"/>
    /// <seealso cref="IServiceListable"/>
    /// <seealso cref="ExcludeCodecFromScanAttribute"/>
    // LUCENENET specific
    public class DefaultCodecFactory : NamedServiceFactory<Codec>, ICodecFactory, IServiceListable
    {
        private static readonly Type[] localCodecTypes = new Type[] {
            typeof(Lucene46.Lucene46Codec),
#pragma warning disable 612, 618
            typeof(Lucene3x.Lucene3xCodec), // Optimize 3.x codec over < 4.6 codecs
            typeof(Lucene45.Lucene45Codec),
            typeof(Lucene42.Lucene42Codec),
            typeof(Lucene41.Lucene41Codec),
            typeof(Lucene40.Lucene40Codec),
#pragma warning restore 612, 618
        };

        // NOTE: The following 2 dictionaries are static, since this instance is stored in a static
        // variable in the Codec class.
        private readonly IDictionary<string, Type> codecNameToTypeMap;
        private readonly IDictionary<Type, Codec> codecInstanceCache;

        /// <summary>
        /// Creates a new instance of <see cref="DefaultCodecFactory"/>.
        /// </summary>
        public DefaultCodecFactory()
        {
            codecNameToTypeMap = new Dictionary<string, Type>();
            codecInstanceCache = new Dictionary<Type, Codec>();
        }

        /// <summary>
        /// An array of custom <see cref="Codec"/>-derived types to be registered. This property
        /// can be initialized during construction of <see cref="DefaultCodecFactory"/>
        /// to make your custom codecs known to Lucene.
        /// <para/>
        /// These types will be registered after the default Lucene types, so if a custom type has the same
        /// name as a Lucene <see cref="Codec"/> (via <see cref="CodecNameAttribute"/>)
        /// the custom type will replace the Lucene type with the same name.
        /// </summary>
        public IEnumerable<Type> CustomCodecTypes { get; set; }

        /// <summary>
        /// Initializes the codec type cache with the known <see cref="Codec"/> types.
        /// Override this method (and optionally call <c>base.Initialize()</c>) to add your
        /// own <see cref="Codec"/> types by calling <see cref="PutCodecType(Type)"/>
        /// or <see cref="ScanForCodecs(Assembly)"/>.
        /// <para/>
        /// If two types have the same name by using the <see cref="CodecNameAttribute"/>, the
        /// last one registered wins.
        /// </summary>
        protected override void Initialize()
        {
            foreach (var codecType in localCodecTypes)
                PutCodecTypeImpl(codecType);
            ScanForCodecs(this.CodecsAssembly);
            if (CustomCodecTypes != null)
            {
                foreach (var codecType in CustomCodecTypes)
                    PutCodecType(codecType);
            }
        }

        /// <summary>
        /// Scans the given <paramref name="assemblies"/> for subclasses of <see cref="Codec"/>
        /// and adds their names to the <see cref="codecNameToTypeMap"/>. Note that names will be
        /// automatically overridden if the <see cref="Codec"/> name appears multiple times - the last match wins.
        /// </summary>
        /// <param name="assemblies">A list of assemblies to scan. The assemblies will be scanned from first to last,
        /// and the last match for each <see cref="Codec"/> name wins.</param>
        protected virtual void ScanForCodecs(IEnumerable<Assembly> assemblies)
        {
            foreach (var assembly in assemblies)
            {
                ScanForCodecs(assembly);
            }
        }

        /// <summary>
        /// Scans the given <paramref name="assembly"/> for subclasses of <see cref="Codec"/>
        /// and adds their names to the <see cref="codecNameToTypeMap"/>. Note that names will be
        /// automatically overridden if the <see cref="Codec"/> name appears multiple times - the last match wins.
        /// </summary>
        /// <param name="assembly">The assembly to scan.</param>
        protected virtual void ScanForCodecs(Assembly assembly)
        {
            if (assembly is null) return;

            foreach (var c in assembly.GetTypes())
            {
                if (IsServiceType(c))
                {
                    PutCodecTypeImpl(c);
                }
            }
        }

        /// <summary>
        /// Adds a <see cref="Codec"/> type to the <see cref="codecNameToTypeMap"/>, using
        /// the name provided in the <see cref="CodecNameAttribute"/>, if present, or the name
        /// of the codec class minus the "Codec" suffix as the name by default.
        /// <para/>
        /// Note that if a <see cref="Codec"/> with the same name already exists in the map,
        /// calling this method will update it to the new type.
        /// </summary>
        /// <param name="codec">A type that subclasses <see cref="Codec"/>.</param>
        protected virtual void PutCodecType(Type codec)
        {
            if (codec is null)
                throw new ArgumentNullException(nameof(codec));
            if (!typeof(Codec).IsAssignableFrom(codec))
                throw new ArgumentException($"The supplied type {codec.AssemblyQualifiedName} does not subclass {nameof(Codec)}.");

            PutCodecTypeImpl(codec);
        }

        private void PutCodecTypeImpl(Type codec)
        {
            string name = GetServiceName(codec);
            UninterruptableMonitor.Enter(m_initializationLock);
            try
            {
                codecNameToTypeMap[name] = codec;
            }
            finally
            {
                UninterruptableMonitor.Exit(m_initializationLock);
            }
        }

        /// <summary>
        /// Gets the <see cref="Codec"/> instance from the provided <paramref name="name"/>.
        /// </summary>
        /// <param name="name">The name of the <see cref="Codec"/> instance to retrieve.</param>
        /// <returns>The <see cref="Codec"/> instance.</returns>
        public virtual Codec GetCodec(string name)
        {
            EnsureInitialized(); // Safety in case a subclass doesn't call it
            UninterruptableMonitor.Enter(m_initializationLock);
            try
            {
                Type codecType = GetCodecType(name);
                return GetCodec(codecType);
            }
            finally
            {
                UninterruptableMonitor.Exit(m_initializationLock);
            }
        }

        /// <summary>
        /// Gets the <see cref="Codec"/> instance from the provided <paramref name="type"/>.
        /// </summary>
        /// <param name="type">The <see cref="Type"/> of <see cref="Codec"/> to retrieve.</param>
        /// <returns>The <see cref="Codec"/> instance.</returns>
        protected virtual Codec GetCodec(Type type)
        {
            if (type is null)
                throw new ArgumentNullException(nameof(type));
            if (!codecInstanceCache.TryGetValue(type, out Codec instance))
            {
                UninterruptableMonitor.Enter(m_initializationLock);
                try
                {
                    if (!codecInstanceCache.TryGetValue(type, out instance))
                    {
                        instance = NewCodec(type);
                        codecInstanceCache[type] = instance;
                    }
                }
                finally
                {
                    UninterruptableMonitor.Exit(m_initializationLock);
                }
            }

            return instance;
        }

        /// <summary>
        /// Instantiates a <see cref="Codec"/> based on the provided <paramref name="type"/>.
        /// </summary>
        /// <param name="type">The <see cref="Type"/> of <see cref="Codec"/> to instantiate.</param>
        /// <returns>The new instance.</returns>
        protected virtual Codec NewCodec(Type type)
        {
            return (Codec)Activator.CreateInstance(type, IsFullyTrusted);
        }

        /// <summary>
        /// Gets the <see cref="Codec"/> <see cref="Type"/> from the provided <paramref name="name"/>.
        /// </summary>
        /// <param name="name">The name of the <see cref="Codec"/> <see cref="Type"/> to retrieve.</param>
        /// <returns>The <see cref="Codec"/> <see cref="Type"/>.</returns>
        protected virtual Type GetCodecType(string name)
        {
            if (name is null)
                throw new ArgumentNullException(nameof(name));
            EnsureInitialized();
            if (!codecNameToTypeMap.TryGetValue(name, out Type codecType) || codecType is null)
            {
                throw new ArgumentException($"Codec '{name}' cannot be loaded. If the codec is not " +
                    $"in a Lucene.Net assembly, you must subclass {typeof(DefaultCodecFactory).FullName}, " +
                    "override the Initialize() method, and call PutCodecType() or ScanForCodecs() to add " +
                    $"the type manually. Call {typeof(Codec).FullName}.SetCodecFactory() at application " +
                    "startup to initialize your custom codec.");
            }

            return codecType;
        }

        /// <summary>
        /// Gets a list of the available <see cref="Codec"/>s (by name).
        /// </summary>
        /// <returns>A <see cref="T:ICollection{string}"/> of <see cref="Codec"/> names.</returns>
        public virtual ICollection<string> AvailableServices
        {
            get
            {
                EnsureInitialized();
                return codecNameToTypeMap.Keys;
            }
        }
    }
}
