/**
 * @fileoverview Library for Sorting Algorithms
 * 
 * @author	Gaetan Lauff	<glauff@plansoft.de>
 * @version $Id: lib.sort.js 286 2007-12-13 15:30:41Z glauff $
 *
 * This library includes:
 * 
 * 	natcompare.js -- Perform 'natural order' comparisons of strings in JavaScript.
 * 	Copyright (C) 2005 by SCK-CEN (Belgian Nucleair Research Centre)
 *	Written by Kristof Coomans <kristof[dot]coomans[at]sckcen[dot]be>
 *
 *	Based on the Java version by Pierre-Luc Paour, of which this is more or less a straight conversion.
 *	Copyright (C) 2003 by Pierre-Luc Paour <natorder@paour.com>
 * 
 *	The Java version was based on the C version by Martin Pool.
 *	Copyright (C) 2000 by Martin Pool <mbp@humbug.org.au>
 *
 *	This software is provided 'as-is', without any express or implied
 *	warranty.  In no event will the authors be held liable for any damages
 *	arising from the use of this software.
 *
 *	Permission is granted to anyone to use this software for any purpose,
 *	including commercial applications, and to alter it and redistribute it
 *	freely, subject to the following restrictions:
 *
 *	1. The origin of this software must not be misrepresented; you must not
 *	claim that you wrote the original software. If you use this software
 *	in a product, an acknowledgment in the product documentation would be
 *	appreciated but is not required.
 *	2. Altered source versions must be plainly marked as such, and must not be
 *	misrepresented as being the original software.
 *	3. This notice may not be removed or altered from any source distribution.
 */
