package edu.cmu.paid.network.test;

import java.lang.String;
import com.objectspace.voyager.message.*;
import edu.cmu.paid.network.CNetwork_Api;
import edu.cmu.paid.network.voyager.*;

/** This test is to exercise the multicasting via the network API.
  * CAUTION: For this code to work, you must start Voyager (by running
  * java edu.cmu.paid.network.test.VoyagerStartup //host:port) on 
  * remote machines specified below by ma3 and ma4.
  * @author Barrett Trask
  */

public class MulticastTest{
  
  public static void main(String argv[]){
    CNetwork_Api nAPI;
    MulticastAgent ma1, ma2;
    IMulticastAgent ma3, ma4;
    MulticastTestObject o1, o2, o3, o4;

    try{

      nAPI = new CNetwork_Api();
      nAPI.clientStartup();

      o1 = new MulticastTestObject();
      o1.name = "o1";
      o2 = new MulticastTestObject();
      o2.name = "o2";
      o3 = new MulticastTestObject();
      o3.name = "o3";
      o4 = new MulticastTestObject();
      o4.name = "o4";

      ma1 = nAPI.getNewMulticastAgent();
      ma2 = nAPI.getNewMulticastAgent();

      ma3 = nAPI.getNewRemoteMulticastAgent("//java.se.cs.cmu.edu:8001/ma3");
      ma4 = nAPI.getNewRemoteMulticastAgent("//java.se.cs.cmu.edu:9001/ma4");

      nAPI.connectAgents(ma1, ma2);
      nAPI.connectAgents(ma2, ma3);
      nAPI.connectAgents(ma3, ma4);
      System.out.println("connected");

      nAPI.addObjectToAgent(ma1, o1);
      nAPI.addObjectToAgent(ma2, o2);
      nAPI.addObjectToAgent(ma3, o3);
      nAPI.addObjectToAgent(ma4, o4);
      System.out.println("Objects added");

      //delay
      for (int i=0; i<50000000; i++);

      // TESTING MESSAGE STARTING POINT
      System.out.print("Testing message starting point...");

      // Agents receiving message: ma1, ma2, ma3, ma4.
      nAPI.multicastMessage(ma1, "receiveMessage", new Object[]{"Initiated from ma1"}, 
                            "edu.cmu.paid.network.test.MulticastTestObject");

      // Agents receiving message: ma1, ma2, ma3, ma4.
      nAPI.multicastMessage(ma2, "receiveMessage", new Object[]{"Initiated from ma2"}, 
                            "edu.cmu.paid.network.test.MulticastTestObject");

      // Agents receiving message: ma1, ma2, ma3, ma4.
      nAPI.multicastMessage(ma3, "receiveMessage", new Object[]{"Initiated from ma3"}, 
                            "edu.cmu.paid.network.test.MulticastTestObject");

      // Agents receiving message: ma1, ma2, ma3, ma4.
      nAPI.multicastMessage(ma4, "receiveMessage", new Object[]{"Initiated from ma4"}, 
                            "edu.cmu.paid.network.test.MulticastTestObject");

      //delay
      for (int i=0; i<50000000; i++);

      // TESTING CONNECTIVITY
      System.out.println("Testing connectivity...");

      nAPI.connectAgents(ma1, ma4);
      System.out.println("Created loop in agents...");

      // Agents receiving message: ma1, ma2, ma3, ma4.
      nAPI.multicastMessage(ma1, "receiveMessage", new Object[]{"Loop message"}, 
                            "edu.cmu.paid.network.test.MulticastTestObject");

      //delay
      for (int i=0; i<50000000; i++);

      nAPI.disconnectAgents(ma1, ma2);
      //nAPI.disconnectAgents(ma2, ma1);
      System.out.println("Broke loop...");

      //delay
      for (int i=0; i<50000000; i++);

      // Agents receiving message: ma1, ma2, ma3, ma4.
      nAPI.multicastMessage(ma1, "receiveMessage", new Object[]{"Broken loop message"}, 
                            "edu.cmu.paid.network.test.MulticastTestObject");

      //delay
      for (int i=0; i<50000000; i++);

      nAPI.disconnectAgents(ma3, ma4);
      System.out.println("Broke into pairs...");

      //delay
      for (int i=0; i<50000000; i++);

      // Agents receiving message: ma1, ma4.
      nAPI.multicastMessage(ma1, "receiveMessage", new Object[]{"Pair 1"}, 
                            "edu.cmu.paid.network.test.MulticastTestObject");
      // Agents receiving message: ma2, ma3.
      nAPI.multicastMessage(ma2, "receiveMessage", new Object[]{"Pair 2"}, 
                            "edu.cmu.paid.network.test.MulticastTestObject");

      //delay
      for (int i=0; i<50000000; i++);

      nAPI.disconnectAgents(ma2,ma3);
      nAPI.connectAgents(ma3, ma4);
      System.out.println("Broke into single and triplet...");

      //delay
      for (int i=0; i<50000000; i++);

      // Agents receiving message: ma2.
      nAPI.multicastMessage(ma2, "receiveMessage", new Object[]{"Singlet"}, 
                            "edu.cmu.paid.network.test.MulticastTestObject");
      // Agents receiving message: ma1, ma3, ma4.
      nAPI.multicastMessage(ma1, "receiveMessage", new Object[]{"Triplet"}, 
                            "edu.cmu.paid.network.test.MulticastTestObject");

      //delay
      for (int i=0; i<50000000; i++);

      // Fully connect agents 1 and 2 and break all other connections.
      nAPI.connectAgents(ma2, ma1);
      nAPI.connectAgents(ma2, ma3);
      nAPI.connectAgents(ma2, ma4);
      nAPI.disconnectAgents(ma3, ma4);
      nAPI.connectAgents(ma1, ma3);
      System.out.println("Created complete interconnect except ma3 and ma4");
      
      //delay
      for (int i=0; i<50000000; i++);

      // Agents receiving message: ma1, ma2, ma3, ma4.
      nAPI.multicastMessage(ma1, "receiveMessage", new Object[]{"Fully connected message"}, 
                            "edu.cmu.paid.network.test.MulticastTestObject");

      // TESTING OBJECTS INSIDE AGENTS
      System.out.println("Testing objects");

      //delay
      for (int i=0; i<50000000; i++);

      MulticastTestObject o5 = new MulticastTestObject();
      o5.name = "o5";
      nAPI.addObjectToAgent(ma3, o5);
      System.out.println("Added o5 to ma3...");

      //delay
      for (int i=0; i<50000000; i++);

      // Agents receiving message: ma1, ma2, ma3, ma4.
      nAPI.multicastMessage(ma1, "receiveMessage", new Object[]{"5 object message"}, 
                            "edu.cmu.paid.network.test.MulticastTestObject");

      //delay
      for (int i=0; i<50000000; i++);

      nAPI.removeObjectFromAgent(ma2, o2);
      System.out.println("Removed o2 from ma2...");

      //delay
      for (int i=0; i<50000000; i++);

      // Agents receiving message: ma1, ma2, ma3, ma4.
      nAPI.multicastMessage(ma1, "receiveMessage", new Object[]{"4 object message, started ma1"}, 
                            "edu.cmu.paid.network.test.MulticastTestObject");
      // Agents receiving message: ma1, ma2, ma3, ma4.
      nAPI.multicastMessage(ma2, "receiveMessage", new Object[]{"4 object message, started ma2"}, 
                            "edu.cmu.paid.network.test.MulticastTestObject");
      // Agents receiving message: ma1, ma2, ma3, ma4.
      nAPI.multicastMessage(ma3, "receiveMessage", new Object[]{"4 object message, started ma3"}, 
                            "edu.cmu.paid.network.test.MulticastTestObject");
      // Agents receiving message: ma1, ma2, ma3, ma4.
      nAPI.multicastMessage(ma4, "receiveMessage", new Object[]{"4 object message, started ma4"}, 
                            "edu.cmu.paid.network.test.MulticastTestObject");
  
      //delay
      for (int i=0; i<50000000; i++);

      nAPI.addObjectToAgent(ma4, o2);
      System.out.println("Added o2 to ma4...");

      //delay
      for (int i=0; i<50000000; i++);

      // Agents receiving message: ma1, ma2, ma3, ma4.
      nAPI.multicastMessage(ma4, "receiveMessage", new Object[]{"o2 new location"}, 
                            "edu.cmu.paid.network.test.MulticastTestObject");

      nAPI.disconnectMachine();

    } catch (java.lang.Exception e){
      System.err.println(e);
    }
  } 
}

