/*
----------------------
Drag Arounder Class
----------------------
Set height to FALSE
if your elements are
different heights.
----------------------
*/

var DragAround = Class.create({
	initialize:	function(id,els,child,height)
					{
						this.ff = new Element('input',{type: 'hidden',name: id});
						this.values = new Array();
						this.curParent = -1;
						this.origParent = -1;
						elsa = els.split(" ");
						this.els = new Array();
						for(var i=0;i<elsa.length;i++) {
							this.els[i] = $(elsa[i]);
							if(this.els[i].getStyle('position') != "absolute"
								&& this.els[i].getStyle('position') != "relative") {
								debug("DragAround: Parent element not absolute or relative");
								return;
							}							
							var ch = this.els[i].childElements();
							//if(ch.length == 0) {
							//	return;
							//}
							this.height = height;
							if(height !== false && !height) {
								this.height = ch[0].getHeight();
							} else if(height === false) {
								this.height = false;
							}
							this.values[i] = new Array();
							for(c=0;c<ch.length;c++) {
								if(ch[c].getStyle('position') != "relative") {
									debug("DragOrder: Child element not relative");
									continue;
								}
								this.values[i][c] = ch[c].identify();
								// Okay, let's add the events
								ch[c].makeDraggable(this,child);
							}
						}
						this.btm = false;
						this.els[0].insert({bottom: this.ff});
					},

	getOrder:	function()
					{
						return this.values;
					},

	setOrder:	function(arr)
					{
						for(i=0;i<arr.length;i++) {
							arr[i].reverse();
							for(j=0;j<arr[i].length;j++) {
								this.els[i].insert({top: $(arr[i][j])});
							}
						}
						this.values.clear();
						var arry = new Array();
						for(i=0;i<this.els.length;i++) {
							this.values[i] = new Array();
							arry = this.els[i].childElements();
							for(j=0;j<arry.length;j++) {
								this.values[i][j] = arry[j].identify();
							}
						}
					},

	updateField:	function()
					{
						a = new Array();
						for(i=0;i<this.values.length;i++) {
							a[i] = this.values[i].join();
						}
						this.ff.value = a.join(':');
					},

	startCond:	function(el)
					{
						// We need to know what the original parent is
						this.origParent = el.parentNode;
						this.origParent.setStyle({zIndex:2});
						// Let's create an element where this element is
						el.insert({after: new Element('div',{id: 'dragMover'}).setStyle({width: (intval(el.getWidth())-4)+'px',
																		height: (intval(el.getHeight())-4)+'px',
																		display: 'block',
																		zIndex: 1
																		}
																	)});
						el.setStyle({position: 'absolute',
										top: this.getPrevHeights(el)+'px'});
						return true;
					},

	getPrevHeights:	function(el)
					{
						var ret = 0;
						while((el = el.previous()) != undefined) {
							ret += el.getHeight();
						}
						return ret;
					},

	complexMove:	function(el,x,y)
					{
						var t = this.els[this.curParent].childElements(), i = 0, u, dm = false;
						if(t.length == 0) {
							this.els[this.curParent].insert({top: $('dragMover')});
							return true;
						}
						var j;
						if(this.btm) {
							i = this.els[this.curParent].getHeight();
							for(j=t.length-1;j>=0;j--) {
								if(t[j] == el) continue;
								if(y > (i-t[j].getHeight())) {
									u = t[j];
									dm = true;
									break;
								} else if(y > (i-(t[j].getHeight()/2))) {
									u = t[j-1];
									break;
								}
								i -= t[j].getHeight();
							}
						} else {
							for(j=0;j<t.length;j++) {
								if(t[j] == el) continue;
								if(y < (i+(t[j].getHeight()/2))) {
									u = t[j];
									break;
								} else if(y < (i+t[j].getHeight())) {
									u = t[j+1];
									dm = true;
									break;
								}
								i += t[j].getHeight();
							}
						}
						this.btm = false;
						if(j > (t.length/2)) {
							this.btm = true;
						}
						if(u != undefined) {
							if(dm) {
								u.insert({after: $('dragMover')});
							} else {
								u.insert({before: $('dragMover')});
							}
						} else {
							this.els[this.curParent].insert({bottom: $('dragMover')});
						}
						
						return true;
					},
					
	simpleMove:		function(el,x,y)
					{
						var t = this.els[this.curParent].childElements();
						if(t.length == 0) {
							this.els[this.curParent].insert({top: $('dragMover')});
							return true;
						}
						var m = y % this.height;
						var i = (y - m) / this.height;
						var u;
						var dm = false;
						if(m < (this.height / 2)) {
							u = t[i];
							if(i == 0) dm = true;
						} else {
							u = t[i+1];
						}
						if(u != undefined) {
							if(!dm) {
								u.insert({after: $('dragMover')});
							} else {
								u.insert({before: $('dragMover')});
							}
						} else {
							this.els[this.curParent].insert({bottom: $('dragMover')});
						}
						return true;
					},

	findNearestParent: function(x,y)
				{
					// Because for this project, we know this is columns
					// We're going to cheat with y values.
					var px = 0;
					var py = 0;
					var px2 = 0, py2 = 0;
					var pos = new Array();
					var dims = new Array();
					var cx = 0, cy = 0, cx2 = 0, cy2 = 0;
					var dist = 10000, dist2 = 10000;
					var dista = 0, distb = 0;
					var par = -1, par2 = -1;
					var dbg = x+','+y+'<br>';
					for(var i=0;i<this.els.length;i++) {
						if(this.els[i]) {
							pos = this.els[i].getPosition();
							px = pos[0];
							py = pos[1];
							dims = this.els[i].getDimensions();
							px2 = px + dims.width;
							dista = Math.min(Math.sqrt(Math.pow(px2-x,2)),Math.sqrt(Math.pow(py2-x)));
							dbg += '<br>'+i+'-'+dista;
							if(px < x && px2 > x) {
								this.curParent = i;
								return [px,py];
							} else if(dista < dist) {
								cx = px;
								cy = py;
								dist = dista;
								par = i;
							}
						}
					}
					//debug(dbg);
					if(par < 0) par = 1;
					this.curParent = par;
					return [cx,cy];
				},

	moveCond:	function(el,x,y)
				{
					var pos = this.origParent.getPosition();
					var px = pos[0];
					var py = pos[1];
					var dims = el.getDimensions();
					var a = this.findNearestParent(x+px+(dims.width/2),y+py+(dims.height/2));
					x += (px - a[0]);
					y += (py - a[1]);
					if(this.height !== false) {
						return this.simpleMove(el,x,y);
					}
					return this.complexMove(el,x,y);
				},

	stopCond:	function (el,x,y)
				{
					this.findNearestParent(x,y);
					el.setStyle({position: 'relative',left: '0px',top: '0px'});
					$('dragMover').insert({before: el});
					$('dragMover').remove();
					this.origParent.setStyle({zIndex:1});
					this.values.clear();
					var arr = new Array();
					for(i=0;i<this.els.length;i++) {
						this.values[i] = new Array();
						arr = this.els[i].childElements();
						for(j=0;j<arr.length;j++) {
							this.values[i][j] = arr[j].identify();
						}
					}
					this.updateField();
					this.btm = false;
					return true;
				}
});

var PositionExtra = {
	getPosition:	function(el,all)
					{
						var curleft = curtop = 0;
						var last = null;
						do {
							if(last == el || el.tagName == 'HTML') break;
							if(!el.tagName) break;
							pos = el.getStyle('position');
							if(!all && last != null && (pos == 'absolute' ||
							pos == 'relative')) break;
							last = el;
							curleft += el.offsetLeft;
							curtop += el.offsetTop;
						} while(el = el.getOffsetParent());
						return [curleft,curtop];
					}
	};
Element.addMethods(PositionExtra);