/** HelloWorld_E2EACK 
 *
 *       The HyperCast HelloWorld programs demonstrate various aspects of
 *       the HyperCast API.  The programs create an overlay socket that 
 *       sends and receives messages. 
 *
 *       The HelloWorld_GlobalACK program sends messages with E2EACK enabled. 
 *       This file corresponds to an example program in the HyperCast API description 
 *       (see Chapter:  "API - Advanced", Section: "1"). 
 * 
 *       The file is a bit more complex than the example in the chapter.
 *
 * @author HyperCast Team, University of Toronto
 * @version August 2006 
 *
 */


import hypercast.*;
import hypercast.events.*;
import java.io.*;


public class HelloWorld_E2EAck extends NotificationHandler implements  I_ReceiveCallback { 
	
	
	//	 The string we send 
	String MyString = new String("Hello World");
	
	//	 The overlay socket 
	I_OverlaySocket MySocket = null;
	
	//	 The configuration object
	HyperCastConfig ConfObj = null;
	
	// 	A message counter
	int counter = 0;
	
	public static void main(String[] args) {
		
		// Create a new HelloWorld_CallBack instance 
		HelloWorld_E2EAck hw = new HelloWorld_E2EAck();
	}
	
	public void ReceiveCallback (I_OverlayMessage msg) {
		
		// Extract the payload and the logical address of the source
		byte[] data = msg.getPayload();
		String Src = msg.getSourceAddress().toString();
		
		// Print the payload (Skip messages sent by this program) 
		if(!msg.getSourceAddress().equals(MySocket.getLogicalAddress()))
			System.out.println("Received #"+  ByteArrayUtility.toInteger(msg.getMessageIdentifier(),0)+  " from" + Src + ".");
	}
	
	public  HelloWorld_E2EAck () {
		
		//	Create a configuration object
		ConfObj = HyperCastConfig.createConfig("hypercast.xml");
		
		// Create an overlay socket with the configuration object
		MySocket=ConfObj.createOverlaySocket(this, this);
		
		// Join the overlay network 
		MySocket.joinOverlay();
		
		// Print the logical address */ 
		String MyLogicalAddress = MySocket.getLogicalAddress().toString();
		System.out.println("My logical address is " + MyLogicalAddress + ".");
		
		// Repeat forever
		for(;;) {
			
			// wait 5 seconds 	
			try {
				Thread.sleep(5000);
			} catch (InterruptedException e) {}	
			
			// Convert the string to a byte array and create a message
			byte[] MyData = MyString.getBytes(); 
			I_OverlayMessage MyMessage = MySocket.createMessage(MyData, I_OverlayMessage.E2EACK);
			MyMessage.setMsgIdentifier(counter++);
			
			
			// The message is sent to all members of the overlay //
			MySocket.sendToAll(MyMessage);
			
			//The message is sent to a specified address (here: "500,500")
			//I_LogicalAddress dest = MySocket.createLogicalAddress("500,500");	
			//MySocket.sendToNode(MyMessage, dest);
			
			System.out.println("Message #" + ByteArrayUtility.toInteger(MyMessage.getMessageIdentifier(),0) + " is  transmitted.");
			
		}
	}
	
	public void handle_E2EACK_RECEIVED (E2EACK_RECEIVED event) {
		byte[] MsgID = (byte []) event.getInfo();
		System.out.println("Message #" + ByteArrayUtility.toInteger(MsgID,0)+ " is acknowledged.");
	}
	
	public void handle_E2EPARTIALACK_RECEIVED (E2EPARTIALACK_RECEIVED event) {
		byte[] MsgID = (byte []) event.getInfo();
		System.out.println("Message #" + ByteArrayUtility.toInteger(MsgID,0)+ " partially  acknowledged.");
		
		//Retransmit with different message ID;
		String MyString = new String("Hello World");
		I_OverlayMessage msg =  
			MySocket.createMessage(MyString.getBytes(), I_OverlayMessage.E2EACK);
		MySocket.sendToAll(msg);
		/*	in case of unicast
		 I_LogicalAddress dest = MySocket.createLogicalAddress("500,500");	
		 MySocket.sendToNode(MyMessage, dest);
		 */	 	
		System.out.println("Message retransmitted as #" + ByteArrayUtility.toInteger(msg.getMessageIdentifier(),0) + ".");
	}
}