/* An omega network example using simjava
 */
package omega;

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import eduni.simanim.*;
import eduni.simjava.*;

//
//  The simulation entities
//

// The main applet
public class Omega extends Anim_applet implements ItemListener {
  Panel inputs;
  Label msgLabel, sizeLabel, workLabel, showMsgLabel;
  TextField msgField;
  Choice sizeChoice;
  Choice workChoice;
  Checkbox showMsgBox;
  public static boolean show_msg = true;

  public Omega() {}

  private int ilog2( int i )
  {
    int l = 0;
    for (l=0; (i>>=1)!=0; l++) ;
    return l;  
  }

  // initialise the gui inputs
  public void anim_init() {
    int i;
    inputs = new Panel();
    inputs.setLayout(new GridLayout(0,2));

    msgLabel = new Label("Messages:", Label.RIGHT);
    inputs.add(msgLabel);
    msgField = new TextField("5",3);
    inputs.add(msgField);

    sizeLabel = new Label("Switch size:", Label.RIGHT);
    inputs.add(sizeLabel);
    sizeChoice = new Choice();
    for(i=2; i<=32; i*=2) sizeChoice.addItem(" "+i+" ");
    sizeChoice.select(2);
    sizeChoice.addItemListener(this);;
    inputs.add(sizeChoice);
    
    workLabel = new Label("Workload:", Label.RIGHT);
    inputs.add(workLabel);
    workChoice = new Choice();
    workChoice.addItem(" One to all (broadcast) ");
    workChoice.addItem(" All to one (gather) ");
    workChoice.addItem(" All to all ");
    workChoice.addItem(" Random (10%) ");
    workChoice.addItem(" Random (50%) ");
    workChoice.addItem(" Random (100%) ");
    workChoice.select(2);
    inputs.add(workChoice);

    showMsgLabel = new Label("Show messages:", Label.RIGHT);
    inputs.add(showMsgLabel);
    showMsgBox = new Checkbox("");
    showMsgBox.setState(true);
    inputs.add(showMsgBox);


    this.add("North", inputs);
    System.out.println("Anim init done ");
  }

  // Setup the animation
  public void anim_layout() {
    int num_msg, i, swsize;
    double src_hold, sink_hold;

    System.out.println("Laying out simulation");
    num_msg = Integer.parseInt(msgField.getText());
    int swlogsize = (sizeChoice.getSelectedIndex())+1; // 1,2,3
    int workload  = (workChoice.getSelectedIndex()); 
    swsize = 1<<swlogsize; // 2,4,8
    double sw_hold = 0.05;
    src_hold = 1.0;
    sink_hold = 0.5; 
    show_msg = showMsgBox.getState();

    // Add entities
    int xsz = swlogsize;
    int ysz = swsize/2;
    for (int x = 0; x<xsz; x++) {
      for (int y=0; y<ysz; y++) {
	Sim_system.add(new Sw("Sw"+x+"."+y, 60 + x*50, 40 + y*50, 
			      swsize, sw_hold));
      }
    }

    for (int y=0; y<ysz*2; y++) {
      int swi = y / 2;
      Sim_system.add(new Bucket("Sink"+y, 60 + xsz*50, 30 + y*25));
      Sim_system.add(new Src("Src"+y,   10, 30 + y*25, 
			     y, swsize, num_msg, src_hold, workload));
    }



    // Link entities
    // Sources to 1st switches, last switches to sinks
    for (int y=0; y<ysz; y++) {
      Sim_system.link_ports("Src"+(y*2), "out", "Sw0."+y, "in1");
      Sim_system.link_ports("Src"+(y*2 +1), "out", "Sw0."+y, "in2");
      Sim_system.link_ports("Sw"+(xsz-1)+"."+y, "out1", "Sink"+(y*2), "in");
      Sim_system.link_ports("Sw"+(xsz-1)+"."+y, "out2", "Sink"+(y*2+1), "in");
    }
  
    // Internal connections
    for (int x = 0; x<xsz-1; x++) {
      for (int y=0; y<ysz; y++) {
	if (y<ysz/2) {
	  Sim_system.link_ports("Sw"+x+"."+y, "out1", 
				"Sw"+(x+1)+"."+y*2, "in1");
	  Sim_system.link_ports("Sw"+x+"."+y, "out2", 
				"Sw"+(x+1)+"."+(y*2+1), "in1");
	} else {
	  Sim_system.link_ports("Sw"+x+"."+y, "out1", 
				"Sw"+(x+1)+"."+(y-ysz/2)*2, "in2");
	  Sim_system.link_ports("Sw"+x+"."+y, "out2", 
				"Sw"+(x+1)+"."+((y-ysz/2)*2+1), "in2");
	}
      }
    }

  }

  public void itemStateChanged(ItemEvent e) {
    System.out.println("Item state changed");
    anim_relayout();
  }

  /** Allow omega to run in standalone mode */
  public static void main(String args[]) {
    Frame f = new Frame("Omege Network");
    Omega o = new Omega();
    f.add("Center", o);
    o.init();
    o.run();
    f.pack();
    f.show();
  }
 
}

