/*
 * 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.
 */

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Threading.Tasks;
using System.Xml;
using Apache.NMS.Util;

namespace Apache.NMS
{
    /// <summary>
    /// Provider implementation mapping class.
    /// </summary>
    public class ProviderFactoryInfo
    {
        public string assemblyFileName;
        public string factoryClassName;

        public ProviderFactoryInfo(string aFileName, string fClassName)
        {
            assemblyFileName = aFileName;
            factoryClassName = fClassName;
        }
    }

    /// <summary>
    /// Implementation of a factory for <see cref="IConnection" /> instances.
    /// </summary>
    public class NMSConnectionFactory : IConnectionFactory
    {
        protected readonly IConnectionFactory factory;
        protected static readonly Dictionary<string, ProviderFactoryInfo> schemaProviderFactoryMap;

        /// <summary>
        /// Static class constructor
        /// </summary>
        static NMSConnectionFactory()
        {
            schemaProviderFactoryMap = new Dictionary<string, ProviderFactoryInfo>();
            schemaProviderFactoryMap["activemq"] =
                new ProviderFactoryInfo("Apache.NMS.ActiveMQ", "Apache.NMS.ActiveMQ.ConnectionFactory");
            schemaProviderFactoryMap["activemqnettx"] = new ProviderFactoryInfo("Apache.NMS.ActiveMQ",
                "Apache.NMS.ActiveMQ.NetTxConnectionFactory");
            schemaProviderFactoryMap["tcp"] =
                new ProviderFactoryInfo("Apache.NMS.ActiveMQ", "Apache.NMS.ActiveMQ.ConnectionFactory");
            schemaProviderFactoryMap["ems"] =
                new ProviderFactoryInfo("Apache.NMS.EMS", "Apache.NMS.EMS.ConnectionFactory");
            schemaProviderFactoryMap["mqtt"] =
                new ProviderFactoryInfo("Apache.NMS.MQTT", "Apache.NMS.MQTT.ConnectionFactory");
            schemaProviderFactoryMap["msmq"] =
                new ProviderFactoryInfo("Apache.NMS.MSMQ", "Apache.NMS.MSMQ.ConnectionFactory");
            schemaProviderFactoryMap["stomp"] =
                new ProviderFactoryInfo("Apache.NMS.Stomp", "Apache.NMS.Stomp.ConnectionFactory");
            schemaProviderFactoryMap["xms"] =
                new ProviderFactoryInfo("Apache.NMS.XMS", "Apache.NMS.XMS.ConnectionFactory");
            schemaProviderFactoryMap["zmq"] =
                new ProviderFactoryInfo("Apache.NMS.ZMQ", "Apache.NMS.ZMQ.ConnectionFactory");
            schemaProviderFactoryMap["amqp"] =
                new ProviderFactoryInfo("Apache.NMS.AMQP", "Apache.NMS.AMQP.ConnectionFactory");
        }

        /// <summary>
        /// The ConnectionFactory object must define a constructor that takes as a minimum a Uri object.
        /// Any additional parameters are optional, but will typically include a Client ID string.
        /// </summary>
        /// <param name="providerURI">The URI for the ActiveMQ provider.</param>
        /// <param name="constructorParams">Optional parameters to use when creating the ConnectionFactory.</param>
        public NMSConnectionFactory(string providerURI, params object[] constructorParams)
            : this(URISupport.CreateCompatibleUri(providerURI), constructorParams)
        {
        }

        /// <summary>
        /// The ConnectionFactory object must define a constructor that takes as a minimum a Uri object.
        /// Any additional parameters are optional, but will typically include a Client ID string.
        /// </summary>
        /// <param name="uriProvider">The URI for the ActiveMQ provider.</param>
        /// <param name="constructorParams">Optional parameters to use when creating the ConnectionFactory.</param>
        public NMSConnectionFactory(Uri uriProvider, params object[] constructorParams)
        {
            this.factory = CreateConnectionFactory(uriProvider, constructorParams);
        }

