
var startValidating = true;

$().ready(function()
{
	initaliseValidation();
});


// TODO: default values
function initaliseValidation()
{
	$("select").change(function() {validateElement(this); });	
	$("select, input, textarea").blur(function() {validateElement(this); });	
	
	// TODO: textareas
	//$("textarea").keyup(function() {validateElement(this); });
	
	$("input:radio, input:checkbox").click(function() {validateElement(this); });
	
	initaliseFocus();
}

function initaliseFocus()
{
	$("select, input, textarea").not('input:radio, input:checkbox, input:button, button').focus(function() {$(this).addClass('inputFieldFocus'); });	
	$("select, input, textarea").not('input:radio, input:checkbox, input:button, button').blur(function() {$(this).removeClass('inputFieldFocus'); });
}

function validateForm(form)
{
	logInfo('validateForm');
	
	startValidating = true;
	
	firstErrorElement = null;
	
	var fieldArray;
	if(typeof(form) == "undefined")
	{
		fieldArray = $('.inputField');
	}
	else // else only validate fields in this form		
	{
		fieldArray = $(form).find('.inputField');
	}
	
	fieldArray.each(function()
	{
		if(!validateElement(this)) {
			if(firstErrorElement == null) {
				firstErrorElement = this;
			}
		}
	});
	
	firstErrorElement = validateCustomFields(firstErrorElement);
	
	if(firstErrorElement == null){
		return true;
	}
	else{
		focusFirstInvalid(firstErrorElement);
		return false;
	}
}

function validateCustomFields(firstErrorElement)
{
	firstInvalid = null;
	if(typeof(customValidation) != "undefined") {
		firstInvalid = customValidation(firstErrorElement);
	}
	if(firstErrorElement == null) {
		return firstInvalid;
	} else {
		return firstErrorElement;
	}
}

function validateElement(element)
{
	logInfo('validateElement. element.name = ' + element.name);
	
	if( isCheckable(element) ){element = getValidationElement(element); }
	
	if(element != null && !isFieldHidden(element))
	{
		validation = $(element).metadata().validation;
		mandatory = $(element).metadata().mandatory;
		empty = !validationNotEmptyField(element, ['return boolean']);
		
		
		log('validation = ' + validation);
		log('mandatory = ' + mandatory);
		log('empty = ' + empty);
		
		
		// 1. Validate if mandatory or empty
		
		// If 'not mandatory' and 'no validation'
		if( (mandatory == null || !mandatory) && validation == null ) {return true; }		
		// If 'not mandatory' and empty
		if( (mandatory == null || !mandatory) && empty)
		{
			hideError(element);
			return true;			
		}
		// If mandatory and empty
		if( mandatory == true && empty)
		{
			if(startValidating)
			{
				displayError(element, getFieldLabel(element) + ' is required');
			}
			else
			{
				hideError(element);
			}
			return false;
		}
		
		// 2. Validate array of items	
		// At this stage, there is a value in the field and the field is mandatory		
		if(validation == null)
		{
			validation = [['notEmptyField']];	
		}		
		
		element.value = stripSpaces(element.value);
		
		var validationFunction;
		for(vei = 0; vei < validation.length; vei++)
		{
			validationFunction = validation[vei][0].charAt(0).toUpperCase() + validation[vei][0].slice(1)			
			validationFunction = eval('validation' + validationFunction);			
			
			validationReturn = validationFunction(element, validation[vei]);
			
			if(validationReturn == true)
			{
				hideError(element);
			}
			else
			{
				displayError(element, validationReturn);
				return false;
			}			
		}
	}
	
	return true;
}

function getValidationElement(element)
{
	if( $(element).metadata().validation != null )
	{
		return element;
	}
	
	elements = document.getElementsByName(element.name);
	
	for(gve = 0; gve < elements.length; gve++)
	{
		if( $(elements[gve]).metadata() != null )
		{
			return elements[gve];
		}
	}
	
	return null;
}

