var idxLookup = new Array();
var sortOrders = new Array();
var lookupFilled = new Array();

var fieldName;
var tableName;

/*
	patternArgs interface:
	0 => Date pattern;
	1 => Numbers: decimal separator;
	2 => Numbers: thousands separator;
	3 => Decimal places;
	4 => Digit group
*/

var fpmPatternArgs;

function orderByGroup( afieldName, sortProcPtr, aTableName, patternArgs )
{

	fpmPatternArgs = patternArgs;
	
	iters = 0;

	fieldName = afieldName;
	tableName = aTableName;
	var tBody = document.getElementById( tableName ).getElementsByTagName( 'tbody' )[ 0 ];
	var trs = tBody.getElementsByTagName( 'tr' );
	var relevantTrs = new Array();
	
	for( var i = 0; i < trs.length; i++ )
		if( trs[ i ].id == '(dh)' )
		{
			var dH = trs[ i ];
			break;
		}

	if( !lookupFilled[ tableName ])
	{
		idxLookup[ tableName ] = new Array();
		sortOrders[ tableName ] = new Array();
		for( var i = 0; i < dH.cells.length; i++ )
			if( dH.cells[ i ].id )
			{
				idxLookup[ tableName ][ dH.cells[ i ].id ] = i;
				sortOrders[ tableName ][ dH.cells[ i ].id ] = false;
			}
		lookupFilled[ tableName ] = true;
	}

	var groupClassName, stdClassName, prevIndex = -1;
	
	while(( i < trs.length ) && ( trs[ i ].id != '(d)' ))
		i++;
	groupClassName = trs[ i ].cells[ 0 ].className;

	while(( i < trs.length ) && ( trs[ i ].cells[ 0 ].className == groupClassName ))
		i++;
	stdClassName = trs[ i ].cells[ 0 ].className;
			
	for( var i = 0; i < trs.length; i++ )
		if( trs[ i ].id == '(d)' )
		{
			if( trs[ i ].cells[ 0 ].className == groupClassName )
			{
				prevIndex++;
				relevantTrs[ prevIndex ] = new Array();
				relevantTrs[ prevIndex ][ 1 ] = new Array();
				relevantTrs[ prevIndex ][ 0 ] = trs[ i ];
			}
			else
				relevantTrs[ prevIndex ][ 1 ].push( trs[ i ]);
		}

	for( var i = trs.length - 1; i >= 0; i-- )
		if( trs[ i ].id == '(d)' )
			tBody.removeChild( trs[ i ]);

	relevantTrs.sort( sortProcPtr );
	var imgName = ascSort.src;
	if( sortOrders[ tableName ][ fieldName ])
		imgName = descSort.src;
		
	sortOrders[ tableName ][ fieldName ] =! sortOrders[ tableName ][ fieldName ];

	for( var i = 0; i < relevantTrs.length; i++ )
	{
		tBody.appendChild( relevantTrs[ i ][ 0 ]);
		for( var j = 0; j < relevantTrs[ i ][ 1 ].length; j++ )
			tBody.appendChild( relevantTrs[ i ][ 1 ][ j ]);
	}
		
	var otherImgs = dH.getElementsByTagName( 'img' );
	var m = /^img/;
	for( var i = 0; i < otherImgs.length; i++ )
		if( m.test( otherImgs[ i ].name ))
			otherImgs[ i ].src = neuSort.src;	
	document.images[ 'img' + fieldName ].src = imgName;
	tempedImg = imgName;
		
}

