import ByteConverter;
import ClientInfo;
import VGateway;
import java.io.*;
import java.net.*;

public class synthesizer {
    // service types
    public final static int SVC_VIDEOCONFERENCE = 1;
    // components
    public final static int CMP_JIACHENG_VIDEO_GATEWAY = 1;
    // response
    public final static int SUCCESS = 0;
  
    public static void usage() {
	System.err.println("usage: java synthesizer inputtextfile");
	System.exit(1);
    }
    
    public static void main(String[] args) {
	int error = 0;
	if (args.length != 1) {
	    synthesizer.usage();
	}
	
	// synthesizer.parse(); //but prefer the interface to be sequential window options
	int numParticipants = 2;
	
	// switch to Video Conferencing recipe
	// recipe load? load classes?  start new threads?

	// recipe includes predefined requirements
	// i.e. VC - latency of x ms, bandwidth of mbps
	
	// recipe -> talk to SIP gateway component for SIP to send invites
	// SIP to take care of ns/ip lookup
	
	// get SIP socket
	// getComponentSocket(CMP_JIACHENG_SIP_GATEWAY);
	// send info to Jiacheng's SIP/H.323 gateway
	// if IP multicast unavailable - use EndSysMulticast
	// if response says no common video format -> search for transcoder
	
	try {
	    // create a TCP socket for sending message
	    ClientInfo clients[] = new ClientInfo[numParticipants];
	    byte[] multicastIPbuf = new byte[4];
	    byte[] sidbuf = new byte[12];
	    int multicastPort = -1;
	    int sessionID = -1;
            Socket sock = new Socket(InetAddress.getByName("rivest.ini.cmu.edu"),	       5000);	    
	    ByteArrayOutputStream bout = new ByteArrayOutputStream();
	    DataOutputStream out = new DataOutputStream(bout);
	    
	    //  clients[0] = new ClientInfo("clin", InetAddress.getByName("federation.nectar.cs.cmu.edu"));
	    clients[0] = new ClientInfo("clin", InetAddress.getByName("swissvale.cmcl.cs.cmu.edu"));
	    clients[1] = new ClientInfo("glenwood", InetAddress.getByName("orlando.cmcl.cs.cmu.edu"));
	    
	    // "poll" video gateway for capability
            out.writeInt(VGateway.GETIPMultiCastCommand);
	    out.writeInt(numParticipants);
	    for (int i = 0; i < numParticipants; i++) {
		out.writeInt((clients[i].clientName).length());
		out.write((clients[i].clientName).getBytes("ASCII"), 0, (clients[i].clientName).length());
		out.write((clients[i].ipaddress).getAddress(), 0, 4);
	    }
	    bout.writeTo(sock.getOutputStream());
	    bout.flush();
      
	    // wait up to 20 seconds for a response?
	    DataInputStream in = new DataInputStream(sock.getInputStream());
	    
	    // get multicast address and port
	    // and addresses that don't support IP multicast
	    //      String multicastIP = new String("255.100.100.100");
            error = in.read(multicastIPbuf);
	    String multicastIP = ByteConverter.BE_makeIPAddr(multicastIPbuf, 0);
	    System.out.println("Multicast IP address is " + multicastIP);
	    multicastPort = in.readInt(); //Int is 32 bits
	    System.out.println("multicast port is: " + multicastPort);
	    
	    in.readFully(sidbuf);
	    System.out.println("Session ID is : " + new String(sidbuf));
	    
	    String mySSID = new String(sidbuf);
	    //assuming success right now
	    // this should be where gateway returns the IP addresses of 
	    // end points that don't support IP multicast
	    //      error =  in.readInt();
	    error = SUCCESS;
	    if (error != SUCCESS) {
		// if no common vid format, then find transcoder. 
		if (error == VGateway.CMP_SIPGTWY_NO_COMMON_VID_FORMAT ) {
		    
		}
	    }
	    
	    //send IP addresses and IP multicast address/port to ESM
	    // don't forget video gateway's IP if 
	    
	    // receive OK from ESM proxy setup
	
	    // send commit to video Gateway and ESM
	    
	    // to video gateway
	    bout = new ByteArrayOutputStream();
	    out = new DataOutputStream(bout);
	    out.writeInt(VGateway.CommitSetup);
	    out.write(mySSID.getBytes("ASCII"), 0, mySSID.length());
	    bout.writeTo(sock.getOutputStream());
	    bout.flush();
	    System.out.println("sent commit to video gateway" );
	    //	System.exit(1);
	    // to ESM
	    // send 
	    Socket ESMsock = new Socket(InetAddress.getByName("federation.nectar.cs.cmu.edu"), 5005);	
	    ByteArrayOutputStream bout2 = new ByteArrayOutputStream();
	    DataOutputStream out2 = new DataOutputStream(bout2);

	    // hmmm...do i need another bytearray and dataoutput? yes
	    int myport = multicastPort;
	    String invokeProxy = new String("./proxy -t 0 -g " + multicastIP + " -p " + new Integer(myport).toString() + " -p " +  new Integer(myport+1).toString() + " -t 0 &");
	    String invokeVic = new String("./vic -X loopback=1 -t 0 " + multicastIP + "/" + new Integer(myport).toString() + " &");
	    String invokeProxy2 = new String("./proxy -t 0 -g " + multicastIP + " -p " + new Integer(myport).toString() + " -p " +  new Integer(myport+1).toString() + " -t 0 -m " + "orlando.cmcl.cs.cmu.edu &");

	    out2.write(invokeVic.getBytes("ASCII"), 0, invokeVic.length());
	    bout2.writeTo(ESMsock.getOutputStream());
	    
	    bout2 = new ByteArrayOutputStream();
	    out2 = new DataOutputStream(bout2);
	    out2.write(invokeProxy2.getBytes("ASCII"), 0, invokeProxy2.length());
	    bout2.writeTo(ESMsock.getOutputStream());
	    
	    ESMsock = new Socket(InetAddress.getByName("orlando.cmcl.cs.cmu.edu"),			       5005);
	    //      bout2.writeTo(ESMsock.getOutputStream());
	    bout2 = new ByteArrayOutputStream();
	    out2 = new DataOutputStream(bout2);
	    out2.write(invokeProxy.getBytes("ASCII"), 0, invokeProxy.length());
	    bout2.writeTo(ESMsock.getOutputStream());
	    
	    ESMsock = new Socket(InetAddress.getByName("federation.nectar.cs.cmu.edu"), 5005);	
	    bout2 = new ByteArrayOutputStream();
	    out2 = new DataOutputStream(bout2);
	    out2.write(invokeProxy2.getBytes("ASCII"), 0, invokeProxy2.length());
	    bout2.writeTo(ESMsock.getOutputStream());
	} catch (IOException e) {
	    System.err.println(e.getMessage());
	}
    }
    
  /* 
   * Parses the input file
   *
   */

    public void parse() throws FileNotFoundException, IOException  {
    StreamTokenizer tk = new StreamTokenizer(new FileReader("testfile"));
    int token;
    boolean error;
    String curToken;
    
    tk.slashSlashComments(true);  // C++ style comments
    tk.lowerCaseMode(true);       // String tokens are lower cased

  }

  /*    
   *  sends messages to components
   */
  public long sendMessage(byte msg[],int msgType, InetAddress routerAddr, int routerPort) {
    //    int offset, cl_count, entries;
    //    int numactions = 0;
    try {
      //create a TCP socket for sending message
      Socket sock = new Socket(routerAddr,
			       routerPort);
      
      ByteArrayOutputStream bout = new ByteArrayOutputStream();
      DataOutputStream out = new DataOutputStream(bout);
      out.writeInt(3);
      //      for (i = 0; i < 3; i++) {
      out.write((InetAddress.getByName("128.2.185.113")).getAddress(), 0, 4);
      //      }
      bout.writeTo(sock.getOutputStream());
    } catch (Exception e) {
      System.err.println(e.getMessage());
    }
    return 0;

  }
}
