package ae {

import flash.display.Sprite;

import flash.events.Event;
import flash.events.MouseEvent;

class Circle extends Sprite 
{
	//width
	public var w:Number;
	//height
	public var h:Number;
	//radius
	public var r:Number;
	//radius / 2
	public var r2:Number;
	//color
	public var c:int;
	
	// interpolation factor
	private var t:Number = 0;
	// time step
	private var step:Number = 0.06;
	
	public var node:CircleNode;
	
	public static var cs:CircleSplit;
	
	public function Circle(_w:Number, _h:Number, _cs:CircleSplit = null)
	{
		super();
		w = _w;
		h = _h;
		r = w/2;
		r2 = r/2;
		if (_cs != null)
			Circle.cs = _cs;
		
		

	}
	
	public function setColor() : void
	{
		if (Circle.cs.pic == null)
		{
			//generate a random color that's not too dark
			var red:int = int(Math.random() * 224) + 32;
			var g:int = int(Math.random() * 224) + 32;
			var b:int = int(Math.random() * 224) + 32;
			c = (red << 16) + (g << 8) + b;
			return;
		}
		
		//sample the pic
		var xm:int = x+r;
		var ym:int = y+r;
		var c1:int = Circle.cs.pic.getPixel32(int(xm-r2), int(ym-r2));
		var c2:int = Circle.cs.pic.getPixel32(int(xm+r2), int(ym-r2));
		var c3:int = Circle.cs.pic.getPixel32(int(xm-r2), int(ym+r2));
		var c4:int = Circle.cs.pic.getPixel32(int(xm+r2), int(ym+r2));
		var cm:int = Circle.cs.pic.getPixel32(int(xm), int(ym));
		c =  averageColor(new Array(c1, c2, c3, c4, cm, cm) );
	}
	
	private function averageColor(a:Array):int
	{
		var rt:int = 0;
		var gt:int = 0;
		var bt:int = 0;
		for each(var cc:int in a)
		{
			rt += (cc >> 16) & 0xFF;
			gt += (cc >> 8) & 0xFF;
			bt += (cc >> 0) & 0xFF;
		}
		return ((rt/a.length) << 16) + ((gt/a.length) << 8) + (bt/a.length);
	}
	
	private function handleFrame(e:Event)
	{
		if (t >= 1)
		{
			// we're done animating
			removeEventListener(Event.ENTER_FRAME, handleFrame);
			split();
		}
		else
		{
			t += step;
			draw();
		}
	}
	
	// draw 4 circles (while animating)
	// animate by interpolating the x,y coords and radius
	public function draw():void
	{
		this.graphics.clear();
		
		// blank the bg behind the original circle
		// this happens after the first step to avoid a flicker
		if (t == step)
			(this.parent as CircleSplit).drawSquare(this);
		
		this.graphics.beginFill(c);
		this.graphics.drawCircle(lerp(r, r-r2, t) , lerp(r, r-r2, t), lerp(r, r2, t));
		this.graphics.endFill();
		
		this.graphics.beginFill(c);
		this.graphics.drawCircle(lerp(r, r-r2, t) , lerp(r, r+r2, t), lerp(r, r2, t));
		this.graphics.endFill();
		
		this.graphics.beginFill(c);
		this.graphics.drawCircle(lerp(r, r+r2, t) , lerp(r, r-r2, t), lerp(r, r2, t));
		this.graphics.endFill();
		
		this.graphics.beginFill(c);
		this.graphics.drawCircle(lerp(r, r+r2, t) , lerp(r, r+r2, t), lerp(r, r2, t));
		this.graphics.endFill();
	}
	
	public function handleMouseOver(e:MouseEvent)
	{
		// dont split if the mouse button is down
		if(e.buttonDown) return;
		// if we're already animating, don't do anything
		if(t > 0) return;
		// still have to do a hitTest
		if ( !hitTest(e) ) return;
		
		// start recieveving frame events to animate
		addEventListener(Event.ENTER_FRAME, handleFrame);
		this.graphics.clear();
	}
	
	// check to see if the mouse is actually inside the circle;
	private function hitTest(e:MouseEvent) : Boolean
	{
		var dx:Number = Math.abs(x+r - e.stageX);
		var dy:Number = Math.abs(y+r - e.stageY);
		var dist = Math.sqrt(dx*dx  +dy*dy);
		return dist <= r;
	}
	
	// split into 4 sub-circles/nodes
	public function split():void
	{
		//create the 4 child Circles
		var c1:Circle = new Circle(r, r);
		var c2:Circle = new Circle(r, r);
		var c3:Circle = new Circle(r, r);
		var c4:Circle = new Circle(r, r);
		
		// the global midlines of the circle
		var ymid:Number = y+r;
		var xmid:Number = x+r;
		// set up their coords
		c1.x = x;    c1.y = y;
		c2.x = xmid; c2.y = y;
		c3.x = x;    c3.y = ymid;
		c4.x = xmid; c4.y = ymid;
		
		c1.setColor(); c2.setColor(); c3.setColor(); c4.setColor();
		
		// create the assicated tree nodes
		var cn1:CircleNode = new CircleNode(c1);
		var cn2:CircleNode = new CircleNode(c2);
		var cn3:CircleNode = new CircleNode(c3);
		var cn4:CircleNode = new CircleNode(c4);
		
		// set the thresholds on the nodes
		cn1.xThresh = xmid - r2;
		cn1.yThresh = ymid - r2;
		
		cn2.xThresh = xmid + r2;
		cn2.yThresh = ymid - r2;
		
		cn3.xThresh = xmid - r2;
		cn3.yThresh = ymid + r2;
		
		cn4.xThresh = xmid + r2;
		cn4.yThresh = ymid + r2;

		// set up the tree
		node.addChildren(cn1, cn2, cn3, cn4);
		
		// draw the new circles
		(this.parent as CircleSplit).addCircles(new Array(c1, c2, c3, c4));

		// this circle is no longer needed, remove all references to it
		node.parentCircle = null;
		node = null;
		this.parent.removeChild(this);
		
	}
	
	// standard linear interpolation function
	private function lerp(a:Number, b:Number, t:Number) : Number
	{
		return a * (1-t) + b * t;
	}

}

}