function MultiColumnSettings() {
}

function MultiColumn(columnContainerIn,settingsIn) {
	//IE6 doesn't support HTMLElement prototyping. IE7 probably won't too. Let's aim for IE8! *sigh*	
	//But thank you, www.quirksmode.org!
	/*
	this.getStyle= function (element,stylePropW3,stylePropIE) {
		var y = null;
		if (element.currentStyle)
			y = element.currentStyle[stylePropIE];
		else if (window.getComputedStyle && document.defaultView.getComputedStyle(element,null)) {
			y = document.defaultView.getComputedStyle(element,null).getPropertyValue(stylePropW3);
		}
		return y;
	}
	*/
		
	this.generateColumns= function () {
		var i=0;
		var numColumns;
		
		//Obtain the base column. This column contains the original text.
		var baseColumn=this.columnContainer.getElementsByTagName('div').item(0);
		
		//Add a node with style: "clear: both;" to stretch the container-node.
		var clearingNode=document.createElement('span');
		clearingNode.style.display="block";
		clearingNode.style.clear="both";
		clearingNode.style.zoom="1"; //yet another work-around for a certain obsolete browser.
		this.columnContainer.appendChild(clearingNode);
		
		//Get the number of columns defined
		numColumns=this.settings.numberOfColumns;
		
		//Add new columns
		for (i=1;i<numColumns;i++) {
			this.columnContainer.insertBefore(baseColumn.cloneNode(false),this.columnContainer.firstChild);
		}
		
		//Get all columns in the container
		var columns=this.columnContainer.getElementsByTagName('div');

		//Cut/paste blocks from the baseColumn to the new columns.
		for (i=0;i<columns.length;i++) {
			var currentColumn=columns.item(i);
			//currentColumn.style.width=availableWidth+'px';
			currentColumn.style.width=this.settings.colWidths[i]+'px';
			
			//Cut/paste blocks from the baseColumn to the current column, while the
			//current column has not reach the defined height
			if (i<columns.length-1) {
				while (currentColumn.offsetHeight<=this.settings.colHeights[i] && baseColumn.hasChildNodes()) {
					if (baseColumn.firstChild.nodeType==1) { //Node.ELEMENT_NODE Doesn't work in ^%@$#@$!!! IE6
						currentColumn.appendChild(baseColumn.firstChild);
					} else {
						baseColumn.removeChild(baseColumn.firstChild);
					}
				}
			}
			
			//Some elements can be split and wrapped to the next column
			
			if (currentColumn.hasChildNodes()) {
				var lastChild=currentColumn.lastChild;
				var nextColumn=columns.item(i+1);
				switch (lastChild.nodeName.toLowerCase()) {
					case 'p': 
						new ParapgraphWrapper(currentColumn,lastChild,nextColumn,this.settings.colHeights[i]);
						break;
					case 'ul':
					case 'ol':
						new ListWrapper(currentColumn,lastChild,nextColumn,this.settings.colHeights[i]);					
						break;
					default:
						//don't know what to do with this element. Let it stick out.
				}
			}
			//Move headings at the bottom to next column. (this implies a proper usage of headings!)
			new HeadingWrapper(currentColumn,nextColumn);
			
			if (this.settings.colColors!=undefined) {
				currentColumn.style.color=this.settings.colColors[i];
			}
			currentColumn.style.height=this.settings.colHeights[i]+'px';
			currentColumn.style.left=this.settings.colXposs[i]+'px';
			currentColumn.style.top=this.settings.colYposs[i]+'px';
			currentColumn.id=this.columnContainer.id+'-column'+i;
			//currentColumn.style.backgroundColor='#996600';
			
			$$('p:empty').dispose();
		}
		
		numgencols=columns.length;
		for (i=0;i<numgencols;i++) {
			var currentColumn=this.columnContainer.getElementById(this.columnContainer.id+'-column'+i);
			// Hide unused columns in the end
			if (currentColumn.hasChildNodes() && currentColumn.childNodes.length==1 && currentColumn.lastChild.textContent=='') {
				currentColumn.parentNode.removeChild(currentColumn);
				//currentColumn.style.display='none';
			} else if (currentColumn.hasChildNodes()) {
				
			} else {
				currentColumn.parentNode.removeChild(currentColumn);
				//currentColumn.style.display='none';
			}
		}
	}
	
	//Initialisation starts here
	this.settings=settingsIn;
	
	this.columnContainer=columnContainerIn;
	this.columnContainer.style.display='block';
	if (this.settings.eventtext) {
		this.columnContainer.style.position='relative';
	} else {
		this.columnContainer.style.position='absolute';
		this.columnContainer.style.top='0';
		if (this.settings.artcols) { this.columnContainer.style.left='0'; }
		this.columnContainer.style.zIndex='10';
	}
	this.columnContainer.getElementsByTagName('div').item(0).style.position='absolute';
	
	//And do the magic!
	this.generateColumns();
	
}








