import eduni.simjava.*;
import eduni.simanim.*;

import simdistalg.*;

public class Channel_tester extends Anim_applet {
  public void anim_layout() {
    Sim_pos_entity.clear_entity_list(); // routine call
    Sim_entity source = new Source("source", "source-img", 300, 60,
        1, Source.SRC_OK);
    Sim_entity sink = new Sink("sink", "sink-img", 10, 10, 2, Sink.SINK_OK);
    // source has an out-port, sink has an in-port
    Sim_unidir_channel channel =
        new Sim_unidir_channel("source", "out", "sink", "in",
            Sim_unidir_channel.center_pos(300,10),
            Sim_unidir_channel.center_pos(10,60),
            Anim_port.RIGHT, // inport side
            Anim_port.LEFT,  // outport side
            // other fault parameters
            (float) 0.4, // loss rate
            (float) 0.2,   // duplication rate
            (float) 0.2,   // reordering rate
            15, 1, 1, // delay +/-
            Anim_port.TOP); // message stack
    // add entities to simulation:
    Sim_system.add(source);
    Sim_system.add(sink);
    Sim_system.add(channel);
    // connect the ports
    channel.connect();
  }
}
class Source extends Sim_entity {
  private Sim_port out;
  private int index;
  private int state;

  public static final int SRC_OK      = 0;
  public static final int SRC_BLOCKED = 1;

  public Source(String name, String image, int x, int y,
      int index, int state) {
    super(name, image, x, y);
    this.index = index;
    this.state = state;
    out = new Sim_port("out", "out-port", Anim_port.LEFT, 10);
    add_port(out);
  }

  public void body() {
    Sim_event ev = new Sim_event();
    int i = 0;

    System.out.println("About to do body S");
    while (true) {
      System.out.println("source: sending message " + i);
      sim_schedule(out,0.0,0,
          new Sim_message_info(Sim_system.clock(),
            get_id(), get_name(), out, "out", "sink", "in",
            "[" + i + "]", "[" + i + "]"));
      sim_trace(1, "S out [" + i + "]");
      // sim_wait(ev);
      sim_hold(Math.abs(20.0-i));
      i++;
      if(i>40) Sim_system.run_stop();
    }
    // System.out.println("Exiting body S");
  }
}
class Sink extends Sim_entity {
  private Sim_port in;
  private int index;
  private int state;

  public static final int SINK_BLOCKED = 0;
  public static final int SINK_OK      = 1;

  public Sink(String name, String image, int x, int y,
      int index, int state) {
    super(name, image, x, y);
    this.index = index;
    this.state = state;
    in = new Sim_port("in", "in-port", Anim_port.RIGHT, 10);
    add_port(in);
  }

  public void body() {
    Sim_event ev = new Sim_event();
    Sim_message_info info;
    int i = 0;

    System.out.println("About to do body R");
    while(true) {
      i++;
      System.out.println("sink: waiting for message");
      if (sim_waiting() > 0) {
        sim_select(Sim_system.SIM_ANY, ev);
        info = (Sim_message_info) ev.get_data();
        System.out.println("sink: received message " +
            (String) info.get_data() +
            " from " + info.get_sender_id() +
            " start time " + info.get_start_time() +
            " (=delay " + (ev.event_time() - info.get_start_time()) +
            ")");
       }
       sim_hold(1.0);
    }
    // System.out.println("Exiting body R");
  }
}

