/** 
 * 
 * Copyright 2004 Protique Ltd
 * 
 * Licensed 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.codehaus.activemq.transport;

import org.codehaus.activemq.broker.BrokerConnector;
import org.codehaus.activemq.message.Packet;
import org.codehaus.activemq.message.PacketListener;
import org.codehaus.activemq.message.Receipt;
import org.codehaus.activemq.message.ReceiptHolder;
import org.codehaus.activemq.service.Service;

import javax.jms.ExceptionListener;
import javax.jms.JMSException;

/**
 * A TransportChannel is used for tranporting packets between nodes
 * e.g. a ActiveMQ JMS Connection and Broker.
 * The TransportChannel supports synchronous and asynchronous send operations
 * as well as sync or async reading of packets. A TransportChannel implementation
 * could use a dedicated thread using blocking IO to read from a socket or
 * could use NIO or poll some file system or database etc.
 * On receipt of a Packet the TransportChannel should invoke the PacketListener
 *
 * @version $Revision: 1.6 $
 */
public interface TransportChannel extends Service {

    
    /**
     * Give the TransportChannel a hint it's about to stop
     * @param pendingStop
     *
     */
    public void setPendingStop(boolean pendingStop);
    
    /**
     * @return true if the channel is about to stop
     */
    public boolean isPendingStop();

    /**
     * close the channel
     */
    public void stop();

    /**
     * start listeneing for events
     *
     * @throws JMSException if an error occurs
     */
    public void start() throws JMSException;

    /**
     * Forces an immediate transport-level disconnect which will be asynchronously reported 
     * as an exception to the exceptionListener. If the channel isn't connected, the call will
     * be ignored.
     */
    public void forceDisconnect();
    
    /**
     * Gets the timestamp of the last received receipt packet.
     * 
     * @return the timestamp in milliseconds
     */
    public long getLastReceiptTimestamp();
    
    /**
     * synchronously send a Packet
     *
     * @param packet
     * @return a Receipt
     * @throws JMSException
     */

    public Receipt send(Packet packet) throws JMSException;

    /**
     * Synchrnously send a Packet
     *
     * @param packet  packet to send
     * @param timeout amount of time to wait for a receipt
     * @return the Receipt
     * @throws JMSException
     */

    public Receipt send(Packet packet, int timeout) throws JMSException;

    /**
     * Asynchronously send a Packet
     *
     * @param packet the packet to send
     * @throws JMSException
     */

    public void asyncSend(Packet packet) throws JMSException;
    
    /**
     * Asynchronously send a Packet with receipt.
     * 
     * @param packet the packet to send
     * @return a ReceiptHolder for the packet
     * @throws JMSException
     */
    public ReceiptHolder asyncSendWithReceipt(Packet packet) throws JMSException;

    /**
     * Set a listener for Packets
     *
     * @param l
     */
    public void setPacketListener(PacketListener l);


    /**
     * Set an exception listener to listen for asynchronously generated exceptions
     *
     * @param listener
     */
    public void setExceptionListener(ExceptionListener listener);

    /**
     * @return true if this transport is multicast based (i.e. broadcasts to multiple nodes)
     */
    public boolean isMulticast();

    /**
     * Add a listener for changes in a channels status
     *
     * @param listener
     */
    public void addTransportStatusEventListener(TransportStatusEventListener listener);

    /**
     * Remove a listener for changes in a channels status
     *
     * @param listener
     */
    public void removeTransportStatusEventListener(TransportStatusEventListener listener);

    /**
     * Provides a way to specify the client ID that this channel is using
     *
     * @param clientID
     */
    public void setClientID(String clientID);

    /**
     * @return the client ID that this channel is being used for
     */
    public String getClientID();

    /**
     * A listener to be notified when the channel is removed
     *
     * @param listener
     */
    public void setTransportChannelListener(TransportChannelListener listener);

    /**
     * @return true if this transport is used by the broker to
     * communicate with a client, or false if this is a client side
     * transport
     */
    public boolean isServerSide();

    /**
     * set the server flag
     * @param serverSide
     */
    public void setServerSide(boolean serverSide);
    
    /**
     * Can this wireformat process packets of this version
     * @param version the version number to test
     * @return true if can accept the version
     */
    public boolean canProcessWireFormatVersion(int version);
    
    /**
     * @return the current version of this wire format
     */
    public int getCurrentWireFormatVersion();
    
    /**
     * @return true if the transport channel is active,
     * this value will be false through reconnecting
     */
    public boolean isTransportConnected();
    
    /**
     * Some transports rely on an embedded broker (peer based protocols)
     * @return true if an embedded broker required
     */
    public boolean requiresEmbeddedBroker();
    
    /**
     * Some transports that rely on an embedded broker need to
     * create the connector used by the broker
     * @return the BrokerConnector or null if not applicable
     * @throws JMSException
     */
    public BrokerConnector getEmbeddedBrokerConnector() throws JMSException;
    
}
