import java.awt.*;
import java.util.*;

/************************************************
 *  Implementation of a directed ray            *
 *  Original code provided by Leonard McMillan  *
 ************************************************/

class Ray {
  public static final float MAX_T = Float.MAX_VALUE;
  public static final int MAX_DEPTH = 20;
  Vector3D origin;
  Vector3D direction;
  float t;
  int depth;
  Renderable object;
  
  public Ray(Vector3D eye, Vector3D dir) {
    origin = new Vector3D(eye);
    direction = Vector3D.normalize(dir);
    depth = 1;
  }

  public Ray(Vector3D eye, Vector3D dir, int d) {
    origin = new Vector3D(eye);
    direction = Vector3D.normalize(dir);
    depth = d;
  }
  
  public boolean trace(Vector objects) {
    Enumeration objList = objects.elements();
    t = MAX_T;
    object = null;
    while (objList.hasMoreElements()) {
      Renderable object = (Renderable) objList.nextElement();
      object.intersect(this);
    }
    return (object != null);
  }
  
  public float lightFactor(Vector objects) {
    float factor = 1f;
    Enumeration objList = objects.elements();
    object = null;
    while ((objList.hasMoreElements()) && (factor > 0)) {
      Renderable object = (Renderable) objList.nextElement();
      t = MAX_T;
      if (object.intersect(this))
	factor *= object.transparency();
    }
    this.trace(objects);
    return factor*factor;
  }

  // The following method is not strictly needed, and most likely
  // adds unnecessary overhead, but I prefered the syntax
  //
  //            ray.Shade(...)
  // to
  //            ray.object.Shade(ray, ...)
  //
  public final Color Shade(Vector lights, Vector objects, Color bgnd) {
    if (depth > MAX_DEPTH) return bgnd;
    return object.Shade(this, lights, objects, bgnd);
  }
  
  public String toString() {
    return ("ray origin = "+origin+"  direction = "+direction+"  t = "+t);
  }
}
