/*
 * 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.Specialized;
using System.Net;
using System.Net.Sockets;
using Apache.NMS.ActiveMQ.OpenWire;
using Apache.NMS.Util;

namespace Apache.NMS.ActiveMQ.Transport.Tcp
{
    public class TcpTransportFactory : ITransportFactory
    {
        public TcpTransportFactory()
        {
        }

        #region Properties

        private bool useLogging = false;
        public bool UseLogging
        {
            get { return useLogging; }
            set { useLogging = value; }
        }

        /// <summary>
        /// Should the Inactivity Monitor be enabled on this Transport.
        /// </summary>
        private bool useInactivityMonitor = true;
        public bool UseInactivityMonitor
        {
           get { return this.useInactivityMonitor; }
           set { this.useInactivityMonitor = value; }
        }

        /// <summary>
        /// Size in bytes of the receive buffer.
        /// </summary>
        private int receiveBufferSize = 8192;
        public int ReceiveBufferSize
        {
            get { return receiveBufferSize; }
            set { receiveBufferSize = value; }
        }

        /// <summary>
        /// Size in bytes of send buffer.
        /// </summary>
        private int sendBufferSize = 8192;
        public int SendBufferSize
        {
            get { return sendBufferSize; }
            set { sendBufferSize = value; }
        }

        /// <summary>
        /// The time-out value, in milliseconds. The default value is 0, which indicates
        /// an infinite time-out period. Specifying -1 also indicates an infinite time-out period.
        /// </summary>
        private int receiveTimeout = 0;
        public int ReceiveTimeout
        {
            get { return receiveTimeout; }
            set { receiveTimeout = value; }
        }

        /// <summary>
        /// The time-out value, in milliseconds. If you set the property with a value between 1 and 499,
        /// the value will be changed to 500. The default value is 0, which indicates an infinite
        /// time-out period. Specifying -1 also indicates an infinite time-out period.
        /// </summary>
        private int sendTimeout = 0;
        public int SendTimeout
        {
            get { return sendTimeout; }
            set { sendTimeout = value; }
        }

        private TimeSpan requestTimeout = NMSConstants.defaultRequestTimeout;
        public int RequestTimeout
        {
            get { return (int) requestTimeout.TotalMilliseconds; }
            set { requestTimeout = TimeSpan.FromMilliseconds(value); }
        }

        #endregion

        #region ITransportFactory Members

        public ITransport CompositeConnect(Uri location)
        {
            return CompositeConnect(location, null);
        }

        public ITransport CompositeConnect(Uri location, SetTransport setTransport)
        {
            // Extract query parameters from broker Uri
            StringDictionary map = URISupport.ParseQuery(location.Query);

            // Set transport. properties on this (the factory)
            URISupport.SetProperties(this, map, "transport.");

			// See if there is a local address and port specified
			string localAddress = null;
			int localPort = -1;
			
			if(!String.IsNullOrEmpty(location.AbsolutePath) && !location.AbsolutePath.Equals("/"))
			{
				int index = location.AbsolutePath.IndexOf(':');
				try
				{
					localPort = Int16.Parse(location.AbsolutePath.Substring(index + 1));					
					localAddress = location.AbsolutePath.Substring(1, index - 1);
					Tracer.DebugFormat("Binding Socket to {0} on port: {1}", localAddress, localPort);
				}
				catch
				{
            		Tracer.Warn("Invalid Port value on URI for local bind option, ignoring.");
				}
			}
			
            Tracer.Debug("Opening socket to: " + location.Host + " on port: " + location.Port);            
			Socket socket = DoConnect(location.Host, location.Port, localAddress, localPort );
			
#if !NETCF
            socket.ReceiveBufferSize = ReceiveBufferSize;
            socket.SendBufferSize = SendBufferSize;
            socket.ReceiveTimeout = ReceiveTimeout;
            socket.SendTimeout = SendTimeout;
#endif

			OpenWireFormat wireformat = new OpenWireFormat();
			// Set wireformat. properties on the wireformat owned by the tcpTransport
			URISupport.SetProperties(wireformat.PreferredWireFormatInfo, map, "wireFormat.");
            ITransport transport = DoCreateTransport(location, socket, wireformat);

            wireformat.Transport = transport;

            if(UseLogging)
            {
                transport = new LoggingTransport(transport);
            }

            if(UseInactivityMonitor)
            {
               transport = new InactivityMonitor(transport);
            }

            transport = new WireFormatNegotiator(transport, wireformat);
            transport.RequestTimeout = this.requestTimeout;
            if(setTransport != null)
            {
                setTransport(transport, location);
            }

            return transport;
        }

        public ITransport CreateTransport(Uri location)
        {
            ITransport transport = CompositeConnect(location);

            transport = new MutexTransport(transport);
            transport = new ResponseCorrelator(transport);
            transport.RequestTimeout = this.requestTimeout;

            return transport;
        }

        #endregion

		/// <summary>
		/// Override in a subclass to create the specific type of transport that is
		/// being implemented.
		/// </summary>
		protected virtual ITransport DoCreateTransport(Uri location, Socket socket, IWireFormat wireFormat )
		{
			return new TcpTransport(location, socket, wireFormat);
		}
		
        // DISCUSSION: Caching host entries may not be the best strategy when using the
        // failover protocol.  The failover protocol needs to be very dynamic when looking
        // up hostnames at runtime.  If old hostname->IP mappings are kept around, this may
        // lead to runtime failures that could have been avoided by dynamically looking up
        // the new hostname IP.
#if CACHE_HOSTENTRIES
        private static IDictionary<string, IPHostEntry> CachedIPHostEntries = new Dictionary<string, IPHostEntry>();
        private static readonly object _syncLock = new object();
#endif
        public static IPHostEntry GetIPHostEntry(string host)
        {
            IPHostEntry ipEntry;

#if CACHE_HOSTENTRIES
            string hostUpperName = host.ToUpper();

            lock (_syncLock)
            {
                if (!CachedIPHostEntries.TryGetValue(hostUpperName, out ipEntry))
                {
                    try
                    {
                        ipEntry = Dns.GetHostEntry(hostUpperName);
                        CachedIPHostEntries.Add(hostUpperName, ipEntry);
                    }
                    catch
                    {
                        ipEntry = null;
                    }
                }
            }
#else
            try
            {
                ipEntry = Dns.GetHostEntry(host);
            }
            catch
            {
                ipEntry = null;
            }
#endif

            return ipEntry;
        }

        private Socket TryConnectSocket(IPAddress address, int port, string localAddress, int localPort)
        {
            if(null != address)
            {
                try
                {
                    Socket socket = new Socket(address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

                    if(null != socket)
                    {
						if(!String.IsNullOrEmpty(localAddress))
						{
							DoBind(socket, localAddress, localPort);
						}
						
                        socket.Connect(new IPEndPoint(address, port));
                        if(socket.Connected)
                        {
                            return socket;
                        }
                    }
                }
                catch
                {
                }
            }

            return null;
        }

        public static bool TryParseIPAddress(string host, out IPAddress ipaddress)
        {
#if !NETCF
            return IPAddress.TryParse(host, out ipaddress);
#else
            try
            {
                ipaddress = IPAddress.Parse(host);
            }
            catch
            {
                ipaddress = null;
            }

            return (null != ipaddress);
#endif
        }

        public static IPAddress GetIPAddress(string hostname, AddressFamily addressFamily)
        {
            IPAddress ipaddress = null;
            IPHostEntry hostEntry = GetIPHostEntry(hostname);

            if(null != hostEntry)
            {
                ipaddress = GetIPAddress(hostEntry, addressFamily);
            }

            return ipaddress;
        }

        public static IPAddress GetIPAddress(IPHostEntry hostEntry, AddressFamily addressFamily)
        {
            if(null != hostEntry)
            {
                foreach(IPAddress address in hostEntry.AddressList)
                {
                    if(address.AddressFamily == addressFamily)
                    {
                        return address;
                    }
                }
            }

            return null;
        }

        protected Socket DoConnect(string host, int port, string localAddress, int localPort)
        {
            Socket socket = null;
            IPAddress ipaddress;

            try
            {
                if(TryParseIPAddress(host, out ipaddress))
                {
                    socket = TryConnectSocket(ipaddress, port, localAddress, localPort);
                }
                else
                {
                    // Looping through the AddressList allows different type of connections to be tried
                    // (IPv6, IPv4 and whatever else may be available).
                    IPHostEntry hostEntry = GetIPHostEntry(host);

                    if(null != hostEntry)
                    {
                        // Prefer IPv6 first.
                        ipaddress = GetIPAddress(hostEntry, AddressFamily.InterNetworkV6);
                        socket = TryConnectSocket(ipaddress, port, localAddress, localPort);
                        if(null == socket)
                        {
                            // Try IPv4 next.
                            ipaddress = GetIPAddress(hostEntry, AddressFamily.InterNetwork);
                            socket = TryConnectSocket(ipaddress, port, localAddress, localPort);
                            if(null == socket)
                            {
                                // Try whatever else there is.
                                foreach(IPAddress address in hostEntry.AddressList)
                                {
                                    if(AddressFamily.InterNetworkV6 == address.AddressFamily
                                        || AddressFamily.InterNetwork == address.AddressFamily)
                                    {
                                        // Already tried these protocols.
                                        continue;
                                    }

                            		socket = TryConnectSocket(ipaddress, port, localAddress, localPort);
                                    if(null != socket)
                                    {
                                        ipaddress = address;
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }

                if(null == socket)
                {
                    throw new SocketException();
                }
            }
            catch(Exception ex)
            {
                throw new NMSConnectionException(String.Format("Error connecting to {0}:{1}.", host, port), ex);
            }

            Tracer.DebugFormat("Connected to {0}:{1} using {2} protocol.", host, port, ipaddress.AddressFamily.ToString());
            return socket;
        }
		
        protected void DoBind(Socket socket, string host, int port)
        {
            IPAddress ipaddress;

            try
            {
                if(TryParseIPAddress(host, out ipaddress))
                {
                    TryBindSocket(socket, ipaddress, port);
                }
                else
                {
                    // Looping through the AddressList allows different type of connections to be tried
                    // (IPv6, IPv4 and whatever else may be available).
                    IPHostEntry hostEntry = GetIPHostEntry(host);

                    if(null != hostEntry)
                    {
                        // Prefer IPv6 first.
                        ipaddress = GetIPAddress(hostEntry, AddressFamily.InterNetworkV6);
                        if(!TryBindSocket(socket, ipaddress, port))
                        {
                            // Try IPv4 next.
                            ipaddress = GetIPAddress(hostEntry, AddressFamily.InterNetwork);
	                        if(!TryBindSocket(socket, ipaddress, port))
                            {
                                // Try whatever else there is.
                                foreach(IPAddress address in hostEntry.AddressList)
                                {
                                    if(AddressFamily.InterNetworkV6 == address.AddressFamily
                                        || AddressFamily.InterNetwork == address.AddressFamily)
                                    {
                                        // Already tried these protocols.
                                        continue;
                                    }

                        			if(TryBindSocket(socket, ipaddress, port))
                                    {
                                        ipaddress = address;
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }

                if(!socket.IsBound)
                {
                    throw new SocketException();
                }
            }
            catch(Exception ex)
            {
                throw new NMSConnectionException(String.Format("Error binding to {0}:{1}.", host, port), ex);
            }

            Tracer.DebugFormat("Bound to {0}:{1} using.", host, port);
        }		
		
        private bool TryBindSocket(Socket socket, IPAddress address, int port)
        {
            if(null != socket && null != address)
            {
                try
                {
                    socket.Bind(new IPEndPoint(address, port));
                    if(socket.IsBound)
                    {
                        return true;
                    }
                }
                catch
                {
                }
            }

            return false;
        }
		
    }
}