function orderBy( afieldName, sortProcPtr, aTableName, patternArgs )
{

	fpmPatternArgs = patternArgs;

	iters = 0;

	fieldName = afieldName;
	tableName = aTableName;
	var tBody = document.getElementById( tableName ).getElementsByTagName( 'tbody' )[ 0 ];
	var trs = tBody.getElementsByTagName( 'tr' );
	var relevantTrs = new Array();
				
	for( var i = 0; i < trs.length; i++ )
		if( trs[ i ].id == '(dh)' )
		{
			var dH = trs[ i ];
			break;
		}

	if( !lookupFilled[ tableName ])
	{
		idxLookup[ tableName ] = new Array();
		sortOrders[ tableName ] = new Array();
		for( var i = 0; i < dH.cells.length; i++ )
			if( dH.cells[ i ].id )
			{
				idxLookup[ tableName ][ dH.cells[ i ].id ] = i;
				sortOrders[ tableName ][ dH.cells[ i ].id ] = false;
			}
		lookupFilled[ tableName ] = true;
	}

	for( var i = 0; i < trs.length; i++ )
		if( trs[ i ].id == '(d)' )
		{
			relevantTrs.push( trs[ i ]);
		}

	for( var i = trs.length - 1; i >= 0; i-- )
		if( trs[ i ].id == '(d)' )
			tBody.removeChild( trs[ i ]);

	relevantTrs.sort( sortProcPtr );
	var imgName = ascSort.src;
	if( sortOrders[ tableName ][ fieldName ])
		imgName = descSort.src;
		
	sortOrders[ tableName ][ fieldName ] =! sortOrders[ tableName ][ fieldName ];

	for( var i = 0; i < relevantTrs.length; i++ )
		tBody.appendChild( relevantTrs[ i ]);
		
	var otherImgs = dH.getElementsByTagName( 'img' );
	var m = /^img/;
	for( var i = 0; i < otherImgs.length; i++ )
		if( m.test( otherImgs[ i ].name ))
			otherImgs[ i ].src = neuSort.src;	
	document.images[ 'img' + fieldName ].src = imgName;
	tempedImg = imgName;
	
	tBody.sortId = afieldName;
	fpmZebra( aTableName );
			
}

function getNodeValue( e )
{
	var nodeVal = '';
	if(( e.nodeType == 3 ) && ( e.nodeValue != '' ))
		nodeVal = e.nodeValue
	else
		for( var i = 0; i < e.childNodes.length; i++ )
			nodeVal = nodeVal + getNodeValue( e.childNodes[ i ]);
	return nodeVal;
}

var iters = 0;

function sortNumber( a, b )
{

	if( document.all )
	{
		var aVal = a.childNodes[ idxLookup[ tableName ][ fieldName ]].innerText;
		var bVal = b.childNodes[ idxLookup[ tableName ][ fieldName ]].innerText;
	}
	else
	{
		var aVal = getNodeValue( a.cells[ idxLookup[ tableName ][ fieldName ]]);
		var bVal = getNodeValue( b.cells[ idxLookup[ tableName ][ fieldName ]]);
	}	

	thousandsPattern = new RegExp( regExpEscape( fpmPatternArgs[ 2 ]));
	decimalPattern = new RegExp( regExpEscape( fpmPatternArgs[ 1 ]));

	aVal = aVal.replace( /%/, '' );
	aVal = aVal.replace( thousandsPattern, '' );
	aVal = aVal.replace( decimalPattern, '.' );
	aVal = parseFloat( aVal );

	bVal = bVal.replace( /%/, '' );
	bVal = bVal.replace( thousandsPattern, '' );
	bVal = bVal.replace( decimalPattern, '.' );
	bVal = parseFloat( bVal );

	if( isNaN( aVal ))
		aVal = -Number.MAX_VALUE;
	if( isNaN( bVal ))
		bVal = -Number.MAX_VALUE;

	return( sortOrders[ tableName ][ fieldName ] ? bVal - aVal : aVal - bVal );
}

function sortNumberGroup( a, b )
{
	if( document.all )
	{
		var aVal = a[ 0 ].childNodes[ idxLookup[ tableName ][ fieldName ]].innerText;
		var bVal = b[ 0 ].childNodes[ idxLookup[ tableName ][ fieldName ]].innerText;
	}
	else
	{
		var aVal = getNodeValue( a[ 0 ].cells[ idxLookup[ tableName ][ fieldName ]]);
		var bVal = getNodeValue( b[ 0 ].cells[ idxLookup[ tableName ][ fieldName ]]);
	}	

	thousandsPattern = new RegExp( regExpEscape( fpmPatternArgs[ 2 ]));
	decimalPattern = new RegExp( regExpEscape( fpmPatternArgs[ 1 ]));

	aVal = aVal.replace( /%/, '' );
	aVal = aVal.replace( thousandsPattern, '' );
	aVal = aVal.replace( decimalPattern, '.' );
	aVal = parseFloat( aVal );

	bVal = bVal.replace( /%/, '' );
	bVal = bVal.replace( thousandsPattern, '' );
	bVal = bVal.replace( decimalPattern, '.' );
	bVal = parseFloat( bVal );

	if( isNaN( aVal ))
		aVal = -Number.MAX_VALUE;
	if( isNaN( bVal ))
		bVal = -Number.MAX_VALUE;

	return( sortOrders[ tableName ][ fieldName ] ? bVal - aVal : aVal - bVal );
}

