/* A simple Source and Sink example, VRML Animated version.
 * The source sends 10 messages to the sink, and waits for acks.
 */

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import eduni.simanim.*;
import eduni.simjava.*;

/* === Vrml includes */
import vrml.external.field.*;
import vrml.external.Node;
import vrml.external.Browser;
import vrml.external.exception.*;

class Source extends Sim_entity {
  private Sim_port out;
  private int index;

  /* === Store applet reference */
  private Applet1 app;

  public Source(String name, int index, int x, int y, Applet1 app) {
    super(name, "source", x,y);
    this.index = index;
    this.app = app;
    out = new Sim_port("out", "port", Anim_port.RIGHT, 10); add_port(out);
    String[] srcstate = {"waiting","holding"};
    add_param(new Anim_param( "State", Anim_param.STATE, 
			      new Param_type("srcstate", srcstate) ));
  }

  // --- Connect to VRML node.
  Node mynode = null;
  EventInMFString picture=null;
  void connect3d() {
    mynode = app.getNode(get_name());
    picture = (EventInMFString) app.getEventIn(mynode, "set_picture");
  }
  void update3d(String s) {
    String[] ss = new String[1]; ss[0]=s;
    if (picture != null) { picture.setValue(ss); }    
  }

  public void body() {
    connect3d();
    Sim_event ev = null;
    int i;
    for (i=0; i<10; i++) {
      sim_trace(1,"S out msg"+i);
      sim_schedule(out,0.0,0);
      sim_trace(1,"P waiting");
 	update3d("bitmaps\\source.waiting.gif");
      sim_wait(ev);
      sim_trace(1,"P holding");
 	update3d("bitmaps\\source.holding.gif");
      sim_hold(10.0);
    }
  }
}

class Sink extends Sim_entity {
  private Sim_port in;
  private int index;
  private int count = 0;
  private Applet1 app;
  public Sink(String name, int index, int x, int y, Applet1 app) {
    super(name, "sink", x, y);
    this.index = index;
    this.app = app;
    in = new Sim_port("in", "port", Anim_port.LEFT, 10);  add_port(in);
    String[] sinkstate = {"waiting","holding"};
    add_param(new Anim_param( "SinkState", Anim_param.STATE, 
			      new Param_type("sinkstate", sinkstate) ));
    add_param(new Anim_param("Count", Anim_param.NAME_VALUE, "0", -10, -5));
  }

  // --- Connect to VRML node.
  // This is a primitive approach to getting the icon node and the 
  // text node. It would be better to define a new PROTO for ICON+TEXT.
  Node mynode = null;
  Node countnode = null;
  EventInMFString picture=null;
  EventInMFString counttext=null;
  void connect3d() {
    mynode  = app.getNode(get_name());
    picture = (EventInMFString) app.getEventIn(mynode, "set_picture");
    countnode  = app.getNode(get_name()+"_count");
    counttext = (EventInMFString) app.getEventIn(countnode, "set_message");
  }
  void update3d(String icons, String counts) {
    String[] ss = new String[1]; ss[0]=icons;
    String[] st = new String[1]; st[0]=counts;
    if (picture != null) { picture.setValue(ss); }    
    if (counttext != null) { counttext.setValue(st); }    
  }

  public void body() {
    Sim_event ev = null;
    connect3d();
    while(true) {
      sim_wait(ev);
      count ++;  

	sim_trace(1,"P holding "+count); 
		update3d("bitmaps\\sink.holding.gif", "Count ="+count);
      sim_hold(5);
      sim_trace(1,"P waiting "+count); 
		update3d("bitmaps\\sink.waiting.gif", "Count ="+count);

      sim_trace(1,"S in ack");
      sim_schedule(in,0.0,1);
    }
  }
}

public class Applet1 extends Anim_applet {

  // === VRML nodes
  Browser browser=null;
  boolean error=false;
  void pause(int t) {
    try {Thread.currentThread().sleep(t);} catch (InterruptedException e) {
	System.out.println("Rudely interrupted");
    }
  }
  public void initBrowser() { 
    System.out.println("About to connect to browser.");
    pause(1000);
    browser = Browser.getBrowser(this);
    if (browser == null) {
	System.out.println("Didn't get the browser: ");
	error = true;
    } else  {
	System.out.println("Got the browser: ");
	error = false;
    }
  }
  public Node getNode(String name) {
    Node n = null;
    if (!error) {
      try {n = browser.getNode(name); }
      catch (InvalidNodeException ne) { 
	  System.out.println("Failed to get node:" + ne);   
	  error = true; }
    }
    return n;
  }
  public EventIn getEventIn(Node n, String ename) {
    EventIn e = null;
    if (!error) {
    if (n!=null) {
	try {
 	  e = n.getEventIn(ename);
 	} catch (Exception ex) { 
	  System.out.println("Couldn't get event "+ename+":"+ex);
	}
    }}
    return e;
  }
  // --- End VRML Nodes ---




  public void anim_layout() {
    initBrowser();
    Sim_system.add(new Source("Sender", 1, 20,20,this));
    Sim_system.add(new Sink("Receiver", 2, 120,20,this));
    Sim_system.link_ports("Sender", "out", "Receiver", "in");
  }
}
