package ae {
	import flash.display.Sprite;
	import flash.events.MouseEvent;
	
	// quad tree used to delegate mouse events
	class CircleNode {
		
		//each Node has an associated Circle sprite
		public var parentCircle:Circle = null;
		
		//the tree has 2-way links
		protected var parent:CircleNode = null;
		
		//the children
		protected var child1:CircleNode = null;
		protected var child2:CircleNode = null;
		protected var child3:CircleNode = null;
		protected var child4:CircleNode = null;
		
		//boundaries used to select children when traversing
		public var xThresh:Number;
		public var yThresh:Number;
		
		//set up the connections to a Circle
		public function CircleNode(pc:Circle)
		{
			parentCircle = pc;
			pc.node = this;
		}
		
		// self explanatory
		public function addChildren(c1:CircleNode, c2:CircleNode, c3:CircleNode, c4:CircleNode) : void
		{
			child1 = c1; child2 = c2; child3 = c3; child4 = c4;
			c1.parent = this;
			c2.parent = this;
			c3.parent = this;
			c4.parent = this;
		}
		
		// recurse through the tree to find the handler for the mouse event
		public function findTarget(e:MouseEvent) : void
		{
			if(child1 == null 
			   && child2 == null 
			   && child3 == null 
			   && child4 == null)
			{
				//we are at a leaf node, split
				if(parentCircle != null)
					parentCircle.handleMouseOver(e);
				return;
			}
			
			//check the stage coords of the mouse event and compare with the 
			//thresholds to determine which child to recurse down into
			//we must check it that child was null, it's possible that part of the
			//tree is already at the max depth
			if     (e.stageX <  xThresh && e.stageY < yThresh && child1 != null)
				child1.findTarget(e);
			else if(e.stageX > xThresh && e.stageY <  yThresh && child2 != null)
				child2.findTarget(e);
			else if(e.stageX < xThresh && e.stageY > yThresh && child3 != null)
				child3.findTarget(e);
			else if(e.stageX > xThresh && e.stageY > yThresh && child4 != null)
				child4.findTarget(e);

		}
		
		//null out references to a given child
		public function killChild(c:CircleNode) : void
		{
			if(c == child1)
				child1 = null;
			if(c == child2)
				child2 = null;
			if(c == child3)
				child3 = null;
			if(c == child4)
				child4 = null;
			
			if(isEmpty())
				//this node is useless, delete it from the parent
				deleteMe();
		}
		
		public function isEmpty() : Boolean
		{
			return child1 == null 
			   && child2 == null 
			   && child3 == null 
			   && child4 == null;
		}
		
		// "delete" in this case just means to remove all references to the node so it can be GC'ed
		public function deleteMe() : void
		{
			parentCircle = null;
			child1 = null;
			child2 = null;
			child3 = null;
			child4 = null;
			if(parent != null) // this could be the root node
			{
				parent.killChild(this);
				parent = null;
			}
		}
		
		
	}
	
}