function sortDate( a, b )
{
	if( document.all )
	{
		var aVal = a.childNodes[ idxLookup[ tableName ][ fieldName ]].innerText.replace( /'/, '' );
		var bVal = b.childNodes[ idxLookup[ tableName ][ fieldName ]].innerText.replace( /'/, '' );
	}
	else
	{
		var aVal = getNodeValue( a.cells[ idxLookup[ tableName ][ fieldName ]]).replace( /'/, '' );
		var bVal = getNodeValue( b.cells[ idxLookup[ tableName ][ fieldName ]]).replace( /'/, '' );
	}
			
	var pattern = fpmPatternArgs[ 0 ];
	
	var aYear = 0, aMonth = 0, aDay = 0;
	var bYear = 0, bMonth = 0, bDay = 0;
	var ch;
	
	for( var i = 0; i < pattern.length; i++ )
	{
		ch = pattern.charAt( i );
		switch( ch )
		{
			case 'D':
				aDay = ( aDay * 10 ) + parseInt( aVal.charAt( i ));
				bDay = ( bDay * 10 ) + parseInt( bVal.charAt( i ));
				break;
			case 'M':
				aMonth = ( aMonth * 10 ) + parseInt( aVal.charAt( i ));
				bMonth = ( bMonth * 10 ) + parseInt( bVal.charAt( i ));
				break;
			case 'Y':
				aYear = ( aYear * 10 ) + parseInt( aVal.charAt( i ));
				bYear = ( bYear * 10 ) + parseInt( bVal.charAt( i ));
				break;
		}
	}
	
	aSerial = String( aYear ) + String( aMonth ) + String( aDay )
	bSerial = String( bYear ) + String( bMonth ) + String( bDay )
		
	if( aSerial == bSerial )
		return 0
	else if( sortOrders[ tableName ][ fieldName ])
		return( aSerial > bSerial ? -1 : 1 )
	else
		return( aSerial > bSerial ? 1 : -1 );
}
	
function sortDateGroup( a, b )
{
	if( document.all )
	{
		var aVal = a[ 0 ].childNodes[ idxLookup[ tableName ][ fieldName ]].innerText.replace( /'/, '' );
		var bVal = b[ 0 ].childNodes[ idxLookup[ tableName ][ fieldName ]].innerText.replace( /'/, '' );
	}
	else
	{
		var aVal = getNodeValue( a[ 0 ].cells[ idxLookup[ tableName ][ fieldName ]]).replace( /'/, '' );
		var bVal = getNodeValue( b[ 0 ].cells[ idxLookup[ tableName ][ fieldName ]]).replace( /'/, '' );
	}
	
	var pattern = fpmPatternArgs[ 0 ];
	
	var aYear = 0, aMonth = 0, aDay = 0;
	var bYear = 0, bMonth = 0, bDay = 0;
	var ch;
	
	for( var i = 0; i < pattern.length; i++ )
	{
		ch = pattern.charAt( i );
		switch( ch )
		{
			case 'D':
				aDay = ( aDay * 10 ) + parseInt( aVal.charAt( i ));
				bDay = ( bDay * 10 ) + parseInt( bVal.charAt( i ));
				break;
			case 'M':
				aMonth = ( aMonth * 10 ) + parseInt( aVal.charAt( i ));
				bMonth = ( bMonth * 10 ) + parseInt( bVal.charAt( i ));
				break;
			case 'Y':
				aYear = ( aYear * 10 ) + parseInt( aVal.charAt( i ));
				bYear = ( bYear * 10 ) + parseInt( bVal.charAt( i ));
				break;
		}
	}
	
	aSerial = String( aYear ) + String( aMonth ) + String( aDay )
	bSerial = String( bYear ) + String( bMonth ) + String( bDay )
		
	if( aSerial == bSerial )
		return 0
	else if( sortOrders[ tableName ][ fieldName ])
		return( aSerial > bSerial ? -1 : 1 )
	else
		return( aSerial > bSerial ? 1 : -1 );
}

function sortString( a, b )
{
	if( document.all )
	{
		var aVal = a.childNodes[ idxLookup[ tableName ][ fieldName ]].innerText;
		var bVal = b.childNodes[ idxLookup[ tableName ][ fieldName ]].innerText;
	}
	else
	{
		var aVal = getNodeValue( a.cells[ idxLookup[ tableName ][ fieldName ]]);
		var bVal = getNodeValue( b.cells[ idxLookup[ tableName ][ fieldName ]]);
	}	
	
	var aColl = '';
	var bColl = '';
	
	for( var i = 0; i < aVal.length; i++ )
		aColl = aColl + String.fromCharCode( serverCollation[ aVal.charCodeAt( i )]);

	for( var i = 0; i < bVal.length; i++ )
		bColl = bColl + String.fromCharCode( serverCollation[ bVal.charCodeAt( i )]);

	if( aColl == bColl )
		return 0
	else if( sortOrders[ tableName ][ fieldName ])
		return( aColl > bColl ? -1 : 1 )
	else
		return( aColl > bColl ? 1 : -1 );
}

function sortStringGroup( a, b )
{
	if( document.all )
	{
		var aVal = a[ 0 ].childNodes[ idxLookup[ tableName ][ fieldName ]].innerText;
		var bVal = b[ 0 ].childNodes[ idxLookup[ tableName ][ fieldName ]].innerText;
	}
	else
	{
		var aVal = getNodeValue( a[ 0 ].cells[ idxLookup[ tableName ][ fieldName ]]);
		var bVal = getNodeValue( b[ 0 ].cells[ idxLookup[ tableName ][ fieldName ]]);
	}	
	
	var aColl = '';
	var bColl = '';
	
	for( var i = 0; i < aVal.length; i++ )
		aColl = aColl + String.fromCharCode( serverCollation[ aVal.charCodeAt( i )]);

	for( var i = 0; i < bVal.length; i++ )
		bColl = bColl + String.fromCharCode( serverCollation[ bVal.charCodeAt( i )]);

	if( aColl == bColl )
		return 0
	else if( sortOrders[ tableName ][ fieldName ])
		return( aColl > bColl ? -1 : 1 )
	else
		return( aColl > bColl ? 1 : -1 );
}

var tempedImg;

var ascSort = new Image();
var descSort = new Image();
var neuSort = new Image();

function sortOn( t, o, c )
{
	var suff = c.replace( /-/, '' );

	try {
		eval( 'ascSort' + suff );
	} catch( e ) {
		eval( 'ascSort' + suff + ' = new Image(); ascSort' + suff + '.src = "/fpm-images/asc-sort-' + c + '.gif";' );
	}
	try {
		eval( 'ascSortH' + suff );
	} catch( e ) {
		eval( 'ascSortH' + suff + ' = new Image(); ascSortH' + suff + '.src = "/fpm-images/asc-sort-h-' + c + '.gif";' );
	}
	try {
		eval( 'descSort' + suff );
	} catch( e ) {
		eval( 'descSort' + suff + ' = new Image(); descSort' + suff + '.src = "/fpm-images/desc-sort-' + c + '.gif";' );
	}
	try {
		eval( 'descSortH' + suff );
	} catch( e ) {
		eval( 'descSortH' + suff + ' = new Image(); descSortH' + suff + '.src = "/fpm-images/desc-sort-h-' + c + '.gif";' );
	}
	try {
		eval( 'neuSort' + suff );
	} catch( e ) {
		eval( 'neuSort' + suff + ' = new Image(); neuSort' + suff + '.src = "/fpm-images/neu-sort-' + c + '.gif";' );
	}

	ascSort = eval( 'ascSort' + suff );
	descSort = eval( 'descSort' + suff );
	neuSort = eval( 'neuSort' + suff );

	tempedImg = document.images[ 'img' + o ].src;
	if( sortOrders[ t ] && sortOrders[ t ][ o ])
		document.images[ 'img' + o ].src = eval( 'descSortH' + suff + '.src' )
	else
		document.images[ 'img' + o ].src = eval( 'ascSortH' + suff + '.src' );

}

function sortOff( o )
{
	document.images[ 'img' + o ].src = tempedImg;
}

function resetSortOrder(list, col) {
  sortOrders[ list ][ col ] =! sortOrders[ list ][ col ];
}