/*
requires prototype 1.6 above

Sorting Methods:
	sortReverse - textual sort in reverse
	sortByNumber - tries to parse text to integer and sorts numerically
	sortByNumberReverse - tries to parse text to integer and sorts numerically in reverse

Usage:
var alcassoftSorter = new AlcassoftSorter();
alcassoftSorter.init({
	targetElementId:'sortable3'
});

//alcassoftSorter.sort(); //sorts 1 level
alcassoftSorter.sortAll(); //sorts recursively
alcassoftSorter.sortAll(alcassoftSorter.sortReverse); //sorts recursively

Sorts a elements First Child elements textually
BEFORE:
<ul id="sortable">
	<li>Giraffe</li>
	<li>Cat</li>
	<li>Aardvark</li>
</ul>
AFTER:
<ul id="sortable">
	<li>Aardvark</li>
	<li>Cat</li>
	<li>Giraffe</li>
</ul>

*/

//constructor
AlcassoftSorter=function(){
	//global properties
	this.targetElementId;
	this.targetElement;
	this.childElements;
	//a array that stores
	//[position][textNode]
	this.sortedElementsArray = new Array();
	this.contextObj = new Object();
	this.contextObj['this'] = this;
	this.childDepth = 1;//e.g. 
	/*
	DEPTH = 1
	<ul>
		<li>TEXT TO SORT BY</li>
		<li>TEXT TO SORT BY</li>
	</ul>
	
	DEPTH = 2
	<ul>
		<li><a>TEXT TO SORT BY</a></li>
		<li><a>TEXT TO SORT BY</a></li>
	</ul>
	*/
}

//initiliazer with configs
AlcassoftSorter.prototype.init=function(config){
	//code|value|default
	this.targetElementId = function(){if(config == null || config.targetElementId == null){return null;}else{return config.targetElementId;}return null;}();	
	this.targetElement = function(contextObj){if(config == null || config.targetElement == null){return $(contextObj['this'].targetElementId);}else{return config.targetElement;}return null;}(this.contextObj);
	
	//get child element
	if(this.targetElement!=null)
	{
		this.childElements = this.targetElement.childElements();
	}
}

//sorts all levels recursively
AlcassoftSorter.prototype.sortAll=function(sortby){
	//sort parent
	this.sort(sortby);
	//sort children
	var sortby = (sortby == null) ? null:sortby;
	
	if(this.targetElement){
		var childElements = this.childElements;
		for(var i=0;i<childElements.length;i++)
		{
			var newChildElements = childElements[i].childElements();
			for(var o=0;o<newChildElements.length;o++)
			{
				var sort = new AlcassoftSorter();
				sort.init({targetElement:newChildElements[o]});
				sort.sort(sortby);
			}
		}
	}
}

//sorts first level elements
AlcassoftSorter.prototype.sort=function(sortby){
	var sortby = function(){if(sortby == null){return null;}else{return sortby;}}();
	//var sortby = (sortby == null) ? null:sortby;
	
	if(this.targetElement){
		/*
		//Element highlight test
		Element.setStyle(this.targetElement,{backgroundColor:'red'})
		alert(this.targetElement);
		Element.setStyle(this.targetElement,{backgroundColor:''})
		*/
		
		//update child elements on sort in case the dom has been changed
		this.childElements = this.targetElement.childElements();
		//should not change during processing so static value is faster
		var childElementsLength = this.childElements.length;
		
		//build array of child [text node,child element]
		//user reverse iterator for performance
		//order is not a issue because we will sort it later
		for(var i=0;i<childElementsLength;i++){	
			var child = this.childElements[i];
			//get current text child text nodes
			var nodeText = this.myDown(child,this.childDepth).nodeValue;
			this.sortedElementsArray[i] = [nodeText,child];
		}
		
		if(sortby){//use defined sorting algo
			this.sortedElementsArray.sort(sortby);
		}
		else{//default sort
			this.sortedElementsArray.sort();
		}
		
		//remove children (might be faster to innerHTML = '' ?)
		for(var i=0;i<childElementsLength;i++)
		{
			this.targetElement.removeChild( this.childElements[i] );
		}
		
		//and reinsert in sorted order
		for(var i=0;i<childElementsLength;i++){
			this.targetElement.appendChild( this.sortedElementsArray[i][1] );
		}
	}
}

AlcassoftSorter.prototype.myDown=function(ele,levels){
	var result = ele;
	for(var i=1;i<levels;i++)
	{
		if(result.down(0)){
			result = result.down(0);
		}
		else{
			return result;
		}
	}
	try{
		return result.firstChild;
	}
	catch(e)
	{
		return null;
	}
}

//Inbuilt sorting function
AlcassoftSorter.prototype.sortByNumber=function(a,b){
	return parseInt(a[0]) - parseInt(b[0]);
}

AlcassoftSorter.prototype.sortByNumberReverse=function(a,b){
	return parseInt(b[0]) - parseInt(a[0]);
}

AlcassoftSorter.prototype.sortReverse=function(a,b){
	var alphabets = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'];
	var a = a[0];
	var b = b[0];
	var firstA;
	var firstB;
	
	if(a!=null && b!=null)
	{
		if(a.trim().length>0){
			firstA =  a.trim().toLowerCase().charAt(0);}
		else{
			firstA = 0;
		}
		
		if(b.trim().length>0){
			firstB = b.trim().toLowerCase().charAt(0);
		}
		else{
			firstB = 0;
		}
		return alphabets.indexOf(firstB) - alphabets.indexOf(firstA);
	}
	else{
		return -1;
	}
}

//Common util functions
String.prototype.trim=function(){
	return this.replace(/^\s+|\s+$/, '');
}