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

abstract public class PhysicalObject extends Object
 {
  public String name;
  public double mass;   // 0 = negligible mass
  public Color color;
  public boolean prehistoric;  // true if object has existed since t=-infty
  public boolean immortal;     // true if object will exist until t=+infty
                               // else it is destroyed at endProperTime
  public boolean definite;     // true if object has been fully defined
  public double length;
  double initProperTime;       // proper time at creation of object
  double endProperTime;        // last time object was edited


  PhysicalObject()
   {
    prehistoric = true;
    immortal = true;
    definite = false;
    initProperTime = endProperTime = 0;
    name = "Object";
    color = Color.black;
    length = 0;
   }
 
  abstract public double abs_t(double properTime);
  abstract public double abs_x(double properTime);

  public SpacetimePoint creation()
   {
    return location(initProperTime);
   }

  public SpacetimePoint destruction()
   {
    return location(endProperTime);
   }

  public boolean existsAt(double properTime)
   {
    if (properTime < initProperTime - 0.0001)
      return prehistoric;

    if (properTime > endProperTime + 0.0001)
      return immortal;

    return true;
   }

  public boolean existsAt(ReferenceFrame f, double t)
   {
    if (t < f.t(creation()) - 0.0001)
      return prehistoric;

    if (t > f.t(destruction()) + 0.0001)
      return immortal;

    return true;
   }

  public void setInitialProperTime(double t0)
   {
    initProperTime = endProperTime = t0;
   }

  abstract public void setInitialLocation(SpacetimePoint p);

  abstract public void setInitialVelocity(double v);

  public boolean determinedAt(double properTime)
	// true if object exists and cannot be further changed at properTime
   {
    if (definite) return true;
    if (properTime > endProperTime + 0.0001) return false;
    return true;
   }

  public SpacetimePoint location(double properTime)
   {
    return new SpacetimePoint(abs_x(properTime), abs_t(properTime));
   }

  public SpacetimePoint location(double properX, double properTime)
   {
    double x = abs_x(properTime);
    double t = abs_t(properTime);
    double v = velocity(properTime);
    double gamma = Math.sqrt(1 - v*v);

    return new SpacetimePoint(x + properX*gamma, t + properX*v*gamma);
   }

  public double velocity()
	// for non-inertial objects, gives the initial velocity
   {
    return velocity(initProperTime);
   }

  abstract public double velocity(double properTime);

  abstract public double intersect(ReferenceFrame f, double t);
      // gives the proper time of intersection of object with f.t = t

  abstract public ReferenceFrame closest(SpacetimePoint p);
      // gives the reference frame of object closest to p
 }
