var VALID_NUMBERS = "0123456789";
var INFINITY_DENOTERS = "Infinity";
var EXPONENT_CHAR = "e";
var MAXIMUM_INTEGER = 2e31 - 1;

function Format_Decimal(actualValue, decimals)
{
	var decimalIndex = -1;
	var currentValue = "";
	var formattedValue = "";
	var exponentValue = "";
	var indexOfExponentChar = -1;
	var value = "" + actualValue;
	
	// if the value we receive is "NaN" then default it to 0.
	if (value == "NaN")
	{
		value = "0";
	}

	// first round the number.  there are a few operations that are taking place here
	// 1.  The DECIMAL_SEPARATOR is replaced with a "."
	// 2.  The value is rounded with the right decimal places
	// 3.  The "." is replaced by the DECIMAL_SEPARATOR
	var temp = "";

	// string replace did not work on mac firefox so just iterating thru the characters
	for (var i = 0; i < value.length; i++) {
		if (value.charAt(i) == DECIMAL_SEPARATOR) {
			temp += ".";
		}
		else {
			temp += value.charAt(i);
		}
	}

	value = ("" + Math.round(temp * Math.pow(10,decimals))/Math.pow(10,decimals));

	if (INFINITY_DENOTERS.indexOf(value) != -1) {
		value = "" + MAXIMUM_INTEGER;
	}

	temp = "";
	// string replace did not work on mac firefox so just iterating thru the characters
	for (var i = 0; i < value.length; i++) {
		if (value.charAt(i) == '.') {
			temp += DECIMAL_SEPARATOR;
		}
		else {
			temp += value.charAt(i);
		}
	}
	value = temp;

	if (value == 'NaN') {
		alert(MESSAGE_INVALID_NUMBER);
		value = "0";
	}

	decimalIndex = value.indexOf(DECIMAL_SEPARATOR);
	indexOfExponentChar = value.indexOf(EXPONENT_CHAR)

	if (decimalIndex != -1) {
		currentValue = value.substring(0, decimalIndex);
	}
	else {
		currentValue = (indexOfExponentChar == -1 ? value : value.substring(0, indexOfExponentChar));
	}

	// if we have an exponent, accomodate the exponent when parsing the number
	// this is required because 1e2 is a valid number (depending on the range)
	if (indexOfExponentChar != -1) {
		exponentValue = value.substring(indexOfExponentChar, value.length);
	}

	if (decimals > 0) {
		// add the DECIMAL_SEPARATOR
		currentValue += DECIMAL_SEPARATOR;

		for (var i = 0; i < decimals; i++) {
			if (decimalIndex != -1 && value.length > (decimalIndex + i + 1)) {
				currentValue += value.substring(decimalIndex + i + 1, decimalIndex + i + 2);
			}
			else {
				currentValue += "0";
			}
		}
	}

	// if we don't have any digits before the DECIMAL_SEPARATOR, then add one
	if (currentValue.charAt(0) == DECIMAL_SEPARATOR) {
		currentValue = "0" + currentValue;
	}

	// now from the decimal point, traverse left and add commas after every 3 characters
	decimalIndex = currentValue.indexOf(DECIMAL_SEPARATOR);

	// if we don't have a decimal, move the end
	if (decimalIndex == -1) {
		decimalIndex = currentValue.length;
	}

	// add the first 3 values before the decimal place and all the values after the decimal place
	formattedValue = currentValue.substring(decimalIndex - 3);

	// if the formatted value is empty, add a zero
	if (formattedValue.length == 0) {
		formattedValue = "0";
	}

	var character;
	for (var i = decimalIndex - 4, pos = 0; i >= 0; i--) {
		character = currentValue.charAt(i);

		if (pos % 3 == 0 && character != '-') {
			formattedValue = character + THOUSAND_SEPARATOR + formattedValue;
		}
		else {
			formattedValue = character + formattedValue;
		}

		if (VALID_NUMBERS.indexOf(currentValue.charAt(i)) >= 0) {
			pos++
		}
	}

	formattedValue += exponentValue;

	return formattedValue;
}

// validate the input
function Format_ValidateNumber(value, minValue, maxValue, numberOfDecimals)
{
	if (value < minValue || value > maxValue) {
		alert(MESSAGE_INVALID_NUMBER + "\n\n" + MESSAGE_NUMBER_RANGE + " " + Format_Decimal(minValue, numberOfDecimals) + " - " + Format_Decimal(maxValue, numberOfDecimals));
		return false;
	}

	return true;
}

// updates an update to the field
function Format_UpdateContent(ctrlName, value)
{
	// format the value provided to the function and then set it as the value for the formatter control
	if (document.forms[0].elements["__FORMATTER__" + ctrlName] != undefined) {
		document.forms[0].elements["__FORMATTER__" + ctrlName].value = (value != "" ? Format_Decimal(Format_ParseDecimal(value), document.forms[0].elements["__FORMATTER_DECIMALS__" + ctrlName].value * 1) : "");
	}

	// set the hidden field value
  if(document.forms[0].elements[ctrlName]){
    document.forms[0].elements[ctrlName].value = (value != "" ? Format_ParseDecimal(value) : "");
  }
}

// disable/enable formatter control
function Format_EnableControl(ctrlName, isEnabled)
{
	if (document.forms[0].elements["__FORMATTER__" + ctrlName] != undefined) {
		document.forms[0].elements["__FORMATTER__" + ctrlName].disabled = !isEnabled;
	}
}

// set the focus for the formatter control
function Format_FocusControl(ctrlName)
{
	document.forms[0].elements["__FORMATTER__" + ctrlName].focus();
}

// update the readonly property
function Format_MakeReadOnly(ctrlName, isReadOnly)
{
	document.forms[0].elements["__FORMATTER__" + ctrlName].readOnly = isReadOnly;
}