        /// <summary>
        /// Create a connection factory that can create connections for the given scheme in the URI.
        /// </summary>
        /// <param name="uriProvider">The URI for the ActiveMQ provider.</param>
        /// <param name="constructorParams">Optional parameters to use when creating the ConnectionFactory.</param>
        /// <returns>A <see cref="IConnectionFactory" /> implementation that will be used.</returns>
        public static IConnectionFactory CreateConnectionFactory(Uri uriProvider, params object[] constructorParams)
        {
            IConnectionFactory connectionFactory = null;

            try
            {
                Type factoryType = GetTypeForScheme(uriProvider.Scheme);

                // If an implementation was found, try to instantiate it.
                if (factoryType != null)
                {
#if NETCF
					// Compact framework does not allow the activator ta pass parameters to a constructor.
					connectionFactory = (IConnectionFactory) Activator.CreateInstance(factoryType);
					connectionFactory.BrokerUri = uriProvider;
#else
                    object[] parameters = MakeParameterArray(uriProvider, constructorParams);
                    connectionFactory = (IConnectionFactory) Activator.CreateInstance(factoryType, parameters);
#endif
                }

                if (null == connectionFactory)
                {
                    throw new NMSConnectionException("No IConnectionFactory implementation found for connection URI: " +
                                                     uriProvider);
                }
            }
            catch (NMSConnectionException)
            {
                throw;
            }
            catch (Exception ex)
            {
                throw new NMSConnectionException(
                    "Could not create the IConnectionFactory implementation: " + ex.Message, ex);
            }

            return connectionFactory;
        }

        /// <summary>
        /// Finds the <see cref="System.Type" /> associated with the given scheme.
        /// </summary>
        /// <param name="scheme">The scheme (e.g. <c>tcp</c>, <c>activemq</c> or <c>stomp</c>).</param>
        /// <returns>The <see cref="System.Type" /> of the ConnectionFactory that will be used
        /// to create the connection for the specified <paramref name="scheme" />.</returns>
        private static Type GetTypeForScheme(string scheme)
        {
            string[] paths = GetConfigSearchPaths();
            string assemblyFileName;
            string factoryClassName;
            Type factoryType = null;

            Tracer.DebugFormat("Locating provider for scheme: {0}", scheme);
            if (LookupConnectionFactoryInfo(paths, scheme, out assemblyFileName, out factoryClassName))
            {
                Assembly assembly = null;

                Tracer.DebugFormat("Attempting to load provider assembly: {0}", assemblyFileName);
                try
                {
                    assembly = Assembly.Load(assemblyFileName);
                    if (null != assembly)
                    {
                        Tracer.Debug("Succesfully loaded provider.");
                    }
                }
                catch (Exception ex)
                {
                    Tracer.ErrorFormat("Exception loading assembly failed: {0}", ex.Message);
                    assembly = null;
                }

                if (null == assembly)
                {
                    foreach (string path in paths)
                    {
                        string fullpath = Path.Combine(path, assemblyFileName) + ".dll";

                        Tracer.DebugFormat("Looking for: {0}", fullpath);
                        if (File.Exists(fullpath))
                        {
                            Tracer.Debug("\tAssembly found!  Attempting to load...");
                            try
                            {
                                assembly = Assembly.LoadFrom(fullpath);
                            }
                            catch (Exception ex)
                            {
                                Tracer.ErrorFormat("Exception loading assembly failed: {0}", ex.Message);
                                assembly = null;
                            }

                            if (null != assembly)
                            {
                                Tracer.Debug("Successfully loaded provider.");
                                break;
                            }

                            Tracer.Debug("Failed to load provider.  Continuing search...");
                        }
                    }
                }

                if (null != assembly)
                {
#if NETCF
					factoryType = assembly.GetType(factoryClassName, true);
#else
                    factoryType = assembly.GetType(factoryClassName, true, true);
#endif
                    if (null == factoryType)
                    {
                        Tracer.Fatal("Failed to load class factory from provider.");
                    }
                }
                else
                {
                    Tracer.Fatal("Failed to load provider assembly.");
                }
            }

            return factoryType;
        }

