/*
 * 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.Specialized;
using Apache.NMS.EMS.Util;
using Apache.NMS.Policies;
using Apache.NMS.Util;

namespace Apache.NMS.EMS
{
	/// <summary>
	/// A Factory that can estbalish NMS connections to TIBCO
	/// </summary>
	public class ConnectionFactory : Apache.NMS.IConnectionFactory
	{
		public TIBCO.EMS.ConnectionFactory tibcoConnectionFactory;
		private Uri brokerUri;
		private string clientId;
		private Hashtable properties;
		private bool exceptionOnFTEvents = true;
		private bool exceptionOnFTSwitch = true;
		private int connAttemptCount = Int32.MaxValue;   // Infinite
		private int connAttemptDelay = 30000;            // 30 seconds
		private int connAttemptTimeout = 5000;           // 5 seconds
		private int reconnAttemptCount = Int32.MaxValue; // Infinite
		private int reconnAttemptDelay = 30000;          // 30 seconds
		private int reconnAttemptTimeout = 5000;         // 5 seconds

		private IRedeliveryPolicy redeliveryPolicy = new RedeliveryPolicy();

		public ConnectionFactory()
		{
			try
			{
				this.tibcoConnectionFactory = new TIBCO.EMS.ConnectionFactory();
				ConfigureConnectionFactory();
			}
			catch(Exception ex)
			{
				Apache.NMS.Tracer.DebugFormat("Exception instantiating TIBCO.EMS.ConnectionFactory: {0}", ex.Message);
				ExceptionUtil.WrapAndThrowNMSException(ex);
			}

			VerifyConnectionFactory();
		}

		public ConnectionFactory(Uri serverUrl)
			: this(serverUrl, string.Empty)
		{
		}

		public ConnectionFactory(Uri serverUrl, string clientId)
			: this(serverUrl, clientId, null)
		{
		}

		public ConnectionFactory(string serverUrl)
			: this(new Uri(serverUrl))
		{
		}

		public ConnectionFactory(string serverUrl, string clientId)
			: this(new Uri(serverUrl), clientId)
		{
		}

		public ConnectionFactory(string serverUrl, string clientId, Hashtable properties)
			: this(new Uri(serverUrl), clientId, properties)
		{
		}

		public ConnectionFactory(Uri serverUrl, string clientId, Hashtable properties)
		{
			try
			{
				this.brokerUri = ParseUriProperties(serverUrl);
				this.tibcoConnectionFactory = new TIBCO.EMS.ConnectionFactory(TrimParens(this.brokerUri.AbsolutePath), clientId, properties);
				this.clientId = clientId;
				this.properties = properties;
				ConfigureConnectionFactory();
			}
			catch(Exception ex)
			{
				Apache.NMS.Tracer.DebugFormat("Exception instantiating TIBCO.EMS.ConnectionFactory: {0}", ex.Message);
				ExceptionUtil.WrapAndThrowNMSException(ex);
			}

			VerifyConnectionFactory();
		}

		private void ConfigureConnectionFactory()
		{
			TIBCO.EMS.Tibems.SetExceptionOnFTEvents(this.ExceptionOnFTEvents);
			TIBCO.EMS.Tibems.SetExceptionOnFTSwitch(this.ExceptionOnFTSwitch);

			// Set the initial connection retry settings.
			this.tibcoConnectionFactory.SetConnAttemptCount(this.ConnAttemptCount);
			this.tibcoConnectionFactory.SetConnAttemptDelay(this.ConnAttemptDelay);
			this.tibcoConnectionFactory.SetConnAttemptTimeout(this.ConnAttemptTimeout);

			// Set the failover reconnect retry settings
			this.tibcoConnectionFactory.SetReconnAttemptCount(this.ReconnAttemptCount);
			this.tibcoConnectionFactory.SetReconnAttemptDelay(this.ReconnAttemptDelay);
			this.tibcoConnectionFactory.SetReconnAttemptTimeout(this.ReconnAttemptTimeout);
		}

		private void VerifyConnectionFactory()
		{
			if(null == this.tibcoConnectionFactory)
			{
				throw new Apache.NMS.NMSException("Error instantiating TIBCO connection factory object.");
			}
		}

		#region Connection Factory Properties (configure via URL parameters)

		public bool ExceptionOnFTEvents
		{
			get { return this.exceptionOnFTEvents; }
			set { this.exceptionOnFTEvents = value; }
		}

		public bool ExceptionOnFTSwitch
		{
			get { return this.exceptionOnFTSwitch; }
			set { this.exceptionOnFTSwitch = value; }
		}

		public int ConnAttemptCount
		{
			get { return this.connAttemptCount; }
			set { this.connAttemptCount = value; }
		}

		public int ConnAttemptDelay
		{
			get { return this.connAttemptDelay; }
			set { this.connAttemptDelay = value; }
		}

		public int ConnAttemptTimeout
		{
			get { return this.connAttemptTimeout; }
			set { this.connAttemptTimeout = value; }
		}

		public int ReconnAttemptCount
		{
			get { return this.reconnAttemptCount; }
			set { this.reconnAttemptCount = value; }
		}

		public int ReconnAttemptDelay
		{
			get { return this.reconnAttemptDelay; }
			set { this.reconnAttemptDelay = value; }
		}

		public int ReconnAttemptTimeout
		{
			get { return this.reconnAttemptTimeout; }
			set { this.reconnAttemptTimeout = value; }
		}

		#endregion

		#region IConnectionFactory Members

		/// <summary>
		/// Creates a new connection to TIBCO.
		/// </summary>
		public Apache.NMS.IConnection CreateConnection()
		{
			Apache.NMS.IConnection connection = null;

			try
			{
				connection = EMSConvert.ToNMSConnection(this.tibcoConnectionFactory.CreateConnection());
				ConfigureConnection(connection);
			}
			catch(Exception ex)
			{
				ExceptionUtil.WrapAndThrowNMSException(ex);
			}

			return connection;
		}

		/// <summary>
		/// Creates a new connection to TIBCO.
		/// </summary>
		public Apache.NMS.IConnection CreateConnection(string userName, string password)
		{
			Apache.NMS.IConnection connection = null;

			try
			{
				connection = EMSConvert.ToNMSConnection(this.tibcoConnectionFactory.CreateConnection(userName, password));
				ConfigureConnection(connection);
			}
			catch(Exception ex)
			{
				ExceptionUtil.WrapAndThrowNMSException(ex);
			}

			return connection;
		}

		/// <summary>
		/// Configure the newly created connection.
		/// </summary>
		/// <param name="connection"></param>
		private void ConfigureConnection(IConnection connection)
		{
			connection.RedeliveryPolicy = this.redeliveryPolicy.Clone() as IRedeliveryPolicy;
			connection.ConsumerTransformer = this.consumerTransformer;
			connection.ProducerTransformer = this.producerTransformer;
		}

		/// <summary>
		/// Get/or set the broker Uri.
		/// </summary>
		public Uri BrokerUri
		{
			get { return this.brokerUri; }
			set
			{
				try
				{
					// Create or Re-create the TIBCO connection factory.
					this.brokerUri = ParseUriProperties(value);
					if(null == this.brokerUri)
					{
						this.tibcoConnectionFactory = new TIBCO.EMS.ConnectionFactory();
					}
					else
					{
						if(null == this.clientId)
						{
							this.tibcoConnectionFactory = new TIBCO.EMS.ConnectionFactory(TrimParens(this.brokerUri.AbsolutePath));
						}
						else
						{
							if(null == this.properties)
							{
								this.tibcoConnectionFactory = new TIBCO.EMS.ConnectionFactory(TrimParens(this.brokerUri.AbsolutePath), this.clientId);
							}
							else
							{
								this.tibcoConnectionFactory = new TIBCO.EMS.ConnectionFactory(TrimParens(this.brokerUri.AbsolutePath), this.clientId, this.properties);
							}
						}
					}

					ConfigureConnectionFactory();
				}
				catch(Exception ex)
				{
					ExceptionUtil.WrapAndThrowNMSException(ex);
				}
			}
		}

		private Uri ParseUriProperties(Uri rawUri)
		{
			Tracer.InfoFormat("BrokerUri set = {0}", rawUri.OriginalString);
			Uri parsedUri = rawUri;

			if(!String.IsNullOrEmpty(rawUri.Query) && !rawUri.OriginalString.EndsWith(")"))
			{
				parsedUri = new Uri(rawUri.OriginalString);
				// Since the Uri class will return the end of a Query string found in a Composite
				// URI we must ensure that we trim that off before we proceed.
				string query = parsedUri.Query.Substring(parsedUri.Query.LastIndexOf(")") + 1);

				StringDictionary properties = URISupport.ParseQuery(query);

				StringDictionary connection = URISupport.ExtractProperties(properties, "connection.");
				StringDictionary nms = URISupport.ExtractProperties(properties, "nms.");

				IntrospectionSupport.SetProperties(this, connection, "connection.");
				IntrospectionSupport.SetProperties(this, nms, "nms.");

				parsedUri = URISupport.CreateRemainingUri(parsedUri, properties);
			}

			return parsedUri;
		}

		private string TrimParens(string stringWithParens)
		{
			return stringWithParens.TrimStart('(').TrimEnd(')');
		}

		/// <summary>
		/// Get/or set the redelivery policy that new IConnection objects are
		/// assigned upon creation.
		/// </summary>
		public IRedeliveryPolicy RedeliveryPolicy
		{
			get { return this.redeliveryPolicy; }
			set
			{
				if(value != null)
				{
					this.redeliveryPolicy = value;
				}
			}
		}

		private ConsumerTransformerDelegate consumerTransformer;
		/// <summary>
		/// A Delegate that is called each time a Message is dispatched to allow the client to do
		/// any necessary transformations on the received message before it is delivered.  The
		/// ConnectionFactory sets the provided delegate instance on each Connection instance that
		/// is created from this factory, each connection in turn passes the delegate along to each
		/// Session it creates which then passes that along to the Consumers it creates.
		/// </summary>
		public ConsumerTransformerDelegate ConsumerTransformer
		{
			get { return this.consumerTransformer; }
			set { this.consumerTransformer = value; }
		}

		private ProducerTransformerDelegate producerTransformer;
		/// <summary>
		/// A delegate that is called each time a Message is sent from this Producer which allows
		/// the application to perform any needed transformations on the Message before it is sent.
		/// The ConnectionFactory sets the provided delegate instance on each Connection instance that
		/// is created from this factory, each connection in turn passes the delegate along to each
		/// Session it creates which then passes that along to the Producers it creates.
		/// </summary>
		public ProducerTransformerDelegate ProducerTransformer
		{
			get { return this.producerTransformer; }
			set { this.producerTransformer = value; }
		}

		#endregion
	}
}
