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

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

import convFramework.domain.*;

import java.util.*;

/**
 * @author Lompa
 */
public class FaultNotificationServer extends COPTask{
	
	/**
	 * @param community
	 * @param conv
	 * @param packetMan
	 * @param statusStore
	 * @param convGraveyard
	 * @param waitingTimeout
	 * @param connectionRank
	 * @param maxDelegationsNumber
	 */
	public FaultNotificationServer(ConfigurationSet conf, COPPacketManager packetMan, StatusManager statusMan, COPEventListenerManager listenerMan,
			ConversationGraveyard convGraveyard, ControlSystem queue, TaskConversersList taskList,
			boolean isClient, boolean priority) {
		super(conf , packetMan, listenerMan, statusMan, convGraveyard, queue, taskList, isClient, priority);
	}
	
	
	/* metodo body */
	protected void body() throws InterruptedException, TranslationException{
		
		jaCop.Debug.print("\nSERVER DI NOTIFICA DI CADUTA: "+convID.encode());
		jaCop.Debug.print("struttura: " + (statusMan.hasCompleteStructure(community) ? "completa\n" : "rotta\n"));
		
		/* RICEZIONE NOTIFICA */
		/* ricezione */
		COPPacket packet = receive();
		/* controllo del tipo */
		if (!packet.getType().equals(FaultNotification.getTypeDescription())){
			return;
		}
		/* casting */
		FaultNotification faultNotification = (FaultNotification) packet;
		/* raccolta dati */
		COPNode[] fallenNodes = faultNotification.getFallenNodes();
		COPNode notifier = faultNotification.getSender();
		
		/* REGISTRAZIONE */
		registerConverser(notifier);
		
		/* CONTROLLI */
		/* se la notifica non viene da un vicino è ignorata */
		if (!statusMan.isNeighbor(community, notifier)){
			return;
		}
		
		/* ELIMINAZIONE DEI VICINI */
		for (int i = 0; i < fallenNodes.length; i++){
			if (statusMan.isNeighbor(community, fallenNodes[i])){
				statusMan.removeNeighbor(community, fallenNodes[i]);
				//System.out.println("vicino rimosso");
			}
		}
		
		/* RISPOSTA */
		/* preparazione */
		Confirmation confirmation = packetMan.newConfirmation(convID, community);
		confirmation.setReceiver(notifier);
		/* invio */
		send(confirmation);
		
		//System.out.println("conferma inviata");
		
	}
	
	private boolean contains(COPNode[] nodes, COPNode node){
		for(int i = 0; i< nodes.length; i++)
			if (nodes[i].getAddress().equals(node.getAddress()) && nodes[i].getPort() == node.getPort())
				return true;
		
		return false;
	}
	
	public static class ConfigurationSet extends COPTask.ConfigurationSet{
		
		public ConfigurationSet(String community, IConversationID convID){
			super(community, convID);
		}
	}
	
}
