// JavaScript Document
function fv_init(formElem, paramOptions ){

	var formId = $( typeof(formElem) == 'object' ? formElem : '#'+formElem ).attr('id');
	if( ! formId )
	{
		formId = 'form'+ (100 + Math.floor(Math.random()*100));
		$(formElem).attr('id', formId);
	}
	formId = '#'+formId;

	var options = typeof(paramOptions) != 'undefined' ? paramOptions : (typeof(formElem.validateParams) != 'undefined' ? formElem.validateParams : {});

	var optionsDefault = {
		'trimSpaces' : 1,
		'errorClass': 'errorField',
		'errorMessageClass': 'errorMessage',
		'errorMessageSuffix': '_error4224622',
		'errorFlag': 'errorFlag',
		'requiredClass' : 'required',
		'emailClass' : 'email',
		'blankClass' : 'blank',
		'fieldOptions' : {}
	};
	var optionsFieldDefault = {
		'trimSpaces' : 1,
		'multipleValues' : 0,
		'multipleValuesMax' : 1,
		'multipleValuesDelimiter' : ','
	}
	for ( o in optionsDefault )
	{
		if ( typeof(options[o]) == 'undefined' || options[o] == "" )
			options[o] = optionsDefault[o];
	}
	for ( f in options['fieldOptions'] )
	{
		for ( o in optionsFieldDefault )
		{
			if ( typeof(options['fieldOptions'][f][o]) == 'undefined' || options['fieldOptions'][f][o] == "" )
				options['fieldOptions'][f][o] = optionsFieldDefault[o];
		}
	}

	if ( typeof(formElem) == 'object' )
		formElem.validateParams = options;

	return [formId, options];
}

function fv_reset(formElem, paramOptions )
{
	var init = fv_init(formElem, paramOptions );
	var formId = init[0];
	var options = init[1];
		// Reset error messages and error highlighting (bg color)
	$(formId+' .'+options['errorMessageClass']).remove();
	$(formId+' .'+options['requiredClass']).removeClass(options['errorClass']);
	$(formId+' .'+options['errorClass']).removeClass(options['errorClass']);

}

