/*
 * 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.Threading;
using System.Text;
using System.Net;
using Apache.NMS.ActiveMQ.Commands;
using Apache.NMS.ActiveMQ.State;
using Apache.NMS.ActiveMQ.Threads;
using Apache.NMS.Util;

namespace Apache.NMS.ActiveMQ.Transport.Failover
{
    /// <summary>
    /// A Transport that is made reliable by being able to fail over to another
    /// transport when a transport failure is detected.
    /// </summary>
    public class FailoverTransport : ICompositeTransport, IComparable
    {
		private static int DEFAULT_INITIAL_RECONNECT_DELAY = 10;
		private static int INFINITE = -1;

        private static int idCounter = 0;
        private readonly int id;

        private bool disposed;
        private bool connected;
        private readonly List<Uri> uris = new List<Uri>();
        private readonly List<Uri> updated = new List<Uri>();

        private CommandHandler commandHandler;
        private ExceptionHandler exceptionHandler;
        private InterruptedHandler interruptedHandler;
        private ResumedHandler resumedHandler;

		private readonly CountDownLatch listenerLatch = new CountDownLatch(4);
        private readonly Mutex reconnectMutex = new Mutex();
        private readonly Mutex backupMutex = new Mutex();
        private readonly Mutex sleepMutex = new Mutex();
        private readonly ConnectionStateTracker stateTracker = new ConnectionStateTracker();
        private readonly Dictionary<int, Command> requestMap = new Dictionary<int, Command>();

        private Uri connectedTransportURI;
        private Uri failedConnectTransportURI;
        private readonly AtomicReference<ITransport> connectedTransport = new AtomicReference<ITransport>(null);
        private TaskRunner reconnectTask = null;
        private bool started;
        private bool initialized;
        private int initialReconnectDelay = DEFAULT_INITIAL_RECONNECT_DELAY;
        private int maxReconnectDelay = 1000 * 30;
        private int backOffMultiplier = 2;
        private int timeout = INFINITE;
        private bool useExponentialBackOff = true;
        private bool randomize = true;
        private int maxReconnectAttempts = INFINITE;
        private int startupMaxReconnectAttempts = INFINITE;
        private int connectFailures;
        private int reconnectDelay = DEFAULT_INITIAL_RECONNECT_DELAY;
        private Exception connectionFailure;
        private bool firstConnection = true;
        private bool backup = false;
        private readonly List<BackupTransport> backups = new List<BackupTransport>();
        private int backupPoolSize = 1;
        private bool trackMessages = false;
    	private bool trackTransactionProducers = true;
        private int maxCacheSize = 256;
        private volatile Exception failure;
        private readonly object mutex = new object();
        private bool reconnectSupported = true;
        private bool updateURIsSupported = true;
    	private bool doRebalance = false;
    	private bool connectedToPriority = false;
	 	private bool priorityBackup = false;
    	private List<Uri> priorityList = new List<Uri>();
    	private bool priorityBackupAvailable = false;
        private String sslProtocol = null;

		// Not Sure how to work these back in with all the changes.
		//private int asyncTimeout = 45000;
        //private bool asyncConnect = false;

        public FailoverTransport()
        {
            id = idCounter++;

            stateTracker.TrackTransactions = true;
            reconnectTask = DefaultThreadPools.DefaultTaskRunnerFactory.CreateTaskRunner(
                new FailoverTask(this), "ActiveMQ Failover Worker: " + this.GetHashCode().ToString());
        }

        ~FailoverTransport()
        {
            Dispose(false);
        }

        #region FailoverTask

        private class FailoverTask : Task
        {
            private readonly FailoverTransport parent;

            public FailoverTask(FailoverTransport p)
            {
                parent = p;
            }

            public bool Iterate()
            {
                bool result = false;
                if (!parent.IsStarted)
                {
                    return false;
                }

                bool buildBackup = true;
                lock (parent.backupMutex) 
				{
                    if ((parent.connectedTransport.Value == null || parent.doRebalance || parent.priorityBackupAvailable) && !parent.disposed)
					{
                        result = parent.DoConnect();
                        buildBackup = false;
                    }
                }
                if (buildBackup) 
				{
                    parent.BuildBackups();
                    if (parent.priorityBackup && !parent.connectedToPriority) 
					{
                        try 
						{
                            parent.DoDelay();
                            if (parent.reconnectTask == null)
							{
                                return true;
                            }
                            parent.reconnectTask.Wakeup();
                        } 
						catch (ThreadInterruptedException) 
						{
                        	Tracer.Debug("Reconnect task has been interrupted.");
                        }
                    }
                }
				else 
				{
                    try 
					{
                        if (parent.reconnectTask == null) 
						{
                            return true;
                        }
                        parent.reconnectTask.Wakeup();
                    }
					catch (ThreadInterruptedException) 
					{
                        Tracer.Debug("Reconnect task has been interrupted.");
                    }
                }
                return result;
            }
        }

        #endregion

        #region Property Accessors

        public CommandHandler Command
        {
            get { return commandHandler; }
            set 
			{ 
				commandHandler = value; 
				listenerLatch.countDown();
			}
        }

        public ExceptionHandler Exception
        {
            get { return exceptionHandler; }
            set 
			{ 
				exceptionHandler = value; 
				listenerLatch.countDown();
			}
        }

        public InterruptedHandler Interrupted
        {
            get { return interruptedHandler; }
            set 
			{ 
				this.interruptedHandler = value; 
				this.listenerLatch.countDown();
			}
        }

        public ResumedHandler Resumed
        {
            get { return resumedHandler; }
            set 
			{ 
				this.resumedHandler = value; 
				this.listenerLatch.countDown();
			}
        }

        internal Exception Failure
        {
            get { return failure; }
            set
            {
                lock(mutex)
                {
                    failure = value;
                }
            }
        }

        public int Timeout
        {
            get { return this.timeout; }
            set { this.timeout = value; }
        }

        public int InitialReconnectDelay
        {
            get { return initialReconnectDelay; }
            set { initialReconnectDelay = value; }
        }

        public int MaxReconnectDelay
        {
            get { return maxReconnectDelay; }
            set { maxReconnectDelay = value; }
        }

        public int ReconnectDelay
        {
            get { return reconnectDelay; }
            set { reconnectDelay = value; }
        }

        public int ReconnectDelayExponent
        {
            get { return backOffMultiplier; }
            set { backOffMultiplier = value; }
        }

        public ITransport ConnectedTransport
        {
            get { return connectedTransport.Value; }
            set { connectedTransport.Value = value; }
        }

        public Uri ConnectedTransportURI
        {
            get { return connectedTransportURI; }
            set { connectedTransportURI = value; }
        }

        public int MaxReconnectAttempts
        {
            get { return maxReconnectAttempts; }
            set { maxReconnectAttempts = value; }
        }

        public int StartupMaxReconnectAttempts
        {
            get { return startupMaxReconnectAttempts; }
            set { startupMaxReconnectAttempts = value; }
        }

        public bool Randomize
        {
            get { return randomize; }
            set { randomize = value; }
        }

        public bool Backup
        {
            get { return backup; }
            set { backup = value; }
        }

		public bool PriorityBackup
		{
			get { return priorityBackup; }
			set { this.priorityBackup = value; }
		}

	    public String PriorityURIs
		{
			get { return PrintableUriList(priorityList); }
			set { this.ProcessDelimitedUriList(value, priorityList); }
	    }

        public int BackupPoolSize
        {
            get { return backupPoolSize; }
            set { backupPoolSize = value; }
        }

        public bool TrackMessages
        {
            get { return trackMessages; }
            set { trackMessages = value; }
        }

		public bool TrackTransactionProducers
		{
			get { return trackTransactionProducers; }
			set { this.trackTransactionProducers = value; }
		}

        public int MaxCacheSize
        {
            get { return maxCacheSize; }
            set { maxCacheSize = value; }
        }

        public bool UseExponentialBackOff
        {
            get { return useExponentialBackOff; }
            set { useExponentialBackOff = value; }
        }

        public IWireFormat WireFormat
        {
            get
            {
                ITransport transport = ConnectedTransport;
                if(transport != null)
                {
                    return transport.WireFormat;
                }

                return null;
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether to asynchronously connect to sockets
        /// </summary>
        /// <value><c>true</c> if [async connect]; otherwise, <c>false</c>.</value>
        public bool AsyncConnect
        {
            set { }
        }

        /// <summary>
        /// If doing an asynchronous connect, the milliseconds before timing out if no connection can be made
        /// </summary>
        /// <value>The async timeout.</value>
        public int AsyncTimeout
        {
            get { return 0; }
            set { }
        }

        public ConnectionStateTracker StateTracker
        {
            get { return this.stateTracker; }
        }

        #endregion

        public bool IsFaultTolerant
        {
            get { return true; }
        }

        public bool IsDisposed
        {
            get { return disposed; }
        }

        public bool IsConnected
        {
            get { return connected; }
        }

        public bool IsConnectedToPriority
        {
            get { return connectedToPriority; }
        }

        public bool IsStarted
        {
            get { return started; }
        }

        public bool IsReconnectSupported
        {
            get { return this.reconnectSupported; }
        }

        public bool IsUpdateURIsSupported
        {
            get { return this.updateURIsSupported; }
        }

        public void OnException(ITransport sender, Exception error)
        {
            try
            {
                HandleTransportFailure(error);
            }
            catch(Exception)
            {
				this.Exception(this, new IOException("Unexpected Transport Failure."));
            }
        }

        public void DisposedOnCommand(ITransport sender, Command c)
        {
        }

        public void DisposedOnException(ITransport sender, Exception e)
        {
        }

        public void HandleTransportFailure(Exception e)
        {
            ITransport transport = connectedTransport.GetAndSet(null);
	        if (transport == null) 
			{
	            // sync with possible in progress reconnect
	            lock(reconnectMutex) 
				{
	                transport = connectedTransport.GetAndSet(null);
	            }
	        }

			if(transport != null)
            {
				DisposeTransport(transport);

	            bool reconnectOk = false;
	            lock(reconnectMutex) 
				{
	                if (CanReconnect()) 
					{
                    	Tracer.WarnFormat("Transport failed to {0}, attempting to automatically reconnect due to: {1}", 
						                  ConnectedTransportURI, e.Message);
	                    reconnectOk = true;
	                }

                    initialized = false;
                    failedConnectTransportURI = ConnectedTransportURI;
                    ConnectedTransportURI = null;
					connectedToPriority = false;
                    connected = false;

	                if (reconnectOk) 
					{
	                    if(this.Interrupted != null)
	                    {
	                        this.Interrupted(transport);
	                    }

	                    updated.Remove(failedConnectTransportURI);
	                    reconnectTask.Wakeup();
	                }
					else if (!disposed) 
					{
	                    PropagateFailureToExceptionListener(e);
	                }
	            }
            }
        }

	    private bool CanReconnect() 
		{
	        return started && 0 != CalculateReconnectAttemptLimit();
	    }

        public void Start()
        {
            lock(reconnectMutex)
            {
                if(started)
                {
                    Tracer.Debug("FailoverTransport Already Started.");
                    return;
                }

                Tracer.Debug("FailoverTransport Started.");
                started = true;
                stateTracker.MaxCacheSize = MaxCacheSize;
                stateTracker.TrackMessages = TrackMessages;
				stateTracker.TrackTransactionProducers = TrackTransactionProducers;
                if(ConnectedTransport != null)
                {
                    Tracer.Debug("FailoverTransport already connected, start is restoring.");
                    stateTracker.DoRestore(ConnectedTransport);
                }
                else
                {
                    Tracer.Debug("FailoverTransport not connected, start is reconnecting.");
                    Reconnect(false);
                }
            }
        }

        public virtual void Stop()
        {
            ITransport transportToStop = null;
	        List<ITransport> backupsToStop = new List<ITransport>(backups.Count);

			try 
			{
	            lock(reconnectMutex)
	            {
	                if(!started)
	                {
	                    Tracer.Debug("FailoverTransport Already Stopped.");
	                    return;
	                }

	                Tracer.Debug("FailoverTransport Stopped.");
	                started = false;
	                disposed = true;
	                connected = false;
	                if(ConnectedTransport != null)
	                {
	                    transportToStop = connectedTransport.GetAndSet(null);
	                }

	            }
				lock(sleepMutex)
				{
					Monitor.PulseAll(sleepMutex);
				}
			}
			finally
			{
            	if(reconnectTask != null)
            	{
	                reconnectTask.Shutdown();
            	}
			}

	        lock(backupMutex) 
			{
	            foreach (BackupTransport backup in backups) 
				{
	                backup.Disposed = true;
	                ITransport transport = backup.Transport;
	                if (transport != null) 
					{
	                    transport.Command = DisposedOnCommand;
						transport.Exception = DisposedOnException;
	                    backupsToStop.Add(transport);
	                }
	            }
	            backups.Clear();
	        }
	        
			foreach (ITransport transport in backupsToStop) 
			{
	            try 
				{
	                if (Tracer.IsDebugEnabled) 
					{
	                    Tracer.Debug("Stopped backup: " + transport);
	                }
	                DisposeTransport(transport);
	            } 
				catch (Exception) 
				{
	            }
	        }

			if(transportToStop != null)
            {
                transportToStop.Stop();
            }
        }

        public FutureResponse AsyncRequest(Command command)
        {
            throw new ApplicationException("FailoverTransport does not implement AsyncRequest(Command)");
        }

        public Response Request(Command command)
        {
            throw new ApplicationException("FailoverTransport does not implement Request(Command)");
        }

        public Response Request(Command command, TimeSpan ts)
        {
            throw new ApplicationException("FailoverTransport does not implement Request(Command, TimeSpan)");
        }

        public void OnCommand(ITransport sender, Command command)
        {
            if(command != null)
            {
                if(command.IsResponse)
                {
                    Command request = null;
                    lock(((ICollection) requestMap).SyncRoot)
                    {
                        int v = ((Response) command).CorrelationId;
                        try
                        {
                            if(requestMap.TryGetValue(v, out request))
                            {
                                requestMap.Remove(v);
                            }
                        }
                        catch
                        {
                        }
                    }

                    Tracked tracked = request as Tracked;
                    if(tracked != null)
                    {
                        tracked.OnResponse();
                    }
                }

                if(!initialized)
                {
                    initialized = true;
                }

                if(command.IsConnectionControl)
                {
                    this.HandleConnectionControl(command as ConnectionControl);
                }
            }

            this.Command(sender, command);
        }

        public void Oneway(Command command)
        {
            Exception error = null;

            lock(reconnectMutex)
            {
                if(command != null && ConnectedTransport == null)
                {
                    if(command.IsShutdownInfo)
                    {
                        // Skipping send of ShutdownInfo command when not connected.
                        return;
                    }
                    else if(command.IsRemoveInfo || command.IsMessageAck)
                    {
                        stateTracker.Track(command);
                        // Simulate response to RemoveInfo command or a MessageAck
                        // since it would be stale at this point.
                        if(command.ResponseRequired)
                        {
                            OnCommand(this, new Response() { CorrelationId = command.CommandId });
                        }
                        return;
                    }
					else if(command.IsMessagePull) 
					{
                        // Simulate response to MessagePull if timed as we can't honor that now.
                        MessagePull pullRequest = command as MessagePull;
                        if (pullRequest.Timeout != 0) 
						{
                            MessageDispatch dispatch = new MessageDispatch();
                            dispatch.ConsumerId = pullRequest.ConsumerId;
                            dispatch.Destination = pullRequest.Destination;
                            OnCommand(this, dispatch);
                        }
                        return;
                    }
                }

                // Keep trying until the message is sent.
                for(int i = 0; !disposed; i++)
                {
                    try
                    {
                        // Any Ack that was being sent when the connection dropped is now
                        // stale so we don't send it here as it would cause an unmatched ack
                        // on the broker side and probably prevent a consumer from getting
                        // any new messages.
                        if(command.IsMessageAck && i > 0)
                        {
                            Tracer.Debug("Inflight MessageAck being dropped as stale.");
                            if(command.ResponseRequired)
                            {
                                OnCommand(this, new Response() { CorrelationId = command.CommandId });
                            }
                            return;
                        }

                        // Wait for transport to be connected.
                        ITransport transport = ConnectedTransport;
                        DateTime start = DateTime.Now;
                        bool timedout = false;
                        TimeSpan timewait = TimeSpan.FromMilliseconds(-1);

                        while(transport == null && !disposed && connectionFailure == null)
                        {
                            Tracer.Debug("Waiting for transport to reconnect.");

                            int elapsed = (int) (DateTime.Now - start).TotalMilliseconds;
                            if(this.timeout > 0 && elapsed > this.timeout)
                            {
                                timedout = true;
                                Tracer.DebugFormat("FailoverTransport.oneway - timed out after {0} mills", elapsed);
                                break;
                            }

                            if(this.timeout > 0)
                            {
                                // Set the timeout for waiting to be at most 100ms past the maximum timeout length.
                                int remainingTime = (this.timeout - elapsed) + 100;
                                timewait = TimeSpan.FromMilliseconds(remainingTime);
                            }

                            // Release so that the reconnect task can run
                            try
                            {
                                // Wait for something.  The mutex will be pulsed if we connect, or are shut down.
                                Monitor.Wait(reconnectMutex, timewait);
                            }
                            catch(ThreadInterruptedException e)
                            {
                                Tracer.DebugFormat("Interrupted: {0}", e.Message);
                            }

                            transport = ConnectedTransport;
                        }

                        if(transport == null)
                        {
                            // Previous loop may have exited due to use being disposed.
                            if(disposed)
                            {
                                error = new IOException("Transport disposed.");
                            }
                            else if(connectionFailure != null)
                            {
                                error = connectionFailure;
                            }
                            else if(timedout)
                            {
                                error = new IOException("Failover oneway timed out after " + timeout + " milliseconds.");
                            }
                            else
                            {
                                error = new IOException("Unexpected failure.");
                            }
                            break;
                        }

                        // If it was a request and it was not being tracked by
                        // the state tracker, then hold it in the requestMap so
                        // that we can replay it later.
                        Tracked tracked = stateTracker.Track(command);
                        lock(((ICollection) requestMap).SyncRoot)
                        {
                            if(tracked != null && tracked.WaitingForResponse)
                            {
                                requestMap.Add(command.CommandId, tracked);
                            }
                            else if(tracked == null && command.ResponseRequired)
                            {
                                requestMap.Add(command.CommandId, command);
                            }
                        }

                        // Send the message.
                        try
                        {
                            transport.Oneway(command);
                            stateTracker.TrackBack(command);
                        }
                        catch(Exception e)
                        {
                            // If the command was not tracked.. we will retry in this method
                            // otherwise we need to trigger a reconnect before returning as
                            // the transport is failed.
                            if (tracked == null)
                            {
                                // since we will retry in this method.. take it
                                // out of the request map so that it is not
                                // sent 2 times on recovery
                                if(command.ResponseRequired)
                                {
                                    lock(((ICollection) requestMap).SyncRoot)
                                    {
                                        requestMap.Remove(command.CommandId);
                                    }
                                }

                                // Rethrow the exception so it will handled by
                                // the outer catch
                                throw;
                            }
                            else
                            {
								if (Tracer.IsDebugEnabled)
								{
                                	Tracer.DebugFormat("Send Oneway attempt: {0} failed: Message = {1}", 
									                   i, e.Message);
                                	Tracer.DebugFormat("Failed Message Was: {0}", command);
								}
                                HandleTransportFailure(e);
                            }
                        }

                        return;
                    }
                    catch(Exception e)
                    {
						if (Tracer.IsDebugEnabled)
						{
                        	Tracer.DebugFormat("Send Oneway attempt: {0} failed: Message = {1}", 
							                   i, e.Message);
                        	Tracer.DebugFormat("Failed Message Was: {0}", command);
						}
                        HandleTransportFailure(e);
                    }
                }
            }

            if(!disposed)
            {
                if(error != null)
                {
                    throw error;
                }
            }
        }

        public void Add(bool rebalance, Uri[] urisToAdd)
        {
			bool newUri = false;
            lock(uris)
            {
                foreach (Uri uri in urisToAdd)
                {
                    if(!Contains(uri))
                    {
                        uris.Add(uri);
						newUri = true;
                    }
                }
            }

			if (newUri)
			{
            	Reconnect(rebalance);
			}
        }

        public void Add(bool rebalance, String u)
        {
            try
            {
                Add(rebalance, new Uri[] { new Uri(u) });
            }
            catch(Exception e)
            {
                Tracer.ErrorFormat("Failed to parse URI '{0}': {1}", u, e.Message);
            }
        }

        public void Remove(bool rebalance, Uri[] u)
        {
            lock(uris)
            {
                for(int i = 0; i < u.Length; i++)
                {
                    uris.Remove(u[i]);
                }
            }

            Reconnect(rebalance);
        }

        public void Remove(bool rebalance, String u)
        {
            try
            {
                Remove(rebalance, new Uri[] { new Uri(u) });
            }
            catch(Exception e)
            {
                Tracer.ErrorFormat("Failed to parse URI '{0}': {1}", u, e.Message);
            }
        }

        public void Reconnect(Uri uri)
        {
            Add(true, new Uri[] { uri });
        }

	    public void Reconnect(bool rebalance)
		{
			lock(reconnectMutex) 
			{
	            if(started) 
				{
	                if (rebalance) 
					{
	                    doRebalance = true;
	                }
                    Tracer.Debug("Waking up reconnect task");
	                try 
					{
	                    reconnectTask.Wakeup();
	                } 
					catch (ThreadInterruptedException) 
					{
	                }
	            } 
				else 
				{
                    Tracer.Debug("Reconnect was triggered but transport is not started yet. Wait for start to connect the transport.");
	            }
	        }
	    }

        private List<Uri> ConnectList
        {
            get
            {
				if (updated.Count != 0)
				{
					return updated;
				}

                List<Uri> l = new List<Uri>(uris);
                bool removed = false;
                if(failedConnectTransportURI != null)
                {
                    removed = l.Remove(failedConnectTransportURI);
                }

                if(Randomize)
                {
					Shuffle(l);
                }

                if(removed)
                {
                    l.Add(failedConnectTransportURI);
                }

		        if (Tracer.IsDebugEnabled)
				{
					Tracer.DebugFormat("Uri connection list: {0} from: {1}", 
					                   PrintableUriList(l), PrintableUriList(uris));
		        }

                return l;
            }
        }

        protected void RestoreTransport(ITransport t)
        {
            Tracer.Info("Restoring previous transport connection.");
            t.Start();

            // Send information to the broker - informing it we are a fault tolerant client
            t.Oneway(new ConnectionControl() { FaultTolerant = true });
            stateTracker.DoRestore(t);

            Tracer.Info("Sending queued commands...");
            Dictionary<int, Command> tmpMap = null;
            lock(((ICollection) requestMap).SyncRoot)
            {
                tmpMap = new Dictionary<int, Command>(requestMap);
            }

            foreach(Command command in tmpMap.Values)
            {
                if(command.IsMessageAck)
                {
                    Tracer.Debug("Stored MessageAck being dropped as stale.");
                    OnCommand(this, new Response() { CorrelationId = command.CommandId });
                    continue;
                }

                t.Oneway(command);
            }
        }

        public Uri RemoteAddress
        {
            get
            {
                if(ConnectedTransport != null)
                {
                    return ConnectedTransport.RemoteAddress;
                }
                return null;
            }
        }

        public Object Narrow(Type type)
        {
            if(this.GetType().Equals(type))
            {
                return this;
            }
            else if(ConnectedTransport != null)
            {
                return ConnectedTransport.Narrow(type);
            }

            return null;
        }

        private bool DoConnect()
        {
            if (this.sslProtocol != null)
            {
                Tcp.SslContext.GetCurrent().SslProtocol = this.sslProtocol;
            }

            lock(reconnectMutex)
            {
				if (disposed || connectionFailure != null)
				{
					Monitor.PulseAll(reconnectMutex);
				}

            	if ((connectedTransport.Value != null && !doRebalance && !priorityBackupAvailable) || disposed || connectionFailure != null)
				{
                    return false;
                }
                else
                {
                    List<Uri> connectList = ConnectList;
                    if(connectList.Count == 0)
                    {
                        Failure = new NMSConnectionException("No URIs available for connection.");
                    }
                    else
                    {
	                    if (doRebalance)
						{
	                        if (connectedToPriority || CompareUris(connectList[0], connectedTransportURI))
							{
	                            // already connected to first in the list, no need to rebalance
	                            doRebalance = false;
	                            return false;
	                        } 
							else
							{
	                            if (Tracer.IsDebugEnabled)
								{
									Tracer.DebugFormat("Doing rebalance from: {0} to {1}", 
									                   connectedTransportURI, PrintableUriList(connectList));
	                            }
	                            try 
								{
	                                ITransport current = this.connectedTransport.GetAndSet(null);
	                                if (current != null) 
									{
	                                    DisposeTransport(current);
	                                }
	                            } 
								catch (Exception e) 
								{
	                            	if (Tracer.IsDebugEnabled)
									{
										Tracer.DebugFormat("Caught an exception stopping existing " + 
										                   "transport for rebalance {0}", e.Message);
	                                }
	                            }
	                        }

	                        doRebalance = false;
	                    }

	                    ResetReconnectDelay();

	                    ITransport transport = null;
	                    Uri uri = null;

	                    // If we have a backup already waiting lets try it.
	                    lock(backupMutex) 
						{
	                        if ((priorityBackup || backup) && backups.Count > 0)
							{
                            	List<BackupTransport> l = new List<BackupTransport>(backups);
	                            if (randomize) 
								{
									Shuffle(l);
	                            }
								BackupTransport bt = l[0];
								l.RemoveAt(0);
	                            backups.Remove(bt);
	                            transport = bt.Transport;
	                            uri = bt.Uri;
	                            if (priorityBackup && priorityBackupAvailable) 
								{
	                                ITransport old = this.connectedTransport.GetAndSet(null);
	                                if (old != null) 
									{
	                                    DisposeTransport(old);
	                                }
	                                priorityBackupAvailable = false;
	                            }
	                        }
	                    }

	                    // Sleep for the reconnectDelay if there's no backup and we aren't trying
	                    // for the first time, or we were disposed for some reason.
	                    if (transport == null && !firstConnection && (reconnectDelay > 0) && !disposed) 
						{
	                        lock(sleepMutex) 
							{
	                            if (Tracer.IsDebugEnabled)
								{
									Tracer.DebugFormat("Waiting {0} ms before attempting connection.", reconnectDelay);
	                            }
	                            try 
								{
	                                Monitor.Wait(sleepMutex, reconnectDelay);
	                            }
								catch (ThreadInterruptedException)
								{
	                            }
	                        }
	                    }

						IEnumerator<Uri> iter = connectList.GetEnumerator();
	                    while ((transport != null || iter.MoveNext()) && (connectedTransport.Value == null && !disposed))
						{
	                        try 
							{
	                            if (Tracer.IsDebugEnabled)
								{
									Tracer.DebugFormat("Attempting {0}th connect to: {1}",
									                   connectFailures, uri);
	                            }

								// We could be starting with a backup and if so we wait to grab a
	                            // URI from the pool until next time around.
	                            if (transport == null) 
								{
	                                uri = iter.Current;
	                                transport = TransportFactory.CompositeConnect(uri);
	                            }

                                transport.Command = OnCommand;
                                transport.Exception = OnException;
	                            transport.Start();

	                            if (started && !firstConnection) 
								{
	                                RestoreTransport(transport);
	                            }

	                            if (Tracer.IsDebugEnabled)
								{
	                                Tracer.Debug("Connection established");
	                            }
	                            reconnectDelay = initialReconnectDelay;
	                            connectedTransportURI = uri;
	                            connectedTransport.Value = transport;
								connectedToPriority = IsPriority(connectedTransportURI);
	                            Monitor.PulseAll(reconnectMutex);
	                            connectFailures = 0;

								// Try to wait long enough for client to init the event callbacks.
								listenerLatch.await(TimeSpan.FromSeconds(2));

	                            if (Resumed != null) 
								{
	                                Resumed(transport);
	                            }
								else 
								{
	                                if (Tracer.IsDebugEnabled) 
									{
	                                    Tracer.Debug("transport resumed by transport listener not set");
	                                }
	                            }

	                            if (firstConnection) 
								{
	                                firstConnection = false;
	                                Tracer.Info("Successfully connected to " + uri);
	                            }
								else 
								{
	                                Tracer.Info("Successfully reconnected to " + uri);
	                            }

	                            connected = true;
                                if (this.sslProtocol == null)
                                {
                                    this.sslProtocol = Tcp.SslContext.GetCurrent().SslProtocol;
                                }

	                            return false;
	                        }
							catch (Exception e) 
							{
	                            failure = e;
                                if (Tracer.IsDebugEnabled) 
								{
	                                Tracer.Debug("Connect fail to: " + uri + ", reason: " + e.Message);
	                            }
	                            if (transport != null) 
								{
	                                try 
									{
	                                    transport.Stop();
	                                    transport = null;
	                                }
									catch (Exception ee) 
									{
	                                	if (Tracer.IsDebugEnabled) 
										{
	                                        Tracer.Debug("Stop of failed transport: " + transport +
	                                                     " failed with reason: " + ee.Message);
	                                    }
	                                }
	                            }
	                        }
	                    }
					}
				}
            
	            int reconnectLimit = CalculateReconnectAttemptLimit();

	            connectFailures++;
	            if (reconnectLimit != INFINITE && connectFailures >= reconnectLimit) 
				{
					Tracer.ErrorFormat("Failed to connect to {0} after: {1} attempt(s)", 
					                   PrintableUriList(uris), connectFailures);
	                connectionFailure = failure;

	                // Make sure on initial startup, that the transportListener has been
	                // initialized for this instance.
					listenerLatch.await(TimeSpan.FromSeconds(2));
	                PropagateFailureToExceptionListener(connectionFailure);
	                return false;
	            }
	        }

	        if(!disposed)
			{
	            DoDelay();
	        }

	        return !disposed;
        }

        private bool BuildBackups()
        {
            lock(backupMutex)
            {
            	if (!disposed && (backup || priorityBackup) && backups.Count < backupPoolSize) 
				{
	                List<Uri> backupList = new List<Uri>(priorityList);
                    List<Uri> connectList = ConnectList;
	                foreach(Uri uri in connectList) 
					{
	                    if (!backupList.Contains(uri)) 
						{
	                        backupList.Add(uri);
	                    }
	                }
                    foreach(BackupTransport bt in backups)
                    {
                        if(bt.Disposed)
                        {
                            backups.Remove(bt);
                        }
                    }

                    foreach(Uri uri in connectList)
                    {
						if (disposed)
						{
							break;
						}

                        if(ConnectedTransportURI != null && !ConnectedTransportURI.Equals(uri))
                        {
                            try
                            {
                                BackupTransport bt = new BackupTransport(this)
                                {
                                    Uri = uri
                                };

                                if(!backups.Contains(bt))
                                {
                                    ITransport t = TransportFactory.CompositeConnect(uri);
                                    t.Command = bt.OnCommand;
                                    t.Exception = bt.OnException;
                                    t.Start();
                                    bt.Transport = t;
	                                if (priorityBackup && IsPriority(uri))
									{
	                                   priorityBackupAvailable = true;
	                                   backups.Insert(0, bt);
	                                }
									else 
									{
	                                    backups.Add(bt);
	                                }
                                }
                            }
                            catch(Exception e)
                            {
                                Tracer.DebugFormat("Failed to build backup: {0}", e.Message);
                            }
                        }

                        if(backups.Count == BackupPoolSize)
                        {
                            break;
                        }
                    }
                }
            }

            return false;
        }

        public void ConnectionInterruptProcessingComplete(ConnectionId connectionId)
        {
            lock(reconnectMutex)
            {
                Tracer.Debug("Connection Interrupt Processing is complete for ConnectionId: " + connectionId);
                stateTracker.ConnectionInterruptProcessingComplete(this, connectionId);
            }
        }

        public void UpdateURIs(bool rebalance, Uri[] updatedURIs)
        {
            if(IsUpdateURIsSupported)
            {
                Dictionary<Uri, bool> copy = new Dictionary<Uri, bool>();
                foreach(Uri uri in updated)
                {
                    if(uri != null)
                    {
                        copy[uri] = true;
                    }
                }
	
				updated.Clear();

                if(updatedURIs != null && updatedURIs.Length > 0)
                {
                    Dictionary<Uri, bool> uriSet = new Dictionary<Uri, bool>();
                    for(int i = 0; i < updatedURIs.Length; i++)
                    {
                        Uri uri = updatedURIs[i];
                        if(uri != null)
                        {
                            uriSet[uri] = true;
                        }
                    }

                    foreach(Uri uri in uriSet.Keys)
                    {
                        if(!updated.Contains(uri))
                        {
							updated.Add(uri);
                        }
                    }

					if (Tracer.IsDebugEnabled)
					{
						Tracer.DebugFormat("Updated URIs list {0}", PrintableUriList(updated));
					}

	                if (!(copy.Count == 0 && updated.Count == 0) && !copy.Keys.Equals(updated))
					{
	                    BuildBackups();
	                    lock(reconnectMutex) 
						{
	                        Reconnect(rebalance);
	                    }
	                }
                }
            }
        }

        public void HandleConnectionControl(ConnectionControl control)
        {
            string reconnectStr = control.ReconnectTo;

            if(reconnectStr != null)
            {
                reconnectStr = reconnectStr.Trim();
                if(reconnectStr.Length > 0)
                {
                    try
                    {
                        Uri uri = new Uri(reconnectStr);
                        if(IsReconnectSupported)
                        {
                            Tracer.Info("Reconnecting to: " + uri.OriginalString);
                            Reconnect(uri);
                        }
                    }
                    catch(Exception e)
                    {
                        Tracer.ErrorFormat("Failed to handle ConnectionControl reconnect to {0}: {1}", reconnectStr, e);
                    }
                }
            }

            ProcessNewTransports(control.RebalanceConnection, control.ConnectedBrokers);
        }

        private void ProcessNewTransports(bool rebalance, String newTransports)
        {
            if(newTransports != null)
            {
                newTransports = newTransports.Trim();

                if(newTransports.Length > 0 && IsUpdateURIsSupported)
                {
                    List<Uri> list = new List<Uri>();
					ProcessDelimitedUriList(newTransports, list);

                    if(list.Count != 0)
                    {
                        try
                        {
                            UpdateURIs(rebalance, list.ToArray());
                        }
                        catch
                        {
                            Tracer.Error("Failed to update transport URI's from: " + newTransports);
                        }
                    }
                }
            }        
		}

		private void ProcessDelimitedUriList(String priorityUris, List<Uri> target)
		{
            String[] tokens = priorityUris.Split(new Char[] { ',' });

            foreach(String str in tokens)
            {
                try
                {
                    Uri uri = new Uri(str);
                    target.Add(uri);

					if (Tracer.IsDebugEnabled)
					{
						Tracer.DebugFormat("Adding new Uri[{0}] to list,", uri);
					}
                }
                catch (Exception e)
                {
					Tracer.ErrorFormat("Failed to parse broker address: {0} because of: {1}",
					                   str, e.Message);
                }
            }
		}

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        public void Dispose(bool disposing)
        {
            this.Stop();
            disposed = true;
        }

        public int CompareTo(Object o)
        {
            if(o is FailoverTransport)
            {
                FailoverTransport oo = o as FailoverTransport;

                return this.id - oo.id;
            }
            else
            {
                throw new ArgumentException();
            }
        }

        public override String ToString()
        {
            return ConnectedTransportURI == null ? "unconnected" : ConnectedTransportURI.ToString();
        }

	    internal bool IsPriority(Uri uri) 
		{
			if (priorityBackup)
			{
		        if (priorityList.Count > 0) 
				{
		            return priorityList.Contains(uri);
		        }

				if (this.uris.Count > 0) 
				{
		        	return uris[0].Equals(uri);
				}
			}
			return false;
	    }

		public void DisposeTransport(ITransport transport) 
		{
			transport.Command = DisposedOnCommand;
			transport.Exception = DisposedOnException;

			try 
			{
	            transport.Stop();
        	}
			catch (Exception e) 
			{
				Tracer.DebugFormat("Could not stop transport: {0]. Reason: {1}", transport, e.Message);
        	}
    	}

	    private void ResetReconnectDelay() 
		{
	        if (!useExponentialBackOff || reconnectDelay == DEFAULT_INITIAL_RECONNECT_DELAY) 
			{
	            reconnectDelay = initialReconnectDelay;
	        }
	    }

	    private void DoDelay()
		{
	        if (reconnectDelay > 0) 
			{
	            lock(sleepMutex) 
				{
	                if (Tracer.IsDebugEnabled) 
					{
						Tracer.DebugFormat("Waiting {0} ms before attempting connection", reconnectDelay);
	                }
	                try 
					{
						Monitor.Wait(sleepMutex, reconnectDelay);
	                } 
					catch (ThreadInterruptedException) 
					{
	                }
	            }
	        }

	        if (useExponentialBackOff) 
			{
	            // Exponential increment of reconnect delay.
	            reconnectDelay *= backOffMultiplier;
	            if (reconnectDelay > maxReconnectDelay) 
				{
	                reconnectDelay = maxReconnectDelay;
	            }
	        }
	    }

	    private void PropagateFailureToExceptionListener(Exception exception) 
		{
	        if (Exception != null) 
			{
                Exception(this, exception);
	        }
			else
			{
				Exception(this, new IOException());
			}
			Monitor.PulseAll(reconnectMutex);
	    }

	    private int CalculateReconnectAttemptLimit() 
		{
	        int maxReconnectValue = this.maxReconnectAttempts;
	        if (firstConnection && this.startupMaxReconnectAttempts != INFINITE) 
			{
	            maxReconnectValue = this.startupMaxReconnectAttempts;
	        }
	        return maxReconnectValue;
	    }

		public void Shuffle<T>(List<T> list)  
		{  
            Random random = new Random(DateTime.Now.Millisecond);
		    int index = list.Count;  
		    while (index > 1) 
			{  
		        index--;  
		        int k = random.Next(index + 1);  
		        T value = list[k];  
		        list[k] = list[index];  
		        list[index] = value;  
		    }  
		}

		private String PrintableUriList(List<Uri> uriList)
		{
			if (uriList.Count == 0)
			{
				return "";
			}

			StringBuilder builder = new StringBuilder();
			for (int i = 0; i < uriList.Count; ++i)
			{
				builder.Append(uriList[i]);
				if (i < (uriList.Count - 1))
				{
					builder.Append(",");
				}
			}

			return builder.ToString();
		}

		private bool CompareUris(Uri first, Uri second) 
		{
			bool result = false;
            if (first.Port == second.Port)
			{
                IPHostEntry firstAddr = null;
                IPHostEntry secondAddr = null;
                try 
				{
            		firstAddr = Dns.GetHostEntry(first.Host);
            		secondAddr = Dns.GetHostEntry(second.Host);

	                if (firstAddr.Equals(secondAddr)) 
					{
						result = true;
	                }
				} 
				catch(Exception e)
				{
                    if (firstAddr == null) 
					{
						Tracer.WarnFormat("Failed to Lookup IPHostEntry for URI[{0}] : {1}", first, e);
                    } 
					else 
					{
						Tracer.WarnFormat("Failed to Lookup IPHostEntry for URI[{0}] : {1}", second, e);
                    }

					if(String.Equals(first.Host, second.Host, StringComparison.CurrentCultureIgnoreCase))
					{
						result = true;
                    }
                }

            }

			return result;
		}

	    private bool Contains(Uri newURI) 
		{
	        bool result = false;
	        foreach (Uri uri in uris) 
			{
	            if (CompareUris(newURI, uri))
				{
					result = true;
					break;
	            }
	        }

	        return result;
	    }
    }
}
