/**
	The autocomplete module provides generic methods to re-format
	and auto-complete data fields with known formats. Currently 
	supported are:
	
	- Date
	- Time
	- Datetime
	- Money
	
	@copyright Copyright &copy; 2004, 2005, 2006, Umbrella Software AG 
	@author Simon Niederberger <simon.niederberger@umbrella.ch>
	@since 09.10.2006
	@version $Id: autocomplete.js 4850 2010-07-20 17:04:27 +0200 (Tue, 20 Jul 2010) sascha $	

*/

var reRemoveGroupingSymbol = new RegExp("[^-\\d" + (MONEY_DECIMAL_SEPARATOR == '.' ? "\\." : MONEY_DECIMAL_SEPARATOR ) + "]", "g");

/* ------------------------------------------------------------------------
	Function:  autocomplete_Date
	
	Synopsis:  Complete the date value by filling in the missing parts 
			   from the current date.

	Arguments: The text to format

	Returns:   The correctly formatted date.

	Notes:     none
	------------------------------------------------------------------------*/
function autocomplete_Date(origText) {
	return autocomplete_DateToText(autocomplete_TextToDate(origText));
}


/* ------------------------------------------------------------------------
	Function:  autocomplete_TextToDate
	
	Synopsis:  Extract a date from a text

	Arguments: The text to format

	Returns:   The correctly formatted date. If a formatting error
			   occurred, an empty string is returned.

	Notes:     none
	------------------------------------------------------------------------*/
function autocomplete_DateToText(date) {
	try {
		return ((date.getDate() <= 9 ? "0" + date.getDate() : date.getDate()) + "." + 
				(date.getMonth() < 9 ? "0" + (date.getMonth() + 1) : (date.getMonth() + 1)) + "." + 
				 date.getFullYear());
	}
	catch (e) {
		return date;
	}
}

/* ------------------------------------------------------------------------
	Function:  autocomplete_TextToDate
	
	Synopsis:  Extract a date from a text

	Arguments: The text to format

	Returns:   The correctly formatted date. If a formatting error
			   occurred, an empty string is returned.

	Notes:     none
	------------------------------------------------------------------------*/
function autocomplete_TextToDate(str) {
	
	if (typeof(str) == 'date') {
		return str;
	}
	
	if ((str == null) || (str.length == 0)) {
		return "";
	}
	
	str = str.replace(/[^\d\.]/g, "");
	
	if (str.indexOf('.') < 0) {
		switch (str.length) {
			case 1:
			case 2:
				break;
			case 3:
			case 4:
				str = str.substring(0, 2) + "." + str.substring(2);
				break;
			default:	
				str = str.substring(0, 2) + "." + str.substring(2, 4) + "." + str.substring(4);
				break;
		}
	}

	var arrParts = str.split(".");
	var now = new Date();

	/*
		Omitting the "break" here will beautifully fill up the date array
	*/
	var autoshiftMonth = false;
	var autoshiftYear = false;
	
	switch (arrParts.length) {
		case 0: arrParts[0] = "" + now.getDate();
		case 1: arrParts[1] = "" + (now.getMonth() + 1);
				autoshiftMonth = true;
		case 2: arrParts[2] = "" + now.getFullYear();
				autoshiftYear = true;
	}
	
	// Note that JS will parse 08 as octal number, so remove leading 0 before passing into 'parseInt'
	arrParts[0]	= parseInt(arrParts[0].replace(/^0/, ""));
	arrParts[1]	= parseInt(arrParts[1].replace(/^0/, ""));
	arrParts[2]	= parseInt(arrParts[2].replace(/^0/, ""));
	
	if (isNaN(arrParts[0])) {
		arrParts[0] = now.getDate();
	}
	
	if (isNaN(arrParts[1])) {
		arrParts[1] = (now.getMonth() + 1);
		autoshiftMonth = true;
	}
	
	if (isNaN(arrParts[2])) {
		arrParts[2] = now.getFullYear();
		autoshiftYear = true;
	}
	
	if ((autoshiftMonth) && (arrParts[0] < now.getDate())) {
		if (arrParts[1] == 12) {
			arrParts[1] = 1;
			arrParts[2]++;
		}
		else {
			arrParts[1]++;
		}
		autoshiftYear = false;
	}
	
	if ((autoshiftYear) && 
		((arrParts[1] < (now.getMonth() + 1)) ||
		((arrParts[1] == (now.getMonth() + 1)) && (arrParts[0] < now.getDate())))) {
		arrParts[2]++;
	}

	// assign year, month and THEN day to prevent unexpected shifts	
	if (!isNaN(arrParts[2])) {
		// allow years 1900 to 2100
		if ((arrParts[2] <= 1880) ||
			(arrParts[2] > 2100)) {
			
			// '73' probably means 1973, but '10' probably means 2010
			var fullyear = 2000 + (arrParts[2] % 1000);
			if ((fullyear - now.getFullYear()) > 10) {
				// fullyear is more than 10 years in the future, probably
				// meant last century
				fullyear = 1900 + (arrParts[2] % 100);
			}
			
			arrParts[2] = fullyear;
		}
		
		now.setFullYear(arrParts[2]);
	}
	
	now.setDate(15); // set the day of month to something each month supports to prevent unwanted auto-adjustments
	now.setMonth(arrParts[1] - 1);
	now.setDate(arrParts[0]);
	
	return now;
}

