/*
 * Created on 21-apr-2004
 */
package convFramework.facade;

import convFramework.domain.*;
import convFramework.traffic.*;
import convFramework.traffic.event.*;
import convFramework.exceptions.*;

/**
 * Classe che fa da punto di accesso unificato per il conversation framework 
 * @author Lompa
 */
public class TrafficManager {
	
	/* campi */
	private PacketDispatcher dispatcher = null;
	private OutQueue outQueue = null;
	private ReceptionEventListenerManager receptionEventListenerManager = null;
	private TransmissionEventListenerManager transmissionEventListenerManager = null;
	private ConversationManager conversationManager = null;
	private IConversationIDFactory convIDFactory = null;
	private IPacketIDFactory packetIDFactory = null;
	private Node currentNode = null;
	
	/**
	 * Crea una istanza di traffica manager
	 * @param dispatcher il dispatecher per i pacchetti in arrivo
	 * @param outQueue la coda per i acchetti in uscita
	 * @param receptionEventListenerManager il registro dei gestori di reventi di ricezione
	 * @param transmissionEventListenerManager il registro dei gestori di eventi di trasmission
	 * @param conversationManager il gestore delle conversazioni
	 */
	public TrafficManager(PacketDispatcher dispatcher, OutQueue outQueue,
						ReceptionEventListenerManager receptionEventListenerManager,
						TransmissionEventListenerManager transmissionEventListenerManager,
						ConversationManager conversationManager,
						IConversationIDFactory convIDFactory,
						IPacketIDFactory packetIDFactory,
						Node currentNode){
		this.dispatcher = dispatcher;
		this.outQueue = outQueue;
		this.receptionEventListenerManager = receptionEventListenerManager;
		this.transmissionEventListenerManager = transmissionEventListenerManager;
		this.conversationManager = conversationManager;
		this.currentNode  = currentNode;
		this.packetIDFactory = packetIDFactory;
		this.convIDFactory = convIDFactory;
	}
	
	/**
	 * Riceve un pacchetto; se non c'è nessun pacchetto disponibile è bloccante
	 * @param convID l'id della conversazione cui il pacchetto appartiene
	 * @return il pacchetto
	 */
	public ContentPacket receivePacket(IConversationID convID) throws InterruptedException{
		return this.dispatcher.extractPacket(convID);
	}
	
	/**
	 * Invia un pacchetto; se il pacchetto attende una risposta e questa non arriva in tempo
	 * limite il pacchetto viene ritrasmesso; dopo un certo numero di rtrasmissioni senza risposta
	 * si invia un event di riposta non arrivata
	 * @param packet il pacchetto da spedire
	 */
	public void sendPacket(Packet packet){
		this.outQueue.insertPacket(packet);
	}
	
	/**
	 * Restituisce la conversazione associata all'id specificato, se esiste
	 * @param convID l'id della conversazione
	 * @return la conversazione
	 */
	public IConversation getConversation(IConversationID convID){
		return this.conversationManager.getConversation(convID);
	}
	
	/**
	 * Verifca se esiste la conversazione con l'ID specificato
	 * @param convID l'id
	 * @return true se la conversazione esiste
	 */
	public boolean existsConversation(IConversationID convID){
		return this.existsConversation(convID);
	}
	
	/**
	 * Aggiunge una conversazione
	 * @param conv la conversazione
	 */
	public IConversation newConversation(){
		IConversation conv = new StateLessConversation(this.convIDFactory.newConversationID(currentNode));
		this.conversationManager.addConversation(conv);
		return conv;
	}
	
	/**
	 * Rimuove la conversazione con l'ID specificato
	 * @param convID l'id
	 */
	public void removeConversation(IConversationID convID){
		this.conversationManager.removeConversation(convID);
	}
	
	/**
	 * @param listener
	 */
	public void addPacketTransmittedListener(IPacketTransmittedListener listener){
		this.transmissionEventListenerManager.addPacketTransmittedListener(listener);
	}
	
	/**
	 * @param listener
	 */
	public void removePacketTransmittedListener(IPacketTransmittedListener listener){
		this.transmissionEventListenerManager.removePacketTransmittedListener(listener);
	}
	
	/**
	 * @param listener
	 */
	public void addMissingResponseListener(IMissingAckListener listener){
		this.transmissionEventListenerManager.addMissingAckListener(listener);
	}
	
	/**
	 * @param listener
	 */
	public void removeMissingResponseListener(IMissingAckListener listener){
		this.transmissionEventListenerManager.removeMissingAckListener(listener);
	}	
	
	/**
	 * @param listener
	 */
	public void addTransmissionErrorListener(ITransmissionErrorListener listener){
		this.transmissionEventListenerManager.addTransmissionErrorListener(listener);
	}
	
	/**
	 * @param listener
	 */
	public void removeTransmissionErrorListener(ITransmissionErrorListener listener){
		this.transmissionEventListenerManager.removeTransmissionErrorListener(listener);
	}
	
	/**
	 * @param listener
	 */
	public void addReceptionErrorListener(IReceptionErrorListener listener){
		this.receptionEventListenerManager.addReceptionErrorListener(listener);
	}
	
	/**
	 * @param listener
	 */
	public void removeReceptionErrorListener(IReceptionErrorListener listener){
		this.receptionEventListenerManager.removeReceptionErrorListener(listener);
	}
	
	/**
	 * @param listener
	 */
	public void addPacketArrivedListener(IContentPacketArrivedListener listener){
		this.receptionEventListenerManager.addContentPacketArrivedListener(listener);
	}
	
	/**
	 * @param listener
	 */
	public void removePacketArrivedListener(IContentPacketArrivedListener listener){
		this.receptionEventListenerManager.removeContentPacketArrivedListener(listener);
	}
	
	/**
	 * @param listener
	 */
	public void addResponseArrivedListener(IAckArrivedListener listener){
		this.receptionEventListenerManager.addAckArrivedListener(listener);
	}
	
	/**
	 * @param listener
	 */
	public void removeResponseArrivedListener(IAckArrivedListener listener){
		this.receptionEventListenerManager.removeAckArrivedListener(listener);
	}
	
	/**
	 * @param listener
	 */
	public void addNewConversationListener(INewConversationListener listener){
		this.receptionEventListenerManager.addNewConversationListener(listener);
	}
	
	/**
	 * @param listener
	 */
	public void removeNewConversationListener(INewConversationListener listener){
		this.receptionEventListenerManager.removeNewConversationListener(listener);
	}
	
	/**
	 * @param convID
	 * @return
	 */
	public ContentPacket newPacket(IConversationID convID){
		ContentPacket packet = new ContentPacket(this.packetIDFactory.newPacketID(currentNode), convID);
		packet.setSender(currentNode);
		return packet;
	}
	/**
	 * @return Returns the currentNode.
	 */
	public Node getCurrentNode() {
		return currentNode;
	}
}