function validationNotEmptyField(element, parameters)
{
	log(' = validationNotEmptyField. element.name = ' + element.name);

	if( isCheckable(element) )
	{
		// At least 1 of these elements should be checked
		
		elements = document.getElementsByName(element.name);
		
		for(rlt = 0; rlt < elements.length; rlt++)
		{
			if(elements[rlt].checked == true)
			{
				return true;
			}
		}
	}
	else
	{
		if(element.value.length > 0)
		{
			return true
		}
	}
	
	if(typeof(parameters) != "undefined" && parameters[0] == 'return boolean')
	{
		return false;
	}
	else
	{
		return "This field is required";	
	}
}

function focusFirstInvalid(element)
{
	try 
	{
		if(element.type == "hidden")
		{
			element = document.getElementById(element.id + "1");
			
			element.focus();
		}
		else
		{
			element.focus();
		}
	} 
	catch(e) 
	{
	}
}

function validationMaxLength(element, parameters)
{
	if(element.value.length != null && parameters[1] != null)
	{
		if (element.value.length > parameters[1] )
		{
			element.value = element.value.substring(0, parameters[1]);
			return 'The maximun number of characters is ' + parameters[1];
		}
	}
	return true;
}

function isCheckable(element) 
{
	return( (element.type == "radio") || (element.type == "checkbox") );
}

function isFieldHidden(element)
{
	fieldHidden = false;
	if($(element).parents(".hidden").length > 0){
		fieldHidden = true;
	}
	
	return fieldHidden;
}



function displayError(element, message)
{
	//log(' === displayError. element.name = ' + element.name);
	
	// Allow [ ] . in the pattern
	var elementName = element.name.replace(/(\[|\]|\.)/g, '\\$1')
	
	if($('#' + elementName + 'Error').length != 0)
	{
		$('#' + elementName).addClass('inputFieldError');
		
		$('#' + elementName + 'Error').html(message);
		$('#' + elementName + 'Error').css('display', 'block');
	}
}

function hideError(element)
{
	//log(' = hideError. element.name = ' + element.name);
	
	var elementName = element.name.replace(/(\[|\]|\.)/g, '\\$1')
	
	if($('#' + elementName + 'Error').length != 0)
	{
		$('#' + elementName).removeClass('inputFieldError');
		
		$('#' + elementName + 'Error').html('');
		$('#' + elementName + 'Error').css('display', 'none');
	}
}



function validationAlphabetic(element)
{
	if (!element.value.match(/[^A-Z]/i)) 
	{
		return true;
	}
	
	return getFieldLabel(element) + " can only contain letters";
}

function validationMoney(element)
{
	if ( (element.value.match(/\d{1,9}\.{1}\d{0,2}|\d{1,9}/)) && (element.value.match(/\d{1,9}\.{1}\d{0,2}|\d{1,9}/) == element.value) )
	{
		return true;
	}
	
	return getFieldLabel(element) + " can only contain 9 significant digits and 2 after the decimal point";
}

