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

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

import jaCop.protocol.*;



/**
 * @author Lompa
 */
public class Loader {
	
	public static ProtocolHandlersCouple loadFramework(ConfigurationSet conf) throws LoadingException{
		try {
			/* campi */
			ProtocolManager jaCOPMan = null;
			
			/* CARICAMENTO DEL SERVIZIO JaCOP  */
			/* applicazione delle opzioni */
			jaCop.protocol.Loader.ConfigurationSet jaCOPConf = jaCop.protocol.Loader.newConfigurationSet();
			jaCOPConf.setPort(conf.getPort()+1);
			jaCOPConf.setConversationTimeout(conf.getConversationTimeout());
			jaCOPConf.setHeartbeatTimeout(conf.getHeartbeatTimeout());
			jaCOPConf.setMaxDelegations(conf.getMaxDelegations());
			jaCOPConf.setOptimizedReJoin(conf.isOptimizedReJoin());
			jaCOPConf.setReTransmissionTimeout(conf.getReTransmissionTimeout());
			/* caricamento */
			jaCOPMan = jaCop.protocol.Loader.loadFramework(jaCOPConf);
			
			/* CARICAMENTO DEL PROTOCOLLO A3 */
			/* 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 A3 */
			/* sottosistema traffico */
			A3PacketManager packetMan = new A3PacketManager(trafficMan);
			/* gestore degli ascoltatori di eventi di protocollo */
			A3EventListenerManager listenerMan = new A3EventListenerManager();
			/* code di controllo */
			ControlQueue clientQueue = new ControlQueue();
			ControlQueue serverQueue = new ControlQueue();
			
			/* trigger di protocollo */
			ProtocolTrigger.ConfigurationSet ptConf = new ProtocolTrigger.ConfigurationSet();
			ptConf.setConversationTimeout(conf.getConversationTimeout());
			ProtocolTrigger trigger = new ProtocolTrigger(ptConf, packetMan, clientQueue, serverQueue, listenerMan, jaCOPMan);
			
			/* registrazione del trigger */
			trafficMan.addNewConversationListener(trigger);
			/* gestore di protocollo */
			A3Manager a3man = new A3Manager(listenerMan, trigger, packetMan);
			
			/* restituzione del gestore */
			return new ProtocolHandlersCouple(jaCOPMan, a3man);
		}
		catch(InstantiationRuleBrokenException e){
			throw new LoadingException(e.getMessage());
		}
		catch(convFramework.exceptions.LoadingException e){
			throw new LoadingException(e.getMessage());
		}
		catch(jaCop.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;
		}
	}
	
	public static class ProtocolHandlersCouple {
		
		private ProtocolManager jaCOPManager = null;
		private A3Manager a3Manager = null;
		
		/**
		 * @param jaCOPManager
		 * @param manager
		 */
		public ProtocolHandlersCouple(ProtocolManager jaCOPManager, A3Manager manager) {
			this.jaCOPManager = jaCOPManager;
			a3Manager = manager;
		}
		/**
		 * @return Returns the a3Manager.
		 */
		public A3Manager getA3Manager() {
			return a3Manager;
		}
		/**
		 * @return Returns the jaCOPManager.
		 */
		public ProtocolManager getJaCOPManager() {
			return jaCOPManager;
		}
	}
	
}
