import java.util.HashSet;
import java.util.Set;

abstract class Value<T> {
	// the currently calling Value. It must depend on "this".
	static private ThreadLocal<Value<?>> current = new ThreadLocal<Value<?>>();

	// meat.
	protected abstract T eval();

	// cached value
	private T value;

	// Accumulation of LazyExprs that depend on "this"
	private Set<Value<?>> depends = new HashSet<Value<?>>();

	// override cached value and clear values that depend on "this"
	synchronized public void setValue(T v) {
		if (v != value) {
			for (Value<?> d : depends) {
				d.setValue(null);
			}
			value = v;
		}
	}

	// return cached value or calculate
	synchronized public T getValue() {
		// d must depend on this, because it's asking for this.value.
		Value<?> d = current.get();
		if (d != null) {
			depends.add(d);
		}
		// is the value set?
		if (value == null) {
			// to calculate this value make sure things we depend on know that
			// we depend on them
			current.set(this);
			value = eval();
			current.set(d);
		}
		return value;
	}

	/**
	 * execute eval in thread. getValue() blocks while eval is executing.
	 */
	public void evalInThread() {
		if (value == null) {
			synchronized (this) {
				new Thread() {
					public void run() {
						synchronized (Value.this) {
							Value.this.notify();
							getValue();
						}
					}
				}.start();
				try {
					// wait until thread has monitor
					wait();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
}

/**
 * works with dependency system, but does not get evaluated.  These Variables must be assigned to.
 * 
 * @author battjt
 * 
 * @param <T>
 */
class Variable<T> extends Value<T> {
	@Override
	protected T eval() {
		return null;
	}
}

class Point {
	double x, y;

	public double distance(Point that) {
		double dx = this.x - that.x;
		double dy = this.y - that.y;
		return Math.sqrt(dx * dx + dy * dy);
	}
}

/**
 * Example class
 * 
 * @author battjt
 * 
 */
class Circle {
	final public Value<Point> center = new Variable<Point>();

	final public Value<Double> radius = new Variable<Double>();

	/**
	 * immediately calculate if p is inside of circle
	 * 
	 * @param p
	 * @return
	 */
	public boolean inside(final Point p) {
		Value<Double> distance = new Value<Double>() {
			@Override
			protected Double eval() {
				return center.getValue().distance(p);
			}
		};
		// calculate center and radius in parallel
		distance.evalInThread();
		radius.evalInThread();
		return distance.getValue() < radius.getValue();
	}
}

/**
 * This is an example of multiple rules to calc these values. Fill in any of the
 * attributes of the circle, and the rest are calculable. (maybe not
 * correctly...my geometry is rusty.)
 */
class Circle2 {
	final public Value<Double> radius = new Value<Double>() {
		public Double eval() {
			return (circumference.getValue() != null) ? circumference
					.getValue()
					/ (2 * Math.PI) : Math.sqrt(area.getValue() / Math.PI);

		}
	};
	final public Value<Double> circumference = new Value<Double>() {
		public Double eval() {
			return radius.getValue() * 2 * Math.PI;
		}
	};

	final public Value<Double> area = new Value<Double>() {
		public Double eval() {
			return Math.PI * radius.getValue() * radius.getValue();
		}
	};
}