var Sort = 
{
	/**
	 * Qsort Compare Function
	 * Compares Date-, String-, Numeric- and Currency Values
	 * Used in addition to array sort functions
	 *
	 * @param	{mixed}	a	value a that should be compared to or an object with a member called value
	 * @param	{mixed} b	value b
	 * @returns mixed
	 */
	compareValues: function(a, b)
	{
		if ( typeof a.value != "undefined" )
		{
			a = a.value;
		}
			
		if ( typeof b.value != "undefined" )
		{
			b = b.value;
		}
			
		if ( a == null || a == 'undefined' || a === false )
		{
			return -1;
		}
		
		if ( b == null || b == 'undefined' || b === false )
		{
			return 1;
		}
	
		var res;
		/**
		 * Date Compare
		 */
		if ( a.match(/^\d\d[\/-]\d\d[\/-]\d\d\d\d$/) || a.match(/^\d\d[\/-]\d\d[\/-]\d\d$/) ) 
		{
			if (a.length == 10) 
			{
		        var date1 = a.substr(6,4) + a.substr(3,2) + a.substr(0,2);
		    } 
		    else 
		    {
		        var year = a.substr(6,2);
		
		        if ( parseInt( year ) < 50 ) 
		        {
		        	year = '20' + year; 
		        } 
		        else 
		        {
		        	year = '19' + year;
		        }
		        
		        date1 = year + a.substr(3,2) + a.substr(0,2);
		    }
		    
		    if (b.length == 10) 
		    {
		        var date2 = b.substr(6,4) + b.substr(3,2) + b.substr(0,2);
		    } 
		    else 
		    {
		        var year = b.substr(6,2);
		        
		        if (parseInt(year) < 50) 
		        {
		        	year = '20' + year;
		        } 
		        else 
		        {
		       		year = '19' + year;
		        }
		       		
		        date2 = year + b.substr(3,2) + b.substr(0,2);
		    }
		    
		    if (date1 == date2)
		    {
		    	res = 0;
		    }
		    	
		    if ( date1 < date2 )
		    {
		    	res = -1;
		    }
	    	
	    	res = 1;
	    /**
	     * Currency Compare
	     */
		} 
		else if ( a.match(/^[€£$]|EURO/) || a.match(/[\d\.]\s+(EURO|[€£$])/) ) 
		{
			//alert(" a before replace: " + a + " b before replace: " + b + "!");
			
			var c = a.replace(/[^0-9.]/g,'');
	    	var d = b.replace(/[^0-9.]/g,'');
			//alert("a has type " + typeof(a) + " and value " + a + "|b has type " + typeof(b) + " and value: " + b);
			    
	    	res = parseFloat(c) - parseFloat(d); 
	    /**
	     * Numeric Compare
	     */
		} 
		else if (!isNaN( parseInt(a) ) && !isNaN( parseInt(b) ) ) 
		{
			if ( a.indexOf('.') != -1 || a.indexOf(',') != -1 ) 
			{
				/**
				 * Float Compare
				 */
				var c = parseFloat(a);
	    
	    		if (isNaN(c)) 
	    		{
	    			c = 0;
	    		}
	    
	    		var d = parseFloat(b);
	    
	    		if (isNaN(d)) 
	    		{
	    			d = 0;
	    		}
	    	
	    		res = c - d;
			} 
			else 
			{
				/**
				 * Integer Compare
				 */
				res = parseInt( a ) - parseInt( b);
			}
		} 
		else 
		{
			/**
	     	*String compare
	     	*/
			res = 1;
			
			if ( a == b ) 
			{
	    		res = 0;
			}
	    	
	   		if ( a < b ) 
	   		{
	    		res = -1;
	   		}
		}
		
		if (descend) 
		{
	    	res = res * -1;
		}
	
	    return res;
	},
	
	compareRight : function(a,b)
	{
		var bias = 0;
		var ia = 0;
		var ib = 0;

		var ca;
		var cb;

		// The longest run of digits wins.  That aside, the greatest
		// value wins, but we can't know that it will until we've scanned
		// both numbers to know that they have the same magnitude, so we
		// remember it in BIAS.
		for (;; ia++, ib++) {
			ca = a.charAt(ia);
			cb = b.charAt(ib);

			if (!Sort.isDigitChar(ca)
					&& !Sort.isDigitChar(cb)) {
				return bias;
			} else if (!Sort.isDigitChar(ca)) {
				return -1;
			} else if (!Sort.isDigitChar(cb)) {
				return +1;
			} else if (ca < cb) {
				if (bias == 0) {
					bias = -1;
				}
			} else if (ca > cb) {
				if (bias == 0)
					bias = +1;
			} else if (ca == 0 && cb == 0) {
				return bias;
			}
		}
	},
	
	isWhitespaceChar : function(a) {
		return ( a.charCodeAt(0) <= 32 ) ? true : false;
	},
	
	isDigitChar : function(a) {
		var charCode = a.charCodeAt(0);
		return ( charCode >= 48  && charCode <= 57 ) ? true : false;
	},
	
	natCompare: function(a,b) 
	{
		var regexpNumber = /^-?\d+([.,]\d*)?\s*$/;	// numbers (floats) with optional whitespaces at the end
	
		// -gl- 081218 adjusted to EasyGUI Usage
		if ( a.value )
			a = a.value;
			
		if ( b.value )
			b = b.value;
			
		if ( a === null || a === undefined || a === false )
			return -1;
		
		if ( b === null || b === undefined || b === false )
			return 1;
		
		//console.log( "Starting to compare a: " + a + " to b: " + b );
		
		if ( regexpNumber.test( a ) && regexpNumber.test( b ) ) 
		{
			// -og- 080701: two doubles -> we don't need to use natcompare
			a = a.replace( ',', '.' );
			b = b.replace( ',', '.' );
			
			var da = parseFloat( a );
			var db = parseFloat( b );
			if ( !isNaN( da ) && !isNaN( db ) )
			{
				if ( descend || descend == "true" ) 
				{
					if ( da <= db )
						return 1;
					else if ( da > db )
						return -1;
				}
				else
				{
					if ( da <= db ) 
						return -1;
					else if ( da > db )
						return +1;
				}
			}
			else if ( !isNaN( da ) )
			{
				if ( descend || descend == "true" ) 
					return 1;
				else return -1;
			}
			else if ( !isNaN( db ) )
			{
				if ( descend || descend == "true" ) 
					return -1;
				else return 1;
			}
			
			return 1;
		}
		
		if ( a.match(/^\d\d[\/-]\d\d[\/-]\d\d\d\d$/) && b.match(/^\d\d[\/-]\d\d[\/-]\d\d$/) ) 
		{
			if (a.length == 10) {
				var date1 = a.substr(6,4) + a.substr(3,2) + a.substr(0,2);
			} 
			else {
				var year = a.substr(6,2);
				year = (parseInt(year) < 50) ? '20' + year : '19' + year;
				date1 = year + a.substr(3,2) + a.substr(0,2);
			}
			
			if (b.length == 10) {
				var date2 = b.substr(6,4) + b.substr(3,2) + b.substr(0,2);
			}
			else {
				var year = b.substr(6,2);
				year = (parseInt(year) < 50) ? '20' + year : '19' + year;
				date2 = year + b.substr(3,2) + b.substr(0,2);
			}
			
			if (date1 == date2)
				return 0;
				
			if ( date1 < date2 )
				return -1;
				
			return 1;
		} 
		else if ( ( a.match(/^[€£$]|EURO/) || a.match(/[\d\.]\s+(EURO|[€£$])/) ) && ( b.match(/^[€£$]|EURO/) || b.match(/[\d\.]\s+(EURO|[€£$])/) ) ) 
		{
			var c = a.replace(/[^0-9.]/g,'');
			var d = b.replace(/[^0-9.]/g,'');
			return parseFloat(c) - parseFloat(d); 
		} 
		
		var ia = 0, ib = 0;
		var nza = 0, nzb = 0;
		var ca, cb;
		var result;

		while (true)
		{
			// only count the number of zeroes leading the last number compared
			nza = nzb = 0;

			ca = a.charAt(ia);
			cb = b.charAt(ib);

			// skip over leading spaces or zeros
			while ( Sort.isWhitespaceChar( ca ) || ca =='0' ) {
				if (ca == '0') {
					nza++;
				} else {
					// only count consecutive zeroes
					nza = 0;
				}

				ca = a.charAt(++ia);
			}

			while ( Sort.isWhitespaceChar( cb ) || cb == '0') {
				if (cb == '0') {
					nzb++;
				} else {
					// only count consecutive zeroes
					nzb = 0;
				}

				cb = b.charAt(++ib);
			}

			// process run of digits
			if (Sort.isDigitChar(ca) && Sort.isDigitChar(cb)) {
				if ((result = Sort.compareRight(a.substring(ia), b.substring(ib))) != 0) {
				
					// -og- 080623 adjusted to IsyCat usage
					if (descend || descend == "true") {
						result = result * -1;
					}
					
					return result;
				}
			}

			if (ca == 0 && cb == 0) {
				// The strings compare the same.  Perhaps the caller
				// will want to call strcmp to break the tie.
				
				// -og- 080623 adjusted to IsyCat usage
				if (descend || descend == "true") {
					return nzb - nza;
				}
				
				return nza - nzb;
			}

			// -og- 080623 adjusted to IsyCat usage
			if (descend || descend == "true") 
			{
				if (ca < cb) {
					return 1;
				} else if (ca > cb) {
					return -1;
				}
			}
			else
			{
				if (ca < cb) {
					return -1;
				} else if (ca > cb) {
					return +1;
				}
			}
			
			++ia; ++ib;
		}
	}
};
