var MooColumns = new Class({
	
	Implements:Options,
	
	options: {
		
		selector: ".multiColumn",
		className: "multiColumn",
		numOfColumns: 2,
		defaultNumOfColumns: 2,
		gutterWidth: 5,
		gutterClassName: "gutter",
		columnClassName: "column",
		tweak: {
			x: 0,
			y: 0,
			width: 0
		},
		splittableElements: [
			"p",
			"div",
			"span",
			"ul"
		],
		morePrecise: true,
		tolerance: 10,
		colBreaksTrump: true,
		debug:false
	},
	
	sizerElWrapper: null,
	
	columnParents: [],
	
	mooColumnsAreasArr: [],
	
	initialize: function(A){
		
		this.setOptions(A);
		if($type(parseFloat(this.options.numOfColumns))!="number"){
			this.options.numOfColumns = this.options.defaultNumOfColumns
		}
		this.sizerElWrapper = new Element("div",{
			id:"sizerElWrapper"
		}).inject(document.body, "inside").setStyles({
			visibility: "hidden",
			position: "absolute",
			display: "block",
			padding: 0,
			margin: 0,
			top: 0,
			left: 0,
			width: 0,
			height: 0,
			overflow: "hidden"
		});
		this.columnParents = $(document.body).getElements(this.options.selector);
		this.columnParents.each(function(D,B){
			var E = this.getOrSetId($(D));
			var C = new MooColumnsArea(this.options,D);
			this.mooColumnsAreasArr[E] = C;
			D.className += "-screen";
		}.bind(this))
	},
	
	getOrSetId: function(C){
		if(!C.id){
			var D = new Date();
			var B = D.getMilliseconds().toString();
			var A = Math.floor(Math.random()*1000);
			if(C.nodeName){
				C.id = C.nodeName.toString() + "-" + B + A.toString()
			}else{
				C.id = "element" + B + A.toString()
			}
		}
		return C.id
	}
});

