/*
 * 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.Threading.Tasks;

namespace Apache.NMS
{
    /// <summary>
    /// A Factory of IConnection objects
    /// </summary>
    public interface IConnectionFactory
    {
        /// <summary>
        /// Creates a new connection
        /// </summary>
        IConnection CreateConnection();

        /// <summary>
        /// Creates a new connection with the given user name and password
        /// </summary>
        IConnection CreateConnection(string userName, string password); 
        
        /// <summary>
        /// Creates a new connection
        /// </summary>
        Task<IConnection> CreateConnectionAsync();

        /// <summary>
        /// Creates a new connection with the given user name and password
        /// </summary>
        Task<IConnection> CreateConnectionAsync(string userName, string password);
        
        /// <summary>
        /// Creates a new context
        /// </summary>
        INMSContext CreateContext();

        /// <summary>
        /// Creates a new context with the given acknowledgement mode.
        /// </summary>
        INMSContext CreateContext(AcknowledgementMode acknowledgementMode);

        /// <summary>
        /// Creates a new context with the given user name and password
        /// </summary>
        INMSContext CreateContext(string userName, string password);

        /// <summary>
        /// Creates a new context with the given user name, password and acknowledgement mode
        /// </summary>
        INMSContext CreateContext(string userName, string password, AcknowledgementMode acknowledgementMode);
        
        /// <summary>
        /// Creates a new context
        /// </summary>
        Task<INMSContext> CreateContextAsync();

        /// <summary>
        /// Creates a new context with the given acknowledgement mode.
        /// </summary>
        Task<INMSContext> CreateContextAsync(AcknowledgementMode acknowledgementMode);

        /// <summary>
        /// Creates a new context with the given user name and password
        /// </summary>
        Task<INMSContext> CreateContextAsync(string userName, string password);

        /// <summary>
        /// Creates a new context with the given user name, password and acknowledgement mode
        /// </summary>
        Task<INMSContext> CreateContextAsync(string userName, string password, AcknowledgementMode acknowledgementMode);

        /// <summary>
        /// Get/or set the broker Uri.
        /// </summary>
        Uri BrokerUri { get; set; }

        /// <summary>
        /// Get/or set the redelivery policy that new IConnection objects are
        /// assigned upon creation.
        /// </summary>
        IRedeliveryPolicy RedeliveryPolicy { get; set; }

        /// <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>
        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 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>
        ProducerTransformerDelegate ProducerTransformer { get; set; }
    }
}