/* ------------------------------------------------------------------------
	Function:  autocomplete_ExpDate
	
	Synopsis:  Complete the date value by filling in the missing parts 
			   from the current date, formatting as expiration date
			   commonly seen on credit cards (08/2008)

	Arguments: The text to format

	Returns:   The correctly formatted date. If a formatting error
			   occurred, an empty string is returned.

	Notes:     none
	------------------------------------------------------------------------*/
function autocomplete_ExpDate(origText) {
	str = (origText == null ? "" : origText);
	
	if (str.indexOf('/') < 0) {
		switch (str.length) {
			case 1:
			case 2:
				break;
			case 3:
			case 4:
				str = str.substring(0, 2) + "/" + str.substring(2);
				break;
			default:	
				str = str.substring(0, 2) + "/" + str.substring(4);
				break;
		}
	}

	var arrParts = str.split("/");
	var now = new Date();

	/*
		Omitting the "break" here will beautifully fill up the date array
	*/
	switch (arrParts.length) {
		case 0: arrParts[0] = "" + (now.getMonth() + 1);
		case 1: arrParts[1] = "" + now.getFullYear();
	}
	
	arrParts[0]	= parseInt(arrParts[0].replace(/^0*/, ""));
	arrParts[1]	= parseInt(arrParts[1].replace(/^0*/, ""));
	
	if (!isNaN(arrParts[1])) {
		
		if (arrParts[1] < 60) {
			arrParts[1] += 2000;
		}
		now.setYear(arrParts[1]);
	}
	
	now.setDate(15); // set the day of month to something each month supports to prevent unwanted auto-adjustments

	if (!isNaN(arrParts[0])) {
		now.setMonth(arrParts[0] - 1);
	}

	
	return ((now.getMonth() < 9 ? "0" + (now.getMonth() + 1) : (now.getMonth() + 1)) + "/" + 
			 now.getFullYear());
}


/* ------------------------------------------------------------------------
	Function:  autocomplete_DayAndMonth
	
	Synopsis:  Complete the date value by filling in the missing parts 
			   from the current date, formatting as a day + month date,
			   mainly used for birthdays

	Arguments: The text to format

	Returns:   The correctly formatted date. If a formatting error
			   occurred, an empty string is returned.

	Notes:     none
	------------------------------------------------------------------------*/
function autocomplete_DayAndMonth(origText) {
	if (!origText) {
		return "";
	}
	
	var dt = autocomplete_TextToDate(origText);

	return 	(dt.getDate() <= 9 ? "0" + dt.getDate() : dt.getDate()) + "." + 
			(dt.getMonth() < 9 ? "0" + (dt.getMonth() + 1) : (dt.getMonth() + 1));
}

/* ------------------------------------------------------------------------
	Function:  autocomplete_Time
	
	Synopsis:  Complete the time value by filling in the missing parts 
			   from the current time.

	Arguments: The text to format

	Returns:   The correctly formatted time. If a formatting error
			   occurred, an empty string is returned.

	Notes:     none
	------------------------------------------------------------------------*/
function autocomplete_Time(origText) {
	if ((origText == null) || (origText.length == 0)) {
		return "";
	}
	
	if (origText.indexOf(':') < 0) {
		switch (origText.length) {
			case 1:
			case 2:
				break;
			default:
				origText = origText.substring(0, 2) + ":" + origText.substring(2);
				break;
		}
	}

	var arrParts = origText.split(":");
	var now = new Date();

	/*
		Omitting the "break" here will beautifully fill up the date array
	*/
	switch (arrParts.length) {
		case 0: arrParts[0] = now.getHours();
		case 1: arrParts[1] = now.getMinutes();
	}
	
	if (!isNaN(arrParts[0])) {
		now.setHours(arrParts[0]);
	}

	if (!isNaN(arrParts[1])) {
		now.setMinutes(arrParts[1]);
	}

	return (now.getHours() + ":" + (now.getMinutes() < 10 ? "0" + now.getMinutes() : now.getMinutes()));
}