function ParapgraphWrapper(sourceColumnIn, sourceParagraphIn, destinationColumnIn, heightIn) {
	this.sourceColumn=sourceColumnIn;
	this.height=heightIn;
	
	/**
	* Recursively loops over given <source>, moving text from <source> to <dest>
	* until the column height is less or equal to the target height.
	*
	* Preconditions: <source> and <dest> are element nodes.
	*/
	this.processElement=function (source,dest) {
		var lastSourceChild;
		source.style.marginBottom = '0';
		
		while (lastSourceChild=source.lastChild) {
			if (lastSourceChild.nodeType==1) { //element node
				//Make an empty clone of the element we're breaking (with attributes but with no content) to the destination node.
				var newDest=lastSourceChild.cloneNode(false);
				if (dest) {
					dest.insertBefore(newDest,dest.firstChild);
				}
				//recursively process this node.
				if (this.processElement(lastSourceChild,newDest)) {
					return true;
				}							
			} else if (lastSourceChild.nodeType==3) { //text node
				//Wrap this text node..
				if (this.wrapTextNode(lastSourceChild,dest)) {
					//..and return when the target has been reached.
					return true;
				}
			}
			
			//This node has been cleaned out. Remove it.
			source.removeChild(lastSourceChild);
		} 
				
		return false;
	}
	
	/**
	* Cuts words at the end of <source>, until the column height
	* is less or equal to target-height.
	* Cut words are then placed into <dest>
	*
	* Preconditions: <source> is a text node. <dest> is an element node.
	*/
	this.wrapTextNode=function (source,dest) {	
		var sourceText=source.nodeValue;
		
		//Split the text at spaces.
		var sourceTextAray=sourceText.split(/\s/);
		var destTextArray=new Array();
		
		//Keep removing words form the source until the column fits.
		while (this.sourceColumn.offsetHeight>this.height && sourceTextAray.length>0) {
			//destText is 'pushed' with a letter that is 'popped' from sourceText
			destTextArray.push(sourceTextAray.pop());
			//update source to get new length (that might now fit)
			source.nodeValue=sourceTextAray.join(' ');
		}
		//source.nodeValue=sourceTextAray.join(' ')+'\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0';
		
		//Add spaces at the front and end, if there are spaces in the original. ????
		//var newText=(/^\s/.test(sourceText)?' ':'') + (destTextArray.reverse().join(' ')) + (/\s$/.test(sourceText)?' ':'');
		var newText = destTextArray.reverse().join(' ');
		
		//Put the text into the destination node in the next column.
		if (dest) {
			dest.insertBefore(document.createTextNode(newText),dest.firstChild);
		}
		
		//return true if the target has been reached.
		return this.sourceColumn.offsetHeight<=this.height;
	}



	//Duplicate the current paragraph by shallow copy
	if (destinationColumnIn) {
		if (sourceParagraphIn.getAttribute('class')=='nocolumnbreak') {
			destinationColumnIn.insertBefore(sourceParagraphIn.cloneNode(true),destinationColumnIn.firstChild);
			this.sourceColumn.removeChild(sourceParagraphIn);
		} else {
			destinationColumnIn.insertBefore(sourceParagraphIn.cloneNode(false),destinationColumnIn.firstChild);
			this.processElement(sourceParagraphIn,destinationColumnIn.firstChild);
			//check if the origal paragraph is emtpy
			if (sourceParagraphIn.offsetHeight==0) { //Check to see if normalized text is "" would be better..
				//Yes it's empty. Remove the empty paragraph.
				this.sourceColumn.removeChild(sourceParagraphIn);		
			}
		}
	}
}



function ListWrapper(sourceColumnIn, sourceListIn, destinationColumnIn, heightIn) {
	//Duplicate the current paragraph by shallow copy
	var newList=sourceListIn.cloneNode(false);
	
	destinationColumnIn.insertBefore(newList,destinationColumnIn.firstChild);
		
	//Loop over all elements in this list.
	while (currentElement=sourceListIn.lastChild) {
		if (sourceColumnIn.offsetHeight<=heightIn) {
			break;
		}
		
		if (currentElement.nodeName.toLowerCase()=='li') {
			newList.insertBefore(currentElement,newList.firstChild);			
		} else {		
			//remove the last element.
			sourceListIn.removeChild(currentElement);
		}
	}
		
	//Count current number of items.
	var numItems=1;
	var elementList=sourceListIn.childNodes;
	//count remaining items.
	for (var i=0;i<elementList.length;i++) {
		if (elementList[i].nodeName.toLowerCase()=='li') {
			numItems++;
		}
	}
	
	newList.start=numItems;
	
	//check if the origal list is emtpy
	if (sourceListIn.offsetHeight==0) { //Check to see if normalized text is "" would be better..
		//Yes it's empty. Remove the empty list.
		sourceColumnIn.removeChild(sourceListIn);		
	}
}

function HeadingWrapper(currentColumn,nextColumn) {
	//Wrap a heading, if there was one.
	if (currentColumn.hasChildNodes()) {
		if (/^h[1-6]$/i.test(currentColumn.lastChild.nodeName)) {			
			nextColumn.insertBefore(currentColumn.lastChild,nextColumn.firstChild);	
		}
	}
}