/*
 * Created on 7-mag-2004
 */
package a3.protocol;

import a3.traffic.*;
import a3.domain.*;
import a3.exceptions.*;

import jaCop.protocol.*;

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

/**
 * @author Lompa
 */
public class ProtocolTrigger implements INewConversationListener {
	
	/* flag di istanziazione */
	//private static boolean instantiated = false;
	
	/* campi */
	/* oggetto di controllo */
	private A3PacketManager packetMan = null;
	private ControlQueue clientQueue = null;
	private ControlQueue serverQueue = null;
	private ProtocolManager jaCOPMan = null;
	private ConversationGraveyard convGraveyard = null;
	private A3EventListenerManager listenerMan = null;
	
	/* configurazione */
	private long conversationTimeout = 20000;
	
	/* campi di stato */
	SoundStructureClient currentActiveClient = null;
	
	/**
	 * @param packetMan
	 * @param statusStore
	 * @param connectionRank
	 * @param monitor
	 */
	public ProtocolTrigger(ConfigurationSet conf, A3PacketManager packetMan, ControlQueue clientQueue,
			ControlQueue serverQueue, A3EventListenerManager listenerMan, ProtocolManager jaCOPMan)
		throws InstantiationRuleBrokenException {
		/* controllo */
		//if (instantiated) throw new InstantiationRuleBrokenException("cannot create more than one ProtocolTrigger");
		//else instantiated = true;
		/* assegnazioni */
		/* strumenti */
		this.packetMan = packetMan;
		this.clientQueue = clientQueue;
		this.serverQueue = serverQueue;
		this.jaCOPMan = jaCOPMan;
		this.listenerMan = listenerMan;
		/* opzioni */
		this.conversationTimeout = conf.getConversationTimeout();
		/* istanziazione nuovi oggetti */
		this.convGraveyard = new FakeConversationGraveyard(200); //TODO attenzione: ho usato un fake conversatin graveyard
	}
	
	/* metodi per l'inizio di conversazioni ***********************************************************/
	
	public synchronized void soundCommunity(String community){
		/* se la comunità non esiste non faccio nulla */
		if(!jaCOPMan.existsCommunity(community)) return;
		
		/* creo una nuova conversazione */
		IConversationID newConvID = packetMan.newConversation().getConversationID();
		
		/* il servant è il nodo locale */
		A3Node servant = packetMan.getCurrentNode();
		
		/* avvio un client per sondaggio struttura */
		SoundStructureClient.ConfigurationSet conf = new SoundStructureClient.ConfigurationSet(community, newConvID);
		conf.setWaitingTimeout(this.conversationTimeout);
		SoundStructureClient client = new SoundStructureClient(conf, packetMan, listenerMan, convGraveyard, clientQueue, jaCOPMan);
		/* impostazione del client corrente */
		this.currentActiveClient = client;
		/* esecuzione */
		client.start();
	}
	
	public synchronized void stopSoundCommunity(){
		if (this.currentActiveClient != null){
			this.currentActiveClient.terminate();
		}
		
	}
	
	/* metodi per la gestione di eventi **************************************************************/
	
	public synchronized void newConversationStarted(NewConversationEvent event){
		/* recupero dati */
		//System.out.println("NUOVA CONVERSAZIONE");
		A3Packet packet = null;
		try { packet = packetMan.translate((ContentPacket) event.getArrivedPacket()); }
		catch(TranslationException e){ return; /* non faccio nulla */ }
		IConversationID convID = packet.getConvID();
		String community = packet.getCommunity();
		
		//System.out.println("packet type: "+packet.getType());
		/* i pacchetti relativi a comunità non esistenti vengno scartati */
		if(!jaCOPMan.existsCommunity(community)) return;
		
		/* l'unico pacchetto che può arrivare è una richiesta di struttura */
		if(packet.getType().equals(A3StructureRequest.getTypeDescription())){
			//System.out.println("NUOVA CONVERSAZIONE: JOIN REQUEST");
			/* casting */
			A3StructureRequest structureRequest = (A3StructureRequest) packet;
			/* recupero dati */
			/* creazione di un servant per richiesta di struttura*/
			SoundStructureServer.ConfigurationSet conf = new SoundStructureServer.ConfigurationSet(community, convID);
			conf.setWaitingTimeout(this.conversationTimeout);
			SoundStructureServer server = new SoundStructureServer(conf, packetMan, listenerMan, convGraveyard, serverQueue, jaCOPMan);
			/* esecuzione */
			server.start();
		}
		
	}

	
	public static class ConfigurationSet {
		
		private long conversationTimeout = 20000;	
		
		/**
		 * @return Returns the conversationTimeout.
		 */
		public long getConversationTimeout() {
			return conversationTimeout;
		}
		/**
		 * @param conversationTimeout The conversationTimeout to set.
		 */
		public void setConversationTimeout(long conversationTimeout) {
			this.conversationTimeout = conversationTimeout;
		}
	}
	
	/**
	 * @return Returns the controlSystem.
	 */
	public ControlQueue getClientQueue() {
		return this.clientQueue;
	}
	
}
