/*
 * 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.
 */
package org.apache.activemq.artemis.api.core.client;

import org.apache.activemq.artemis.api.core.ActiveMQException;
import org.apache.activemq.artemis.api.core.TransportConfiguration;
import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;

/**
 * A ClientSessionFactory is the entry point to create and configure ActiveMQ Artemis resources to produce and consume messages.
 * <br>
 * It is possible to configure a factory using the setter methods only if no session has been created.
 * Once a session is created, the configuration is fixed and any call to a setter method will throw an IllegalStateException.
 */
public interface ClientSessionFactory extends AutoCloseable {

   /**
    * Creates a session with XA transaction semantics.
    *
    * @return a ClientSession with XA transaction semantics
    * @throws ActiveMQException if an exception occurs while creating the session
    */
   ClientSession createXASession() throws ActiveMQException;

   /**
    * Creates a <em>transacted</em> session.
    * <p>
    * It is up to the client to commit when sending and acknowledging messages.
    *
    * @return a transacted ClientSession
    * @throws ActiveMQException if an exception occurs while creating the session
    * @see ClientSession#commit()
    */
   ClientSession createTransactedSession() throws ActiveMQException;

   /**
    * Creates a <em>non-transacted</em> session.
    * Message sends and acknowledgements are automatically committed by the session. <em>This does not
    * mean that messages are automatically acknowledged</em>, only that when messages are acknowledged,
    * the session will automatically commit the transaction containing the acknowledgements.
    *
    * @return a non-transacted ClientSession
    * @throws ActiveMQException if an exception occurs while creating the session
    */
   ClientSession createSession() throws ActiveMQException;

   /**
    * Creates a session.
    *
    * @param autoCommitSends <code>true</code> to automatically commit message sends, <code>false</code> to commit manually
    * @param autoCommitAcks  <code>true</code> to automatically commit message acknowledgement, <code>false</code> to commit manually
    * @return a ClientSession
    * @throws ActiveMQException if an exception occurs while creating the session
    */
   ClientSession createSession(boolean autoCommitSends, boolean autoCommitAcks) throws ActiveMQException;

   /**
    * Creates a session.
    *
    * @param autoCommitSends <code>true</code> to automatically commit message sends, <code>false</code> to commit manually
    * @param autoCommitAcks  <code>true</code> to automatically commit message acknowledgement, <code>false</code> to commit manually
    * @param ackBatchSize    the batch size of the acknowledgements
    * @return a ClientSession
    * @throws ActiveMQException if an exception occurs while creating the session
    */
   ClientSession createSession(boolean autoCommitSends,
                               boolean autoCommitAcks,
                               int ackBatchSize) throws ActiveMQException;

   /**
    * Creates a session.
    *
    * @param xa              whether the session support XA transaction semantic or not
    * @param autoCommitSends <code>true</code> to automatically commit message sends, <code>false</code> to commit manually
    * @param autoCommitAcks  <code>true</code> to automatically commit message acknowledgement, <code>false</code> to commit manually
    * @return a ClientSession
    * @throws ActiveMQException if an exception occurs while creating the session
    */
   ClientSession createSession(boolean xa, boolean autoCommitSends, boolean autoCommitAcks) throws ActiveMQException;

   /**
    * Creates a session.
    * <p>
    * It is possible to <em>pre-acknowledge messages on the server</em> so that the client can avoid additional network trip
    * to the server to acknowledge messages. While this increase performance, this does not guarantee delivery (as messages
    * can be lost after being pre-acknowledged on the server). Use with caution if your application design permits it.
    *
    * @param xa              whether the session support XA transaction semantic or not
    * @param autoCommitSends <code>true</code> to automatically commit message sends, <code>false</code> to commit manually
    * @param autoCommitAcks  <code>true</code> to automatically commit message acknowledgement, <code>false</code> to commit manually
    * @param preAcknowledge  <code>true</code> to pre-acknowledge messages on the server, <code>false</code> to let the client acknowledge the messages
    * @return a ClientSession
    * @throws ActiveMQException if an exception occurs while creating the session
    */
   ClientSession createSession(boolean xa,
                               boolean autoCommitSends,
                               boolean autoCommitAcks,
                               boolean preAcknowledge) throws ActiveMQException;

   /**
    * Creates an <em>authenticated</em> session.
    * <p>
    * It is possible to <em>pre-acknowledge messages on the server</em> so that the client can avoid additional network trip
    * to the server to acknowledge messages. While this increase performance, this does not guarantee delivery (as messages
    * can be lost after being pre-acknowledged on the server). Use with caution if your application design permits it.
    *
    * @param username        the user name
    * @param password        the user password
    * @param xa              whether the session support XA transaction semantic or not
    * @param autoCommitSends <code>true</code> to automatically commit message sends, <code>false</code> to commit manually
    * @param autoCommitAcks  <code>true</code> to automatically commit message acknowledgement, <code>false</code> to commit manually
    * @param preAcknowledge  <code>true</code> to pre-acknowledge messages on the server, <code>false</code> to let the client acknowledge the messages
    * @return a ClientSession
    * @throws ActiveMQException if an exception occurs while creating the session
    */
   ClientSession createSession(String username,
                               String password,
                               boolean xa,
                               boolean autoCommitSends,
                               boolean autoCommitAcks,
                               boolean preAcknowledge,
                               int ackBatchSize) throws ActiveMQException;

   /**
    * Closes this factory and any session created by it.
    */
   void close();

   /**
    * @return {@code true} if the factory is closed, {@code false} otherwise.
    */
   boolean isClosed();

   /**
    * Adds a FailoverEventListener to the session which is notified if a failover event  occurs on the session.
    *
    * @param listener the listener to add
    * @return this ClientSessionFactory
    */
   ClientSessionFactory addFailoverListener(FailoverEventListener listener);

   /**
    * Removes a FailoverEventListener to the session.
    *
    * @param listener the listener to remove
    * @return <code>true</code> if the listener was removed, <code>false</code> else
    */
   boolean removeFailoverListener(FailoverEventListener listener);

   /**
    * Opposed to close, will call cleanup only on every created session and children objects.
    */
   void cleanup();

   /**
    * @return the server locator associated with this session factory
    */
   ServerLocator getServerLocator();

   /**
    * Returns the code connection used by this session factory.
    *
    * @return the core connection
    */
   RemotingConnection getConnection();

   /**
    * Return the configuration used
    *
    * @return
    */
   TransportConfiguration getConnectorConfiguration();

}
