/*--------------------------------------------------------------*/
// HTML TABLE SORTER
// OBJECT ORIENTED JAVASCRIPT IMPLEMENTATION OF QUICKSORT
// @author	Terrill Dent 
// @source	http://www.terrill.ca
// @date	August 28th, 2006
/*--------------------------------------------------------------*/
function TSorter(){
	this.table = Object;
	this.trs = Array;
	this.ths = Array;
	this.curSortCol = Object;
	this.prevSortCol = '3';
	this.sortType = Object;

	this.get = function(){}

	this.getCell = function(index){
		return this.trs[index].cells[this.curSortCol] 
	}

	/*----------------------INIT------------------------------------*/
	// Initialize the variable
	// @param tableName - the name of the table to be sorted
	/*--------------------------------------------------------------*/
	this.init = function(tableName)
	{
		this.table = document.getElementById(tableName);
		this.ths = this.table.getElementsByTagName("th");
		for(var i = 0; i < this.ths.length ; i++)
		{
			// Edit to get the onclick registered in yahoo ui
			//ths[i].id = tableName + '_th_' + i;
			//var el = new YAHOO.util.Element(ths[i].id);
			//el.on('click', function(cell) { return function(){ this.sort(cell); } }(ths[i]), this, true);
			YAHOO.util.Event.addListener(this.ths[i], "click", function(e, sorter){ sorter.sort(this); }, this, this.ths[i]); 
			/*ths[i].onclick = function()
			{
				sort(this);
			}*/
		}
		return true;
	};
	
	/*----------------------SORT------------------------------------*/
	// Sorts a particular column. If it has been sorted then call reverse
	// if not, then use quicksort to get it sorted.
	// Sets the arrow direction in the headers.
	// @param oTH - the table header cell (<th>) object that is clicked
	/*--------------------------------------------------------------*/
	this.sort = function(oTH, skipColumns)
	{
		// Check if this column gets skipped for sorting
		if(skipColumns) {
			for(var x = 0; x < skipColumns.length; ++x) {
				if(skipColumns[x] == oTH.cellIndex) {
					return;
				}
			}
		}
				
		this.curSortCol = oTH.cellIndex;
		this.sortType = oTH.abbr;
		this.trs = this.table.tBodies[0].getElementsByTagName("tr");

		//set the get function
		this.setGet(this.sortType)
		
		// it would be nice to remove this to save time,
		// but we need to close any rows that have been expanded
		for(var j=0; j<this.trs.length; j++)
		{
			if(this.trs[j].className == 'detail_row')
			{
				closeDetails(j+2);
			}
		}

		// if already sorted just reverse
		if(this.prevSortCol == this.curSortCol)
		{
			oTH.className = (oTH.className != 'ascend' ? 'ascend' : 'descend' );
			this.reverseTable();
		}
		// not sorted - call quicksort
		else
		{
			oTH.className = 'ascend';
			if(this.ths[this.prevSortCol] && this.ths[this.prevSortCol].className != 'exc_cell'){this.ths[this.prevSortCol].className = '';}
			this.quicksort(0, this.trs.length);
		}
		this.prevSortCol = this.curSortCol;
		
		// Fix up "alt" class on rows
		var tbl = this.table;
		var len = tbl.tBodies[0].rows.length;
		for(var i = 0; i < len; ++i) {
			tbl.tBodies[0].rows[i].className = i % 2 == 0 ? 'alt' : '';
		}
	}
	
	/*--------------------------------------------------------------*/
	// Sets the GET function so that it doesnt need to be 
	// decided on each call to get() a value.
	// @param: colNum - the column number to be sorted
	/*--------------------------------------------------------------*/
	this.setGet = function(sortType)
	{
		switch(sortType)
		{   
			case "linkColumn":
			case "link_column":
				this.get = function(index){
					if(!this.getCell(index).firstChild) return '';
					return  this.getCell(index).firstChild.firstChild.nodeValue;
				};
				break;
			case 'number':
				this.get = function(index){
					if(!this.getCell(index).firstChild) return 0;
					return  parseFloat(this.getCell(index).firstChild.nodeValue);
				};
				break;
			case 'inputBox':
				this.get = function(index){
					if(!this.getCell(index).getElementsByTagName('textarea')[0]) return '';
					return this.getCell(index).getElementsByTagName('textarea')[0].value;
				};
				break;
			default:
				this.get = function(index){	if(!this.getCell(index).firstChild) return ''; return this.getCell(index).firstChild.nodeValue;};
				break;
		};	
	}

	/*-----------------------EXCHANGE-------------------------------*/
	//  A complicated way of exchanging two rows in a table.
	//  Exchanges rows at index i and j
	/*--------------------------------------------------------------*/
	this.exchange = function(i, j)
	{
		if(i == j+1) {
			this.table.tBodies[0].insertBefore(this.trs[i], this.trs[j]);
		} else if(j == i+1) {
			this.table.tBodies[0].insertBefore(this.trs[j], this.trs[i]);
		} else {
			var tmpNode = this.table.tBodies[0].replaceChild(this.trs[i], this.trs[j]);
			if(typeof(this.trs[i]) == "undefined") {
				this.table.appendChild(tmpNode);
			} else {
				this.table.tBodies[0].insertBefore(tmpNode, this.trs[i]);
			}
		}
	}
	
	/*----------------------REVERSE TABLE----------------------------*/
	//  Reverses a table ordering
	/*--------------------------------------------------------------*/
	this.reverseTable = function()
	{
		for(var i = 1; i<this.trs.length; i++)
		{
			this.table.tBodies[0].insertBefore(this.trs[i], this.trs[0]);
		}
	}

	/*----------------------QUICKSORT-------------------------------*/
	// This quicksort implementation is a modified version of this tutorial: 
	// http://www.the-art-of-web.com/javascript/quicksort/
	// @param: lo - the low index of the array to sort
	// @param: hi - the high index of the array to sort
	/*--------------------------------------------------------------*/
	this.quicksort = function(lo, hi)
	{
		if(hi <= lo+1) return;
		 
		if((hi - lo) == 2) {
			if(this.get(hi-1) > this.get(lo)) this.exchange(hi-1, lo);
			return;
		}
		
		var i = lo + 1;
		var j = hi - 1;
		
		if(this.get(lo) > this.get(i)) this.exchange(i, lo);
		if(this.get(j) > this.get(lo)) this.exchange(lo, j);
		if(this.get(lo) > this.get(i)) this.exchange(i, lo);
		
		var pivot = this.get(lo);
		
		while(true) {
			j--;
			while(pivot > this.get(j)) j--;
			i++;
			while(this.get(i) > pivot) i++;
			if(j <= i) break;
			this.exchange(i, j);
		}
		this.exchange(lo, j);
		
		if((j-lo) < (hi-j)) {
			this.quicksort(lo, j);
			this.quicksort(j+1, hi);
		} else {
			this.quicksort(j+1, hi);
			this.quicksort(lo, j);
		}
	}
	
}
