import vrml.*;
import vrml.node.*;
import vrml.field.*;

public class leader extends Script {
  // eventIn
  private SFFloat time;
  // eventOut
  private SFRotation rotation_changed;
  private SFVec3f translation_changed;

  // fields
  private SFRotation current_rotation;
  private SFVec3f current_translation;

  // variables
  private float max_ang_velocity;
  private float min_ang_velocity;

  private float max_radius_velocity;
  private float min_radius_velocity;
  private float min_radius;
  private float max_radius;

  private float max_height_velocity;
  private float min_height_velocity;
  private float min_height;
  private float max_height;

  private float time_slice;
  private float dampening;

  private float ang_acceleration;
  private float ang_velocity;
  
  private float radius_acceleration;
  private float radius_velocity;

  private float height_acceleration;
  private float height_velocity;

  public void initialize() {
    try {
      current_rotation = (SFRotation)getField("current_rotation");
      current_translation = (SFVec3f)getField("current_translation");
      rotation_changed = (SFRotation)(getEventOut("rotation_changed"));
      translation_changed = (SFVec3f)(getEventOut("translation_changed"));

      max_ang_velocity = (float).9;
      min_ang_velocity = (float).1;

      max_radius_velocity = (float).9;
      min_radius_velocity = (float)-.9;
      min_radius = 3;
      max_radius = 12;

      max_height_velocity = (float).9;
      min_height_velocity = (float)-.9;
      min_height = 2;
      max_height = 7;

      time_slice = (float).2;
      dampening = (float).985;
 
      ang_acceleration = 0;
      ang_velocity = 0;

      radius_acceleration = 0;
      radius_velocity = 0;

      height_acceleration = 0;
      height_velocity = 0;
    }
    catch (InvalidFieldException e) {
      System.exit(1);
      System.out.println("something died on initialization");
    }
  }

  public void time_signal() {
    // to get the new rotation;
    float rot[] = new float[4];
    current_rotation.getValue(rot);
    ang_acceleration = (float) (((Math.random())*2)-1);
    ang_velocity = ang_velocity+(ang_acceleration*time_slice);
    if (ang_velocity < min_ang_velocity)
      ang_velocity = min_ang_velocity;
    if (ang_velocity > max_ang_velocity)
      ang_velocity = max_ang_velocity;
    rot[3] = (float)(rot[3]+(ang_velocity*time_slice));

    current_rotation.setValue(rot);
    rotation_changed.setValue(rot);
        
    // get the location
    float trans[] = new float[3];
    current_translation.getValue(trans);

    // to get the new radius
    radius_acceleration = (float) (((Math.random())*2)-1);
    if ((trans[0] < min_radius) && (radius_acceleration < 0))
      radius_acceleration = 0-radius_acceleration;
    if ((trans[0] > max_radius) && (radius_acceleration > 0))
      radius_acceleration = 0-radius_acceleration;
    radius_velocity = (float)(radius_velocity*dampening)+(radius_acceleration*time_slice);
    if (radius_velocity < min_radius_velocity)
      radius_velocity = min_radius_velocity;
    if (radius_velocity > max_radius_velocity)
      radius_velocity = max_radius_velocity;
    trans[0] = (float)(trans[0]+(radius_velocity*time_slice));

    // get the new height.
    height_acceleration = (float) (((Math.random())*2)-1);
    if ((trans[1] < min_height) && (height_acceleration < 0))
      height_acceleration = 0-height_acceleration;
    if ((trans[1] > max_height) && (height_acceleration > 0))
      height_acceleration = 0-height_acceleration;
    height_velocity = (float)(height_velocity*dampening)+(height_acceleration*time_slice);
    if (height_velocity < min_height_velocity)
      height_velocity = min_height_velocity;
    if (height_velocity > max_height_velocity)
      height_velocity = max_height_velocity;
    trans[1] = (float)(trans[1]+(height_velocity*time_slice));

    // send the results
    current_translation.setValue(trans);
    translation_changed.setValue(trans);
  }
  
  public void processEvent(Event e) {
    String event_name = e.getName();
 
    if (event_name.equals("time")) {
      time_signal();
    }
  }
}