/* ------------------------------------------------------------------------
	Function:  autocomplete_Money
	
	Synopsis:  Complete the currency amount by filling in the missing parts,
			   i.e. cents and thousand separators

	Arguments: The text to format
			   smallestUnit
			   noformat = true Is the text already in native format?
	Returns:   The correctly formatted amount (as string). If a formatting error
			   occurred, an empty string is returned.

	Notes:     none
	------------------------------------------------------------------------*/
function autocomplete_Money(origText, smallestUnit, noformat) {
	if ((origText == null) || (origText.length == 0)) {
		return "";
	}
	
	var dbl = autocomplete_RoundMoney(origText, smallestUnit, noformat);
	dbl = dbl.toFixed(2);
	return addSeparator(dbl, MONEY_GROUP_SEPARATOR);
}

// autocomplete money to a double
function autocomplete_RoundMoney(origText, smallestUnit, noformat) {
	if ((origText == null) || (origText.length == 0)) {
		return "";
	}
	
	if (!smallestUnit) {
		smallestUnit = DEFAULT_MONEY_UNIT;
	}
	else if ((typeof(smallestUnit) == 'string') && (moneyunits)) {
		smallestUnit = moneyunits[smallestUnit];
	}
	
	var dbl = noformat ? parseFloat(origText) : autocomplete_TextToFloat(origText);
	try {
		dbl = Math.round(dbl / smallestUnit) * smallestUnit;
	}
	catch (e) {
		; // smallestUnit is not defined or zero
	}
	return dbl;
}

function addSeparator(amt, sepChar) {
	amt += '';
	x = amt.split(/\./);
	x1 = x[0];
	x2 = x.length > 1 ? MONEY_DECIMAL_SEPARATOR + x[1] : '';
	var rgx = /(\d+)(\d{3})/;
	while (rgx.test(x1)) {
		x1 = x1.replace(rgx, '$1' + sepChar + '$2');
	}
	return x1 + x2;
}

/* ------------------------------------------------------------------------
	Function:  autocomplete_Percent
	
	Synopsis:  Complete the percent value by reducing to 1 digit precision
			   and adding a '%' sign

	Arguments: The text to format

	Returns:   The correctly formatted percent amount. If a formatting error
			   occurred, an empty string is returned.

	Notes:     none
	------------------------------------------------------------------------*/
function autocomplete_Percent(origText) {
	if ((origText == null) || (origText.length == 0)) {
		return "";
	}
	
	var dbl = autocomplete_TextToFloat(origText);
	return addSeparator(dbl.toFixed(1), MONEY_GROUP_SEPARATOR) + "%";
}

/* ------------------------------------------------------------------------
	Function:  autocomplete_TextToFloat
	
	Synopsis:  Extract a float from a text by leaving out all non-numeric
			   characters

	Arguments: The text to format

	Returns:   A float (number)

	Notes:     This method will not round monetary amounts
	------------------------------------------------------------------------*/
function autocomplete_TextToFloat(str) {
	// expect: 100 / 100.50 / 1'500.50 / -500.50
	if (typeof(str) == 'number') {
		str = autocomplete_FloatToText(str);
	}
	
	var value = "" + str;
	value = value.replace(reRemoveGroupingSymbol, "");
	if (MONEY_DECIMAL_SEPARATOR != ".") {
		value = value.replace(MONEY_DECIMAL_SEPARATOR, ".");
	}
	if (value == '') {
		value = 0;
	}
	
	return parseFloat(value);
}

function autocomplete_FloatToText(nbr, precision) {
	if (typeof(nbr) != 'number') {
		return nbr;
	}
	if (!precision) {
		precision = 2;
	}
	return addSeparator(nbr.toFixed(precision), MONEY_GROUP_SEPARATOR);
}

function autocomplete_Datetime(str) {
	if (str == null || str.length == 0) {
		return "";
	}
	
	var parts = str.split(" ");
	var datepart = autocomplete_Date(parts[0]);
	var timepart = autocomplete_Time((parts.length == 2) ? parts[1] : null);
	return datepart + " " + timepart;
}