import java.util.Random;

public class Spinny extends Shape {
	public double len = 0.;
	public double lalph = 0.,ralph = 0.,
		last_lalph = 0., last_ralph = 0.;
	public static double DRAG = 0.91;


	Spinny l_ = null,r_ = null;
	Sphere sphere_ = null;
	Tube tube_ = null;
	int level_;
	static Random rnd = new Random();
	
	Spinny(int level) {
		super(0,0,0);
		level_ = level;
		int detail = Math.max(11-level,4);
		sphere_ = new Sphere(detail,detail);
		tube_ = new Tube(detail);
		children_ = new Shape[4];
		children_[0] = sphere_;
		children_[1] = tube_;
		sphere_.setScale(1/6.,1/6.,1/6.);
		tube_.setRotationY(Math.PI/2.);
		grow(0);
	}

	void expand(int n) {
		if(n==0)
			return;
		else if(l_==null) {
			boolean shrink = n%2 != 0;
			children_[2] = l_ = new Spinny(level_+1);
			children_[3] = r_ = new Spinny(level_+1);
			if(shrink) {
				l_.setScale(0.5,0.5,0.5);
				r_.setScale(0.5,0.5,0.5);
			}
			l_.setRotationZ(Math.PI/2.);
			r_.setRotationZ(-Math.PI/2.);
			grow(0);
		}
		l_.expand(n-1);
		r_.expand(n-1);
	}
	void contract(int n) {
		if(l_!=null)
			l_.contract(Math.max(n-1,0));
		if(r_!=null)
			r_.contract(Math.max(n-1,0));
		if(n==0) {
			l_ = null;
			r_ = null;
		}
	}	
	void grow(double dt) {
		if(l_!=null && len<0.999)
			len += dt/5.;
		if(len>1.)
			len = 1.;
		if(l_!=null)
			l_.setTranslation(-len,0,0);
		if(r_!=null)
			r_.setTranslation(len,0,0);
		tube_.setScale(1/16.,1/16.,len);
	}
	void spin() {
		if(l_!=null) {
			double dla = lalph - last_lalph;
			dla *= DRAG;
			last_lalph = lalph;
			lalph += dla;
			l_.setRotationY(lalph);
		}
		if(r_!=null) {
			double dra = ralph - last_ralph;
			dra *= DRAG;
			last_ralph = ralph;
			ralph += dra;
			r_.setRotationY(ralph);
		}
	}
	void render(Matrix3D view, double t, double dt) {
		grow(dt);
		spin();
		super.render(view,t,dt);
	}
	private static Vector3D preshTemp_ = new Vector3D();
	void presh(Vector3D where) {
				//System.out.println("presh");
		if(l_!=null) {
			l_.tube_.getWorldy().transformR(where,preshTemp_);
			if(-1 < preshTemp_.x() && preshTemp_.x() < 1
				&& -1 < preshTemp_.y() && preshTemp_.y() < 1) {
				System.out.println("hit");
				if(preshTemp_.x() < 0)
					last_lalph -= 0.01*level_;
				else
					last_lalph += 0.01*level_;
			}
			l_.presh(where);
		}
	}
	void zounds() {
		if(l_!=null) {
			last_lalph = lalph + rnd.nextGaussian()/3.;
			l_.zounds();
		}
		if(r_!=null) {
			last_ralph = ralph + rnd.nextGaussian()/3.;
			r_.zounds();
		}
	}
}