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

import jaCop.domain.*;
import jaCop.protocol.*;

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

import convFramework.domain.*;

/**
 * @author Lompa
 */
public class SoundStructureClient extends A3Task{
	
	/**
	 * @param community
	 * @param conv
	 * @param packetMan
	 * @param statusStore
	 * @param convGraveyard
	 * @param waitingTimeout
	 * @param connectionRank
	 * @param maxDelegationsNumber
	 */
	public SoundStructureClient(ConfigurationSet conf,
			A3PacketManager packetMan, A3EventListenerManager listenerMan,
			ConversationGraveyard convGraveyard, ControlQueue queue, ProtocolManager jaCOPMan) {
		super(conf, packetMan, convGraveyard, listenerMan, queue, jaCOPMan);
	}
	
	
	/* metodo body */
	protected void body() throws TranslationException, InterruptedException{
		//System.out.println("CLIENT PER SCANDAGLIO STRUTTURA");
		
		/* NOTIFICA DELLA PROPRIA STRUTTURA */
		this.notifyStructureSounded(community, jaCOPMan.getCurrentNode(community), jaCOPMan.getStructureNeighbors(community));
		
		/* INVIO DELLA RICHIESTA LUNGO BACKWARD LINKS */
		/* recupero dei backward neighbors */
		COPNode[] backwardNeighbors = jaCOPMan.getJoinedNeighbors(community);
		for(int i = 0; i < backwardNeighbors.length; i++){
			/* preparazione della richiesta */
			A3StructureRequest req = packetMan.newA3StructureRequest(convID, community);
			req.setRequester(packetMan.getCurrentNode());
			A3Node receiver = null;
			try { receiver = new A3Node(backwardNeighbors[i].getAddress(), backwardNeighbors[i].getPort()-1); }
			catch(convFramework.exceptions.BadInvocationArgumentException e){
				throw new A3Error(e.getMessage());
			}
			req.setReceiver(receiver);
			/* invio */
			try { send(req); }
			catch(TranslationException e){
				throw new A3Error(e.getMessage());
			}
		}
		
		/* INVIO DELLA RICHIESTA LUNGO IL FORWARD LINK */
		COPNode forwardNeighbor = jaCOPMan.getJuncturePoint(community);
		if (forwardNeighbor != null){
			/* preparazione della richiesta */
			A3StructureRequest req = packetMan.newA3StructureRequest(convID, community);
			req.setRequester(packetMan.getCurrentNode());
			A3Node receiver = null;
			try { receiver = new A3Node(forwardNeighbor.getAddress(), forwardNeighbor.getPort()-1); }
			catch(convFramework.exceptions.BadInvocationArgumentException e){
				throw new A3Error(e.getMessage());
			}
			req.setReceiver(receiver);
			/* invio */
			try { send(req); }
			catch(TranslationException e){
				throw new A3Error(e.getMessage());
			}		
		}
		
		/* ATTESA RISPOSTE */
		/* il client attende risposte finchè ne arrivano => a ciclo infinito, salvo il timeout di ricezione */
		/* il client può essere interrotto a forza dall'utente */
		while(true){
			/* ricezione */
			A3Packet ans = null;
			ans = this.receive();
			/* controllo del tipo */
			/* se il tipo non corrisponde si scarta il pachetto */
			if (!ans.getType().equals(A3Structure.getTypeDescription()));
			/* altrimenti si genera un evento di struttura sondata */
			else {
				A3Structure remoteStruct = (A3Structure) ans;
				this.notifyStructureSounded(community, remoteStruct.getSenderCOPNode(), remoteStruct.getStructureNeighbors());
			}
		}
		
	}
	
	public static class ConfigurationSet extends A3Task.ConfigurationSet{
		
		public ConfigurationSet(String community, IConversationID convID){
			super(community, convID);
		}
	}
}
