var Boxes = {
	
	stack : null,
	boxes : new Array(),
	locked : false,
	activeBox : false,
	
	build : function(amount)
	{
		this.stack = 100;
		
		var doc = document.viewport.getDimensions();
		for (i=0; i<amount; i++) {
			var xpos = (doc.width / 2) - 35;
			var ypos = (doc.height / 2) - 35;
			var box = new Box(xpos, ypos);
		}
		var bb = new Element('div', {'class':'boundingbox'});
		bb.setStyle({
			position : 'absolute',
			left : (doc.width / 2) - 200 + 'px',
			top : (doc.height / 2) - 150 + 'px',
			width : '400px',
			height : '300px'
		});
		document.body.appendChild(bb);
		this.scatter();
		
	},
	register : function(boxObject)
	{
		this.boxes[boxObject.getDepth()] = boxObject;
	},
	scatter : function()
	{
		var doc = document.viewport.getDimensions();
		this.boxes.each(function(b) {
			var dimensions = b.getDimensions();
			var xpos = (doc.width / 2) - 200 + (Math.random() * (400-dimensions.width));
			var ypos = (doc.height / 2) - 150 + (Math.random() * (300-dimensions.height));
			b.moveTo(xpos, ypos);
		});
	},
	avoid : function(box, dim)
	{
		this.get().each(function(b) {
			if (b == box) return;
			
			var position = b.getPosition();
			var dimensions = b.getDimensions();
			if (dim.left <= position.left) {
				var newX = position.left - dim.left - dim.width + dim.x2;
			} else {
				var newX = dim.x1 - (dim.left - position.left - dimensions.width);
			}
			if (dim.top <= position.top) {
				var newY = position.top - dim.top - dim.height + dim.y2;
			} else {
				var newY = dim.y1 - (dim.top - position.top - dimensions.height);
			}
			b.moveTo(newX, newY);
		});
	},
	revert : function(box)
	{
		this.get().each(function(b) {
			if (b == box) return;
			
			b.revertPosition();
		});
	},
	get : function()
	{
		return this.boxes;
	},
	lock : function(activeBox)
	{
		this.locked = true;
		this.activeBox = activeBox;
	},
	unlock : function()
	{
		this.locked = false;
		this.activeBox = false;
	},
	getLock : function()
	{
		return this.activeBox;
	}
};

var Box = Class.create();

Box.prototype = {
	initialize : function(xpos, ypos)
	{
		this.z = Boxes.stack;
		Boxes.stack++;
		this.create(xpos, ypos);
	},
	create : function()
	{
		this.boxId = 'box'+this.z;
		if (!$(this.boxId)) {
			var b = new Element('div', {'id':this.boxId, 'class':'box'}).update(this.z);
			b.setStyle({
				position : 'absolute',
				background : 'rgb(' + (10+Math.round(Math.random()*230)) +',200,'+ (10+Math.round(Math.random()*230))+')',
				zIndex : this.z,
				cursor : 'pointer',
				width : '70px',
				height : '70px'
			});
			document.body.appendChild(b);
		}
		this.box = $(this.boxId);
		this.box.setOpacity(0.7);
		//this.box.observe('click', Boxes.scatter.bindAsEventListener(Boxes));
		this.box.observe('click', this.onMouseClick.bindAsEventListener(this));
		this.box.observe('mouseover', this.onMouseOver.bindAsEventListener(this));
		this.box.observe('mouseout', this.onMouseOut.bindAsEventListener(this));
		if (arguments[0] && arguments[1]) {
			this.position(arguments[0], arguments[1]);
		}
		Boxes.register(this);
		this.box.show();
	},
	getDepth : function()
	{
		return this.z;
	},
	position : function(x, y)
	{
		this.box.setStyle({
			left : x+'px',
			top : y+'px'
		});
	},
	moveTo : function(xpos, ypos)
	{
		this.oldPosition = this.getPosition();
		new Effect.Move(this.box, {
			x: xpos,
			y: ypos,
			duration : 0.5,
			mode: 'absolute'
		});
	},
	revertPosition : function()
	{
		new Effect.Move(this.box, {
			x: this.oldPosition.left,
			y: this.oldPosition.top,
			duration : 0.5,
			mode: 'absolute'
		});
	},
	getDimensions : function()
	{
		return this.box.getDimensions();
	},
	getPosition : function()
	{
		return this.box.cumulativeOffset();
	},
	onMouseOver : function()
	{
		this.box.style.zIndex = Boxes.get().last().getDepth()+1;
		this.box.setOpacity(1);
	},
	onMouseOut : function()
	{
		this.box.setOpacity(0.7);
		this.box.style.zIndex = this.getDepth();
	},
	onMouseClick : function()
	{
		if (this.expanded) {
			this.shrink();
		} else{
			this.expand();
		}

	},
	expand : function(oncomplete)
	{
		if (this.expanded) return;
		
		if (Boxes.locked) {
			Boxes.getLock().shrink(this.expand.bind(this));
			return;
		}
		
		var position = this.box.cumulativeOffset();
		var dimensions = this.box.getDimensions();
		this.oldStyle = {
			top: position.top,
			left: position.left,
			height: this.box.style.height,
			width: this.box.style.width
		};
		var width = 400;
		var height = 300;
		var avoidDimensions = {
			x1:(position.left - (width/2)),
			x2:(position.left + (width/2)),
			y1:(position.top - (height/2)),
			y2:(position.top + (height/2)),
			left:position.left,
			top:position.top,
			width:dimensions.width,
			height:dimensions.height
		};
		new Effect.Parallel([
			new Effect.Morph(this.box, {
				style : {
					width : width+'px',
					height : height+'px'
				},
				sync : true
			}),
			new Effect.Move(this.box, {
				x : (position.left - (width/2)),
				y : (position.top - (height/2)),
				mode : 'absolute',
				sync: true
			})
		], {
			duration : 0.5,
			afterFinish : oncomplete || Prototype.emptyFunction
		});
		Boxes.avoid(this, avoidDimensions);
		this.expanded = true;
		Boxes.lock(this);
	},
	shrink : function(oncomplete)
	{

		new Effect.Parallel([
			new Effect.Morph(this.box, {
				style : {
					width : this.oldStyle.width,
					height : this.oldStyle.height
				},
				sync : true
			}),
			new Effect.Move(this.box, {
				x : this.oldStyle.left,
				y : this.oldStyle.top,
				mode : 'absolute',
				sync: true
			})
		], {
			duration : 0.5,
			afterFinish : oncomplete || Prototype.emptyFunction
		});
		Boxes.revert(this);
		this.expanded = false;
		Boxes.unlock();
	}
};