function validationAlphabeticName(element)
{
	if (!element.value.match(/[^\sA-Z-']/i)) 
	{
		return true;
	}
	
	return getFieldLabel(element) + " can only contain a to z, A to Z, the characters - ' and the space character";
}

function validationAlphanumericAddress(element)
{
	if (!element.value.match(/[^\sA-Z0-9\.\,\&'-]/i)) 
	{
		return true;
	}
	
	return getFieldLabel(element) + " can only contain a to z and A to Z and 0 to 9 and the characters , - ' . & and the space character";
}

function getFieldLabel(element)
{
	return $(element).metadata().label == null ? 'This field' : $(element).metadata().label;
}

function validationAlphanumericAll(element)
{
	if (!element.value.match(/[^\sA-Z0-9\!\\\"\£\$\€\%\&\*\(\)\_\+\-\=\[\]\{\}\:\@\~\;\'\#\|\<\>\?\\\,\.\\\/]/i))	
	{
		return true;
	}
	
	return getFieldLabel(element) + " can only contain a to z and A to Z and 0 to 9 and the characters ! \" &#163; $ &#8364; % & * ( ) _ + - = [ ] { } : @ ~ ; ' # | < > ? \\\ , . / and the space character";
}

function validationAlphaNumeric(element)
{
	if (!element.value.match(/[^a-zA-Z0-9]/))
	{
		return true;
	}
	
	return getFieldLabel(element) + ' can only contain letters and numbers';
}

function validationNumeric(element)
{
	if (!element.value.match(/[^0-9]/))
	{
		return true;
	}
	
	return getFieldLabel(element) + ' can only contain numbers';
}

function validationMinLength(element, parameters)
{
	if (element.value.length > parameters[1] - 1)
	{
		return true;
	}
	
	return getFieldLabel(element) + ' should be at least ' + parameters[1] + ' characters long';
}

// Valid date
function validationDate(element)
{	
	$(element).dateNormalizer();
		
	// Only skip validation if a value is not entered and its not mandatory
	if(element.value.length == 0)
	{
		if($(element).metadata().mandatory != null)
		{
			if($(element).metadata().mandatory == false)
			{
				return true;
			}
		}
	}
	
	if(Date.parseExact(element.value, 'dd/MM/yyyy') != null)
	{
		return true;
	}
	
	return getFieldLabel(element) + " is not a valid date";
}

function validationDateAfter(element, parameters)
{
	isDateAfter = Date.parseExact(element.value, 'dd/MM/yyyy').compareTo(Date.parseExact(parameters[1], 'dd/MM/yyyy')) == 1;
	
	if(isDateAfter)
	{
		return true
	}
	else
	{
		return "This date should be after " + parameters[1];
	}
}

function validationDateBefore(element, parameters)
{
	var dateBefore;
	
	if(parameters[1] == 'todayMinus18Years')
	{
		dateBefore = Date.parseExact(dateNow, 'dd/MM/yyyy').addYears(-18).addDays(1).toString('dd/MM/yyyy');
	}
	else
	{
		dateBefore = parameters[1];
	}
	
	isDateBefore = Date.parseExact(element.value, 'dd/MM/yyyy').compareTo(Date.parseExact(dateBefore, 'dd/MM/yyyy')) == -1;
	
	if(isDateBefore)
	{
		return true
	}
	else
	{
		return("This date should be before " + dateBefore);
	}
}

function validationAge(element)
{
	lifeBirthDtElement = $('#life' + $(element).metadata().life + 'BirthDt');
	if( validationDate(lifeBirthDtElement[0]) != true)
	{
		return "Please input the date of birth above";
	}
	
	ageNext = getAge(lifeBirthDtElement.val()) + 1;
	
	if( ageNext != $(element).val() )
	{
		return 'This age next birthday should be ' + ageNext + ' as calculated from the date of birth above';
	}
	
	return true;	
}

function getAge(date)
{
	D = date.substring(0,2);
	M = date.substring(3,5);
	Y = date.substring(6,10);
	now = Date.parseExact(dateNow, 'dd/MM/yyyy');
	m = now.getMonth() + 1;
	d = now.getDate();
	return now.getFullYear()-Y+(M>m?-1:M==m&&D>d?-1:0);
}

function validationEmail(element)
{
	log('validationEmail');
	
	var reg = /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/;
	
	if(reg.test(element.value) == true) 
	{
		return true
	}
	
	return getFieldLabel(element) + " should be in valid email format: name@domain.ie";
}

function stripSpaces(value) 
{
	// This function strips leading and trailing whitespaces from a string	
	var re = new RegExp();
	re = /\s+$|^\s+/g;
	
	return value.replace(re, "");
}


function initFieldUpdates(divId)
{
	log(' = initFieldUpdates');
	
	var fieldUpdateArray;
	
	if(divId != null)
	{
		fieldUpdateArray = $('#' + divId).find(".fieldUpdateElement");
	}
	else
	{
		fieldUpdateArray = $().find(".fieldUpdateElement");
	}
	
	fieldUpdateArray.each(function()
	{
		if(!isFieldHidden(this))
		{
			if($(this).metadata().fieldUpdateFunction != null)
			{
				eval($(this).metadata().fieldUpdateFunction)
			}
		}
	});
}

function getSelected(id)
{
	return $("#" + id + " option:selected")[0].value;
}

function getSelectedRadioId(name)
{
	elements = document.getElementsByName(name);
	
	for(rlt = 0; rlt < elements.length; rlt++)
	{
		if(elements[rlt].checked == true)
		{
			return elements[rlt].id;
		}
	}
	
	return false;
}

function validateAndPrintForm()
{
	if( validateForm() )
	{
		window.print();
	}
}