function fv_validate(formElem, paramOptions )
{
	var init = fv_init(formElem, paramOptions );
	var formId = init[0];
	var options = init[1];

	// Reset error messages and error highlighting (bg color)
	$(formId+' .'+options['errorMessageClass']).html('').hide();
	$(formId+' .'+options['requiredClass']).removeClass(options['errorClass']);

	// Begin checking

	var hasErrors = false;
	var errors = {};
	var errorsArr = [];

	$(formId+' .'+options['requiredClass']).each(
		function() {
			errorMessage = '';
			var fieldId = $(this).attr('name') || $(this).attr('id');  fv_debug('---- field: '+fieldId+' ----');
			var fLabel = $(this).attr( $(this).attr('title') != '' ? 'title' : 'name' );

			var fieldValidators = $(this).attr('class').split(/\s+/); fv_debug( 'fieldValidators: '+typeof(fieldValidators)+' = '+fieldValidators.join('+'));

			var fieldValues = $(this).val(); fv_debug('values:'+fieldValues);
			// Trim any leading and trailing space, if option is on (default: on)
			if ( options['trimSpaces'] )
			{
				fieldValues = fieldValues.replace(/^\s+|\s+$/g,'');
				$(this).val(fieldValues);
			}
			var fieldOptions = typeof(options['fieldOptions'][fieldId]) == 'object' ? options['fieldOptions'][fieldId] : '';
			if (
				fieldOptions &&
				fieldOptions['multipleValuesMax'] > 1
			)
			{
				var rex = new RegExp( fieldOptions['multipleValuesDelimiter'] );
				fieldValues = fieldValues.split(rex);
			}
			else
			{
				fieldValues = [ fieldValues ];
			}
			fv_debug('multiple?'+fieldOptions['multipleValues']+','+fieldOptions['multipleValuesMax']+'; num values:'+fieldValues.length);

			var fieldValuesCount = fieldValues.length;

			// Insert check for minimum number of values


			if ( fieldValuesCount > fieldOptions['multipleValuesMax'] )
				errorMessage = "you have entered too many values";

		for ( var i=0; i < fieldValuesCount && !errorMessage; i++ )
		{

			var v = fieldValues[i];

			if (fieldOptions && fieldOptions['trimSpaces'])
				v = v.replace(/^\s+|\s+$/g,'');

			fv_debug('value '+i+':'+v);
			fv_debug('validators: '
				+(fv_hasKey( fieldValidators, options['emailClass'] ) ? 'email' : '')+options['emailClass']+','
				+(fv_hasKey( fieldValidators, options['blankClass'] ) ? 'blank' : '')
			);
			if ( fv_hasKey( fieldValidators, options['blankClass'] ) )
			{
				fv_debug('is blank');
				if ( v != '' )
					errorMessage = 'error: malicious activity';
			}
			else if( v === '' )
			{
				errorMessage = ( fieldValuesCount > 1 ? 'a' : 'the' ) + ' value you entered is blank';
			}

			else if ( fv_hasKey( fieldValidators, options['emailClass'] ) || fieldId == 'email' )
			{
				fv_debug('is email');
				if ( !fv_isValidEmail(v) )
						errorMessage = ( fieldValuesCount > 1 ? 'an' : 'the') + ' email address you entered is invalid';
			}

		}//end-for each value

			// Add highlight (background color) if errors
			if (errorMessage)
			{
				var errorBoxId = $(this).attr('name')+options['errorMessageSuffix'];
				var errorBox = $('#'+errorBoxId);
				if ( errorBox.length > 0 )
					errorBox.addClass(options['errorMessageClass']).html(errorMessage).show();
				else
					$(this).before('<span id="'+errorBoxId+'" class="'+options['errorMessageClass']+'">'+errorMessage+'</span>');

				$(this).addClass(options['errorClass']);

				errors[fLabel] = errorMessage;
			}

		}//end-function

	);//end-each

	for(err in errors)
		errorsArr.push(errors[err] + ' in "' + err + '"');

	// If errors found, print error warning and put focus at beginning of form
	if ( errorsArr.length > 0 )
	{
		if($('#'+options['errorFlag']).length == 0) {
			$(formElem).prepend('<a id="'+options['errorFlag']+'" href="#""></a>');
		}

		var errorFlagAlt = "Please review the form for errors: "+errorsArr.join(',');
		$('#'+options['errorFlag']).attr('alt',errorFlagAlt).attr('title',errorFlagAlt).focus();
		// Clear errors
		errorsArr = []; errors = {};
		return false;
	}


	return true;
}



function fv_isValidEmail(emailAddress) {
	var pattern = new RegExp( "^[^\\n\\s,;@]+@[^\\n\\s,;@]+$");
	// Old pattern:	^(("[\w-\s]+")|([\w-]+(?:\.[\w-]+)*)|("[\w-\s]+")([\w-]+(?:\.[\w-]+)*))(@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$)|(@\[?((25[0-5]\.|2[0-4][0-9]\.|1[0-9]{2}\.|[0-9]{1,2}\.))((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\.){2}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\]?$)
	return pattern.test(emailAddress);
}

function fv_hasKey (h, k)
{
	fv_debug('hasKey: typeof='+ typeof(h));
	if ( typeof(h) == 'array' || typeof(h.length) == 'number' )
	{
		for(var i=0; i < h.length; i++)
		{
			fv_debug('hasKey: array item('+i+'):'+h[i]+'.'+(h[i]==k));
			if ( h[i] == k ) return true;
		}
		return false;
	}
	if ( typeof(h) == 'object')
	{
		fv_debug('hasKey: hash :'+h[k]);
		return typeof(h[k]) != 'undefined';
	}

	return false;
}

var fv_debug_on = 0;
function fv_debug( str )
{
	if ( !fv_debug_on ) return;
	if (typeof(console) != 'undefined' && typeof(console.log) != 'undefined' )
		console.log('fv: '+str);
}