var MooColumnsArea = new Class({

	Implements: Options,
	
	options: {
		parentEl:null,
		printEl:null,
		debug:null,
		colBreakDepth:5
	},
	
	columnElsArr:[],
	
	gutterElsArr:[],
	
	colWidth:null,
	
	targetHeight:null,
	
	tempContentHolder:null,
	
	sizerEl:null,
	
	tallest:0,
	
	unsplittableTags: [
		"td",
		"tr",
		"table",
		"tbody"
	],
	
	hasColBreaks: false,
	
	initialize: function(B,E){
		this.setOptions(B);
		this.options.parentEl = E;
		this.sizerEl = new Element("div").inject($("sizerElWrapper"),"inside").setStyles({
			visibility: "hidden",
			position: "absolute",
			display: "block",
			padding: 0,
			margin: 0,
			top: 0,
			left: 0
		});
		this.options.printEl = new Element("div",{
			"class":this.options.className + "-print"
		}).inject(this.options.parentEl,"after").set("html",this.options.parentEl.innerHTML);
		this.options.parentEl.empty();
		var D = new Element("div").setStyles({
			display: "block",
			position: "relative",
			padding: 0,
			margin: 0
		}).inject(this.options.parentEl, "top");
		this.options.parentEl = E.getFirst();
		var C = D.getStyle("width").toInt() + this.options.tweak.width.toInt();
		var A = (100 * C) / D.getStyle('width').toInt();
		if(!Browser.Engine.trident){
			D.setStyles({
				width: A + "%",
				left: this.options.tweak.x
			});		
		}
		this.go();
		
		window.addEvent("resize", function(){
			$clear(F);
			var F = (function(){this.setHeights()}.bind(this)).delay(100);
		}.bind(this));
	},
	
	go: function(){
		var A = this.options.numOfColumns-1;
		if(this.options.gutterWidth.toString().contains("px")){
			this.options.gutterWidth = Math.round((100 * parseFloat(this.options.gutterWidth)) / this.options.parentEl.getCoordinates().width)
		}
		var B = Math.round(A * parseFloat(this.options.gutterWidth) / this.options.numOfColumns);
		this.colWidth = Math.round(100 / this.options.numOfColumns) - B;
		var C = Math.round((this.options.parentEl.getCoordinates().width * this.colWidth) / 100);
		this.sizerEl.setStyle("width", C).set("html", this.options.printEl.innerHTML);
		this.targetHeight = Math.round(this.sizerEl.getCoordinates().height / this.options.numOfColumns);
		this.makeWireFrame();
		this.options.printEl.set("html", this.options.printEl.get("html").stripScripts().split(/<!--[^(-->)]*-->/).join(""));
		this.wrapTextNodes(this.options.printEl);
		this.convertColBreaks(this.options.printEl);
		if($(this.options.printEl).getElements(".colBreak").length > 0){
			this.hasColBreaks = true;
		}
		while(this.options.colBreakDepth>0){
			this.splitColBreakParents(this.options.printEl);
			this.options.colBreakDepth--;
		}
		if(this.options.colBreaksTrump === true && this.hasColBreaks){
			this.options.morePrecise = false;
		}
		var D;
		if(this.hasColBreaks && this.options.colBreaksTrump){
			D = this.divideContent2();
		}else{
			D = this.divideContent();
		}
		for(i = 0; i < D.length; i++){
			this.columnElsArr[i].set("html", D[i].innerHTML)
		}
		if(this.options.morePrecise){
			this.shaveColumns()
		}
		this.columnsContentArr = D;
		this.setHeights()
	},
	
	setHeights: function(){
		this.options.parentEl.setStyles({
			overflow: "hidden",
			height: "0"
		});
		this.tallest = 0;
		if(!this.options.debug){
			for(i = 0; i < this.columnsContentArr.length; i++){
				if(this.columnElsArr[i].getCoordinates().height > this.tallest){
					this.tallest = this.columnElsArr[i].getCoordinates().height
				}
			}
			if(this.options.parentEl.getScrollSize().y > 0){
				this.tallest = this.options.parentEl.getScrollSize().y
			}
			for(i = 0; i < this.columnElsArr.length; i++){
				this.columnElsArr[i].setStyles({
					top: 0,
					bottom: 0
				});
				this.options.parentEl.setStyle("height", this.tallest)
			}
			if(Browser.Engine.trident){
				this.options.parentEl.getParent().setStyle("height", this.tallest);
				this.gutterElsArr.each(function(B, A){
					B.setStyle("height", "100%")
				})
			}
		}
	},
	
	makeWireFrame: function(){
		this.options.parentEl.empty();
		for(i = 0; i < this.options.numOfColumns; i++){
			colLeft = (i*(parseFloat(this.colWidth)+parseFloat(this.options.gutterWidth)));
			this.columnElsArr[i] = new Element("div",{
				"class": "column"
			}).inject(this.options.parentEl,"inside").setStyles({
				display: "block",
				position: "absolute",
				left: colLeft + "%",
				top: this.options.tweak.y,
				width: this.colWidth + "%"
			});
			if(i < this.options.numOfColumns - 1){
				this.gutterElsArr[i] = new Element("div",{
					"class": "gutter"
				}).inject(this.options.parentEl,"inside").setStyles({
					display:"block",
					position:"absolute",
					left: (colLeft + parseFloat(this.colWidth) + "%"),
					top: this.options.tweak.y, width: parseFloat(this.options.gutterWidth) + "%",
					bottom: 0
				});
				if(this.options.debug){
					this.gutterElsArr[i].setStyle("background", "yellow")
				}
			}
			if(this.options.debug){
				this.columnElsArr[i].setStyle("background", "#eee")
			}
		}
		if(this.options.debug){
			this.options.parentEl.setStyle("background", "#ccc")
		}
	},
	
	convertColBreaks: function(H){
		var B = $(H).getElements("hr");
		for(var A = 0; A < B.length; A++){
			var I = $(B[A]);
			var G = I.getNext() && I.getNext().get("tag") === "hr";
			var F = I.getNext() && I.getNext().get("tag") === "br" && I.getNext().getNext() && I.getNext().getNext().get("tag") === "hr";
			var E = I.getNext() && I.getNext().get("tag") === "p" && !I.getNext().get("html") && I.getNext().getNext() && I.getNext().getNext().get("tag") === "hr";
			var D = I.getNext() && I.getNext().getNext() && I.getNext().getNext().getNext() && I.getNext().get("tag") === "p" && I.getNext().getNext().get("tag") === "p" && I.getNext().getNext().getNext().get("tag") === "hr" && !I.getNext().get("html") && !I.getNext().getNext().get("html");
			if(D || E || F || G){
				var C = new Element("span",{
					"class":"colBreak"
				}).inject(I,"before");
				this.hasColBreaks = true
			}
			if(D){
				I.getNext().getNext().getNext().dispose()
			}
			if(D || E || F){
				I.getNext().getNext().dispose()
			}
			if(D || E || F || G){
				I.getNext().dispose();I.dispose()
			}
		}
	},
	
	splitColBreakParents: function(A){
		$(A).getElements(".colBreak").each(function(G,C){
			if(!G.getParent()){
				return;
			}
			if(!G.getParent().hasClass("wrapper-print") && !this.unsplittableTags.contains(G.getParent().get("tag"))){
				var E = G.getParent();
				var H = E.clone(false);
				if(!H || H.hasClass("colBreak")){
					return;
				}
				var I = $(E).childNodes;
				var D = I[0];
				var B = 1;
				while(D && !D.className || D && D.className != "colBreak"){
					if(D.parentNode.className && D.parentNode.className.contains("multi")){
						return;
					}
					if($type(D) === "textnode" || $type(D) === "whitespace"){
						if(H && H.innerHTML && D.nodeValue){
							H.set("html", H.get("html") + D.nodeValue);
							D.parentNode.removeChild(D)
						}else{
							break;
						}
					}else{
						D.inject(H,"bottom")
					}
					B++;
					D = I[B];
				}
				var F = E.clone(true, true).inject(E, "after");
				$(H).replaces($(E));
				if(F.getElements(".colBreak").length >= 1){
					$(F.getElements(".colBreak")[0]).inject(H, "after")
				}
			}
		}.bind(this))
	},
	
	wrapTextNodes: function(A){
		var C = $(A).childNodes;
		for(i = 0; i < C.length; i++){
			if($type(C[i]) === "textnode"){
				var B = new Element("p").inject(C[i], "after").set("html", C[i].nodeValue);
				C[i].parentNode.removeChild(C[i]);
			}
		}
	},
	
	divideContent: function(){
		this.tempContentHolder = new Element("div", {
			id: "tempContentHolder"
		}).set("html", this.options.printEl.innerHTML).inject(document.body, "inside").setStyles({
			display: "none",
			position: "absolute"
		});
		this.sizerEl.empty();
		var C = [];
		var A = 0;
		var B = 1300;
		while(this.sizerEl.getCoordinates().height <= this.targetHeight && $(this.tempContentHolder).getFirst() && B > 0){
			B--;
			if(!C[A]){
				C[A] = new Element("div")
			}
			$(this.tempContentHolder).getFirst().inject(this.sizerEl, "inside");
			if(this.sizerEl.getCoordinates().height >= this.targetHeight || this.sizerEl.getLast().hasClass("colBreak")){
				$(C[A]).set("html", this.sizerEl.innerHTML);
				this.sizerEl.empty();
				A++;
				if(A >= this.options.numOfColumns){
					A = this.options.numOfColumns - 1
				}
				if(!C[A]){
					C[A] = new Element("div")
				}
				if(!this.tempContentHolder.getFirst()){
					$(C[A]).set("html", this.tempContentHolder.innerHTML + $(C[A]).innerHTML);
				}
			}
		}
		$(C[A]).set("html", $(C[A]).innerHTML + this.sizerEl.innerHTML);
		this.sizerEl.empty();
		return C;
	},
	
	divideContent2: function(){
		this.tempContentHolder = new Element("div",{
			id: "tempContentHolder"
		}).set("html", this.options.printEl.innerHTML).inject(document.body, "inside").setStyles({
			display: "none",
			position: "absolute"
		});
		this.sizerEl.empty();
		var C = [];
		var A = 0;
		var B = 1300;
		while(A < this.options.numOfColumns && B > 0){
			B--;
			if(!C[A]){
				C[A] = new Element("div")
			}
			if(this.tempContentHolder.getFirst()){
				$(this.tempContentHolder).getFirst().inject(this.sizerEl, "inside")
			}
			if(this.sizerEl.getLast().hasClass("colBreak")){
				$(C[A]).set("html", this.sizerEl.innerHTML);
				this.sizerEl.empty();
				A++;
				if(A >= this.options.numOfColumns){
					A = this.options.numOfColumns -1
				}
				if(!C[A]){
					C[A] = new Element("div")
				}
				if(!this.tempContentHolder.getFirst()){
					$(C[A]).set("html", this.tempContentHolder.innerHTML + $(C[A]).innerHTML);
				}
			}
		}
		$(C[A]).set("html" ,$(C[A]).innerHTML + this.sizerEl.innerHTML);
		this.sizerEl.empty();
		return C;
	},
	
	shaveColumns: function(){
		for(i = 0; i < this.columnElsArr.length - 1; i++){
			var C = this.columnElsArr[i].getCoordinates().height - this.targetHeight;
			var F = this.columnElsArr[i].getLast().get("tag") && this.options.splittableElements.contains(this.columnElsArr[i].getLast().get("tag"));
			var G = this.columnElsArr[i].getLast();
			if(C > 0 && F){
				var B = G.getCoordinates().height - C + this.options.tolerance;
				var H = G.clone().inject($("sizerElWrapper"), "inside");
				H.empty();
				var A = 50;
				while(A > 0 && G.childNodes.length && G.getCoordinates().height > B){
					A--;
					if($type(G.childNodes[G.childNodes.length - 1]) === "textnode" || $type(G.childNodes[G.childNodes.length - 1]) === "whitespace"){
						var D = 50;
						var E = G.childNodes[G.childNodes.length - 1].nodeValue.split(" ");
						while(D > 0 && G.childNodes[G.childNodes.length - 1].nodeValue.length >= 0 && G.getCoordinates().height > B){
							D--;
							if($defined(E.getLast())){
								H.innerHTML = E.getLast().toString() + " " + H.innerHTML
							}
							E = E.filter(function(J, I){
								return I < (E.length - 1) && $defined(J);
							});
							G.childNodes[G.childNodes.length - 1].nodeValue = E.join(" ")
						}
						if(!$defined(E.getLast())){
							G.removeChild(G.childNodes[G.childNodes.length - 1])
						}
					}else{
						if($(G.childNodes[G.childNodes.length - 1])){
							if($(G.childNodes[G.childNodes.length - 1]).hasClass("colBreak")){
								A = 0;
							}else{
								$(G.childNodes[G.childNodes.length - 1]).inject(H, "top");
							}
						}
					}
				}
				H.inject(this.columnElsArr[i + 1], "top");
			}else{
				if(C > this.options.tolerance && !F){
					G.inject(this.columnElsArr[i + 1], "top");
				}
			}
		}
	}
});