/*
 * 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;

namespace Apache.NMS
{
	/// <summary>
	/// Represents a single unit of work on an IConnection.
	/// So the ISession can be used to perform transactional receive and sends
	/// </summary>
	public interface ISession : IDisposable
	{		
		/// <summary>
		/// Creates a producer of messages
		/// </summary>
		IMessageProducer CreateProducer();

		/// <summary>
		/// Creates a producer of messages on a given destination
		/// </summary>
		IMessageProducer CreateProducer(IDestination destination);

		/// <summary>
		/// Creates a consumer of messages on a given destination
		/// </summary>
		IMessageConsumer CreateConsumer(IDestination destination);

		/// <summary>
		/// Creates a consumer of messages on a given destination with a selector
		/// </summary>
		IMessageConsumer CreateConsumer(IDestination destination, string selector);

		/// <summary>
		/// Creates a consumer of messages on a given destination with a selector
		/// </summary>
		IMessageConsumer CreateConsumer(IDestination destination, string selector, bool noLocal);

		/// <summary>
		/// Creates a named durable consumer of messages on a given destination with a selector
		/// </summary>
		IMessageConsumer CreateDurableConsumer(ITopic destination, string name, string selector, bool noLocal);

		/// <summary>
		/// Deletes a durable consumer created with CreateDurableConsumer().
		/// </summary>
		/// <param name="name">Name of the durable consumer</param>
		void DeleteDurableConsumer(string name);

        /// <summary>
        /// Creates a QueueBrowser object to peek at the messages on the specified queue.
        /// </summary>
        /// <param name="queue">
        /// A <see cref="IQueue"/>
        /// </param>
        /// <returns>
        /// A <see cref="IQueueBrowser"/>
        /// </returns>
        /// <exception cref="System.NotSupportedException">
        /// If the Prodiver does not support creation of Queue Browsers.
        /// </exception>
        IQueueBrowser CreateBrowser(IQueue queue);
        
        /// <summary>
        /// Creates a QueueBrowser object to peek at the messages on the specified queue 
        /// using a message selector.
        /// </summary>
        /// <param name="queue">
        /// A <see cref="IQueue"/>
        /// </param>
        /// <param name="selector">
        /// A <see cref="System.String"/>
        /// </param>
        /// <returns>
        /// A <see cref="IQueueBrowser"/>
        /// </returns>
        /// <exception cref="System.NotSupportedException">
        /// If the Prodiver does not support creation of Queue Browsers.
        /// </exception>
        IQueueBrowser CreateBrowser(IQueue queue, string selector);
        
		/// <summary>
		/// Returns the queue for the given name
		/// </summary>
		IQueue GetQueue(string name);

		/// <summary>
		/// Returns the topic for the given name
		/// </summary>
		ITopic GetTopic(string name);

		/// <summary>
		/// Creates a temporary queue
		/// </summary>
		ITemporaryQueue CreateTemporaryQueue();

		/// <summary>
		/// Creates a temporary topic
		/// </summary>
		ITemporaryTopic CreateTemporaryTopic();

		/// <summary>
		/// Delete a destination (Queue, Topic, Temp Queue, Temp Topic).
		/// </summary>
		void DeleteDestination(IDestination destination);

		// Factory methods to create messages

		/// <summary>
		/// Creates a new message with an empty body
		/// </summary>
		IMessage CreateMessage();

		/// <summary>
		/// Creates a new text message with an empty body
		/// </summary>
		ITextMessage CreateTextMessage();

		/// <summary>
		/// Creates a new text message with the given body
		/// </summary>
		ITextMessage CreateTextMessage(string text);

		/// <summary>
		/// Creates a new Map message which contains primitive key and value pairs
		/// </summary>
		IMapMessage CreateMapMessage();

		/// <summary>
		/// Creates a new Object message containing the given .NET object as the body
		/// </summary>
		IObjectMessage CreateObjectMessage(object body);

		/// <summary>
		/// Creates a new binary message
		/// </summary>
		IBytesMessage CreateBytesMessage();

		/// <summary>
		/// Creates a new binary message with the given body
		/// </summary>
		IBytesMessage CreateBytesMessage(byte[] body);

		/// <summary>
		/// Creates a new stream message
		/// </summary>
		IStreamMessage CreateStreamMessage();

		/// <summary>
		/// Closes the session.  There is no need to close the producers and consumers
		/// of a closed session.
		/// </summary>
		void Close();

        /// <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 Session instance sets the delegate on each Consumer it creates.
        /// </summary>
        ConsumerTransformerDelegate ConsumerTransformer
        {
            get;
            set;
        }

        /// <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 Session instance sets the delegate on each Producer it creates.
        /// </summary>
        ProducerTransformerDelegate ProducerTransformer
        {
            get;
            set;
        }

		#region Transaction methods

		/// <summary>
		/// If this is a transactional session then commit all message
		/// send and acknowledgements for producers and consumers in this session
		/// </summary>
		void Commit();

		/// <summary>
		/// If this is a transactional session then rollback all message
		/// send and acknowledgements for producers and consumers in this session
		/// </summary>
		void Rollback();

		#endregion

		#region Attributes

		TimeSpan RequestTimeout { get; set; }

		bool Transacted { get; }

		AcknowledgementMode AcknowledgementMode { get; }

		#endregion
	}
}