        /// <summary>
        /// Lookup the connection factory assembly filename and class name.
        /// Read an external configuration file that maps scheme to provider implementation.
        /// Load XML config files named: nmsprovider-{scheme}.config
        /// Following is a sample configuration file named nmsprovider-jms.config.  Replace
        /// the parenthesis with angle brackets for proper XML formatting.
        ///
        ///     (?xml version="1.0" encoding="utf-8" ?)
        ///     (configuration)
        ///         (provider assembly="MyCompany.NMS.JMSProvider.dll" classFactory="MyCompany.NMS.JMSProvider.ConnectionFactory"/)
        ///     (/configuration)
        ///
        /// This configuration file would be loaded and parsed when a connection uri with a scheme of 'jms'
        /// is used for the provider.  In this example the connection string might look like:
        ///     jms://localhost:7222
        ///
        /// </summary>
        /// <param name="paths">Folder paths to look in.</param>
        /// <param name="scheme">The scheme.</param>
        /// <param name="assemblyFileName">Name of the assembly file.</param>
        /// <param name="factoryClassName">Name of the factory class.</param>
        /// <returns><c>true</c> if the configuration file for the specified <paramref name="scheme" /> could
        /// be found; otherwise, <c>false</c>.</returns>
        private static bool LookupConnectionFactoryInfo(string[] paths, string scheme, out string assemblyFileName,
            out string factoryClassName)
        {
            bool foundFactory = false;
            string schemeLower = scheme.ToLower();
            ProviderFactoryInfo pfi;

            // Look for a custom configuration to handle this scheme.
            string configFileName = String.Format("nmsprovider-{0}.config", schemeLower);

            assemblyFileName = String.Empty;
            factoryClassName = String.Empty;

            Tracer.DebugFormat("Attempting to locate provider configuration: {0}", configFileName);
            foreach (string path in paths)
            {
                string fullpath = Path.Combine(path, configFileName);
                Tracer.DebugFormat("Looking for: {0}", fullpath);

                try
                {
                    if (File.Exists(fullpath))
                    {
                        Tracer.DebugFormat("\tConfiguration file found in {0}", fullpath);
                        XmlDocument configDoc = new XmlDocument();

                        configDoc.Load(fullpath);
                        XmlElement providerNode = (XmlElement) configDoc.SelectSingleNode("/configuration/provider");

                        if (null != providerNode)
                        {
                            assemblyFileName = providerNode.GetAttribute("assembly");
                            factoryClassName = providerNode.GetAttribute("classFactory");
                            if (!String.IsNullOrEmpty(assemblyFileName) && !String.IsNullOrEmpty(factoryClassName))
                            {
                                foundFactory = true;
                                Tracer.DebugFormat("Selected custom provider for {0}: {1}, {2}", schemeLower,
                                    assemblyFileName, factoryClassName);
                                break;
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    Tracer.DebugFormat("Exception while scanning {0}: {1}", fullpath, ex.Message);
                }
            }

            if (!foundFactory)
            {
                // Check for standard provider implementations.
                if (schemaProviderFactoryMap.TryGetValue(schemeLower, out pfi))
                {
                    assemblyFileName = pfi.assemblyFileName;
                    factoryClassName = pfi.factoryClassName;
                    foundFactory = true;
                    Tracer.DebugFormat("Selected standard provider for {0}: {1}, {2}", schemeLower, assemblyFileName,
                        factoryClassName);
                }
            }

            return foundFactory;
        }

        /// <summary>
        /// Get an array of search paths to look for config files.
        /// </summary>
        /// <returns>
        /// A collection of search paths, including the current directory, the current AppDomain's
        /// BaseDirectory and the current AppDomain's RelativeSearchPath.
        /// </returns>
        private static string[] GetConfigSearchPaths()
        {
            ArrayList pathList = new ArrayList();

            // Check the current folder first.
            pathList.Add("");
#if !NETCF
            try
            {
                AppDomain currentDomain = AppDomain.CurrentDomain;

                // Check the folder the assembly is located in.
                Assembly executingAssembly = Assembly.GetExecutingAssembly();
                try
                {
                    pathList.Add(Path.GetDirectoryName(executingAssembly.Location));
                }
                catch (Exception ex)
                {
                    Tracer.DebugFormat("Error parsing executing assembly location: {0} : {1}",
                        executingAssembly.Location, ex.Message);
                }

                if (null != currentDomain.BaseDirectory)
                {
                    pathList.Add(currentDomain.BaseDirectory);
                }

                if (null != currentDomain.RelativeSearchPath)
                {
                    pathList.Add(currentDomain.RelativeSearchPath);
                }
            }
            catch (Exception ex)
            {
                Tracer.DebugFormat("Error configuring search paths: {0}", ex.Message);
            }
#endif

            return (string[]) pathList.ToArray(typeof(string));
        }

        /// <summary>
        /// Converts a <c>params object[]</c> collection into a plain <c>object[]</c>s, to pass to the constructor.
        /// </summary>
        /// <param name="firstParam">The first parameter in the collection.</param>
        /// <param name="varParams">The remaining parameters.</param>
        /// <returns>An array of <see cref="Object" /> instances.</returns>
        private static object[] MakeParameterArray(object firstParam, params object[] varParams)
        {
            ArrayList paramList = new ArrayList();
            paramList.Add(firstParam);
            foreach (object param in varParams)
            {
                paramList.Add(param);
            }

            return paramList.ToArray();
        }

        /// <summary>
        /// Creates a new connection.
        /// </summary>
        /// <returns>An <see cref="IConnection" /> created by the requested ConnectionFactory.</returns>
        public IConnection CreateConnection()
        {
            return this.factory.CreateConnection();
        }

        /// <summary>
        /// Creates a new connection with the given <paramref name="userName" /> and <paramref name="password" /> credentials.
        /// </summary>
        /// <param name="userName">The username to use when establishing the connection.</param>
        /// <param name="password">The password to use when establishing the connection.</param>
        /// <returns>An <see cref="IConnection" /> created by the requested ConnectionFactory.</returns>
        public IConnection CreateConnection(string userName, string password)
        {
            return this.factory.CreateConnection(userName, password);
        }

        public Task<IConnection> CreateConnectionAsync()
        {
            return this.factory.CreateConnectionAsync();
        }

        public Task<IConnection> CreateConnectionAsync(string userName, string password)
        {
            return this.factory.CreateConnectionAsync(userName, password);
        }

        public INMSContext CreateContext()
        {
            return this.factory.CreateContext();
        }

        public INMSContext CreateContext(AcknowledgementMode acknowledgementMode)
        {
            return this.factory.CreateContext(acknowledgementMode);
        }

        public INMSContext CreateContext(string userName, string password)
        {
            return this.factory.CreateContext(userName, password);
        }

        public INMSContext CreateContext(string userName, string password, AcknowledgementMode acknowledgementMode)
        {
            return this.factory.CreateContext(userName, password, acknowledgementMode);
        }

        public Task<INMSContext> CreateContextAsync()
        {
            return this.factory.CreateContextAsync();
        }

        public Task<INMSContext> CreateContextAsync(AcknowledgementMode acknowledgementMode)
        {
            return this.factory.CreateContextAsync(acknowledgementMode);
        }

        public Task<INMSContext> CreateContextAsync(string userName, string password)
        {
            return this.factory.CreateContextAsync(userName, password);
        }

        public Task<INMSContext> CreateContextAsync(string userName, string password, AcknowledgementMode acknowledgementMode)
        {
            return this.factory.CreateContextAsync(userName, password, acknowledgementMode);
        }

        /// <summary>
        /// Get/or set the broker Uri.
        /// </summary>
        public Uri BrokerUri
        {
            get { return ConnectionFactory.BrokerUri; }
            set { ConnectionFactory.BrokerUri = value; }
        }

        /// <summary>
        /// The actual IConnectionFactory implementation that is being used.  This implementation
        /// depends on the scheme of the URI used when constructed.
        /// </summary>
        public IConnectionFactory ConnectionFactory
        {
            get { return factory; }
        }

        /// <summary>
        /// Get/or Set the IRedeliveryPolicy instance using the IConnectionFactory implementation
        /// that is being used.
        /// </summary>
        public IRedeliveryPolicy RedeliveryPolicy
        {
            get { return this.factory.RedeliveryPolicy; }
            set { this.factory.RedeliveryPolicy = value; }
        }

        /// <summary>
        /// Get/or Set the ConsumerTransformerDelegate using the IConnectionFactory implementation
        /// that is currently being used.
        /// </summary>
        public ConsumerTransformerDelegate ConsumerTransformer
        {
            get { return this.factory.ConsumerTransformer; }
            set { this.factory.ConsumerTransformer = value; }
        }

        /// <summary>
        /// Get/or Set the ProducerTransformerDelegate using the IConnectionFactory implementation
        /// that is currently being used.
        /// </summary>
        public ProducerTransformerDelegate ProducerTransformer
        {
            get { return this.factory.ProducerTransformer; }
            set { this.factory.ProducerTransformer = value; }
        }
    }
}