/*
 * Created on 24-apr-2004
 */
package jaCop.protocol;

import jaCop.nodeStatus.*;
import jaCop.exceptions.*;
import jaCop.heartbeat.*;
import jaCop.traffic.*;

/**
 * @author Lompa
 */
public class Loader {
	
	/**
	 * Carica il servizio jaCOP
	 * @param conf il set di configurazioni
	 * @return un TrafficManager per l'uso del framework
	 */
	public static ProtocolManager loadFramework(ConfigurationSet conf) throws LoadingException{
		try {
			/* caricamento del conversationFramework */
			/* applicazione delle opzioni */
			convFramework.facade.Loader.ConfigurationSet cfConf = convFramework.facade.Loader.newConfigurationSet();
			cfConf.setInPort(conf.getPort());
			cfConf.setOutPort(conf.getPort());
			cfConf.setMaxRetransmissiosNumber(conf.maxRetransmissiosNumber);
			cfConf.setReTransmissionTimeout(conf.reTransmissionTimeout);
			/* caricamento */
			convFramework.facade.TrafficManager trafficMan = convFramework.facade.Loader.loadFramework(cfConf);
			
			/* caricamento di JaCOP */
			/* sottosistema stato */
			StatusStore statusStore = new StatusStore(trafficMan.getCurrentNode());
			/* sottosistema traffico */
			COPPacketManager packetMan = new COPPacketManager(trafficMan, statusStore);
			/* sottosistema di monitoraggio */
			Monitor monitor = new Monitor(conf.getHeartbeatTimeout(), packetMan, statusStore);
			trafficMan.addPacketArrivedListener(monitor);
			trafficMan.addPacketTransmittedListener(monitor);
			/* gestore degli ascoltatori di eventi di protocollo */
			COPEventListenerManager listenerMan = new COPEventListenerManager();
			/* gestore dello stato e dell'attivitą di controllo */
			StatusManager statusMan = new StatusManager(statusStore, monitor);
			
			/* trigger di protocollo */
			ProtocolTrigger.ConfigurationSet ptConf = new ProtocolTrigger.ConfigurationSet();
			ptConf.setConversationTimeout(conf.getConversationTimeout());
			ptConf.setOptimizedReJoin(conf.isOptimizedReJoin());
			ProtocolTrigger trigger = new ProtocolTrigger(ptConf, packetMan, statusMan, listenerMan);
			
			/* inizializzaziaone gestore dello stato */
			statusMan.setTrigger(trigger);
			
			/* registrazione del trigger */
			trafficMan.addMissingResponseListener(trigger);
			trafficMan.addNewConversationListener(trigger);
			/* gestore di protocollo */
			ProtocolManager protocolMan = new ProtocolManager(trigger, listenerMan, statusStore);
			
			/* restituzione del gestore */
			return protocolMan;
		}
		catch(InstantiationRuleBrokenException e){
			throw new LoadingException(e.getMessage());
		}
		catch(convFramework.exceptions.LoadingException e){
			throw new LoadingException(e.getMessage());
		}
	}
	
	/**
	 * @return
	 * @throws BadInvocationArgumentException
	 */
	public static ConfigurationSet newConfigurationSet(){
		return new ConfigurationSet();
	}
	
	/**
	 * @author Lompa
	 */
	public static class ConfigurationSet {
		
		/* parametri del conversationFramework */
		private int inPort = 3337;
		private int outPort = 3337;
		private int maxRetransmissiosNumber = 2;
		private long reTransmissionTimeout = 10000;
		private long conversationTimeout = 20000;
		private int maxDelegations = 2;
		private boolean optimizedReJoin = false;
		private long heartbeatTimeout = 20000;
		
		
		private ConfigurationSet(){
		}
		
		/**
		 * @return
		 */
		public int getPort() {
			return outPort;
		}

		/**
		 * @param port
		 */
		public void setPort(int port) {
			this.outPort = port;
			this.inPort = port;
		}
		/**
		 * @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 maxDelegations.
		 */
		public int getMaxDelegations() {
			return maxDelegations;
		}
		/**
		 * @param maxDelegations The maxDelegations to set.
		 */
		public void setMaxDelegations(int maxDelegations) {
			this.maxDelegations = maxDelegations;
		}
		/**
		 * @return Returns the optimizedReJoin.
		 */
		public boolean isOptimizedReJoin() {
			return optimizedReJoin;
		}
		/**
		 * @param optimizedReJoin The optimizedReJoin to set.
		 */
		public void setOptimizedReJoin(boolean optimizedReJoin) {
			this.optimizedReJoin = optimizedReJoin;
		}
		/**
		 * @return Returns the heartbeatTimeout.
		 */
		public long getHeartbeatTimeout() {
			return heartbeatTimeout;
		}
		/**
		 * @param heartbeatTimeout The heartbeatTimeout to set.
		 */
		public void setHeartbeatTimeout(long heartbeatTimeout) {
			this.heartbeatTimeout = heartbeatTimeout;
		}
		/**
		 * @return Returns the reTransmissionTimeout.
		 */
		public long getReTransmissionTimeout() {
			return reTransmissionTimeout;
		}
		/**
		 * @param reTransmissionTimeout The reTransmissionTimeout to set.
		 */
		public void setReTransmissionTimeout(long reTransmissionTimeout) {
			this.reTransmissionTimeout = reTransmissionTimeout;
		}
	}	
	
}
