function clientValidator(countryIsoCode) {
	this.items            = [];
	this.conditionItems   = [];
	this.errors           = [];
	this.isValid          = true;
	this.Country_IsoCode  = (countryIsoCode) ? countryIsoCode : 'dk';
	this.renderMethod     = 'summery';
	this.hasBeenValidated = false;
	this.headText         = '';
	this.translateArray   = {};
	this.translateArray.add = function(v) {
	};
}

clientValidator.prototype.reset = function(hardReset) {
	if (hardReset) {
		this.items.length = 0;
		this.conditionItems.length = 0;
	}

	this.errors           = [];
	this.isValid          = true;
	this.hasBeenValidated = false;

	jQuery('#clientErrorContainer').empty();
};

clientValidator.prototype.add = function(objValidator) {
	this.items.push(objValidator);
};

clientValidator.prototype.addCondition = function(condition, objValidator) {
	var i = this.conditionItems.length;
	this.conditionItems[i] = objValidator;
	this.conditionItems[i].condition = condition;
};

clientValidator.prototype.addError = function(objValidator) {
	this.errors.push(objValidator);
};

clientValidator.prototype.validate = function() {
	this.reset();
	this.onValidateStart();

	for (var i = 0; i < this.items.length; i++) {
		if (!this.items[i].validate()) {
			this.addError(this.items[i]);
			this.isValid = false;
		}
	}

	// CONDITION ITEMS, only added and validated if the condition is true!
	for (var i = 0; i < this.conditionItems.length; i++) {
		if (eval(this.conditionItems[i].condition)) {
			if (!this.conditionItems[i].validate()) {
				this.addError(this.conditionItems[i]);
				this.isValid = false;
			}
		}
	}

	if (!this.isValid) this.onValidateError();

	this.onValidateEnd();
	this.hasBeenValidated = false;
	return this.isValid;
};

clientValidator.prototype.getErrorText = function(errIndex) {
	var err = this.errors[errIndex];
	var etext = err.errorText;
	var etext2 = '';
	var fname = 'fieldname not found';

	if (etext && etext.indexOf('%f') >= 0) {
		fname = jQuery('#' + err.clientId).attr('fieldname');
		etext2 = etext.replace(/%fieldname%/ig, '"' + fname + '"');
	} else {
		etext2 = etext;
	}

	return etext2;
};

clientValidator.prototype.render = function(highlight) {
	var errors = [];

	switch (this.renderMethod) {
		case 'summery' :
			errors.push(
				'<div class="hspace"></div>',
				'<div class="ui-widget">',
					'<div class="', (highlight) ? 'ui-state-highlight' : 'ui-state-error', '" style="padding: 0.0em 0.7em;">',
						'<p>',
							'<span class="ui-icon ', (highlight) ? 'ui-icon-info' : 'ui-icon-alert', '" style="float: left; margin-right: 0.3em;"></span>'
			);

			if (highlight) {
			} else {
				errors.push('<strong>', this.headText, '</strong><br />');
			}

			for (var i = 0; i < this.errors.length; i++) {
				errors.push(this.getErrorText(i), '<br />');
			}

			errors.push(
						'</p>',
					'</div>',
				'</div>'
			);

			jQuery('#clientErrorContainer').empty().html(errors.join(''));
			window.scrollTo(0, jQuery('#clientErrorContainer').offset().top);
			break;

		case 'alertbox' :
			for (var i = 0; i < this.errors.length; i++) {
				errors.push(this.getErrorText(i));
			}
			alert(errors.join('\n'));
			break;
	}
};

clientValidator.prototype.onValidateEnd = function() { };
clientValidator.prototype.onValidateStart = function() { };
clientValidator.prototype.onValidateError = function (){ };

/*
 * Helper Functions
 */
function _validHour(theHour) {
	var m = theHour.split(':');
	if (parseInt(m[0]) <= 23 && parseInt(m[1]) <= 59) {
		return true;
	} else {
		return false;
	}
}

function _daysInMonth(intMonth, intYear) {
	if (intMonth == 1 || intMonth == 3 || intMonth == 5 || intMonth == 7 || intMonth == 8 || intMonth == 10 || intMonth == 12) {
		return 31;
	} else if (intMonth == 4 || intMonth == 6 || intMonth == 9 || intMonth == 11) {
		return 30;
	} else if (intMonth == 2) {
		if (_isLeapYear(intYear)) {
			return 29;
		} else {
			return 28;
		}
	} else {
		return 0;
	}
}

function _isLeapYear(intYear) {
	if (intYear.length == 2) {
		if (intYear > 30) {
			intYear = parseInt('19' + intYear);
		} else {
			intYear = parseInt('20' + intYear);
		}
	}

	if (intYear % 400 == 0) {
		return true;
	} else if (intYear % 100 == 0) {
		return false;
	} else if (intYear % 4 == 0) {
		return true;
	} else {
		return false;
	}
}

function _validDate(source) {
	var datePartArray = (typeof(source) == 'object') ? cc.getDateParts(source.value) : cc.getDateParts(jQuery('#' + source).val());
	var tmpDaysInMonth = _daysInMonth(datePartArray[1], datePartArray[0]);
	if (datePartArray[2] <= tmpDaysInMonth && datePartArray[1] <= 12 && datePartArray[0] <= 2099 && datePartArray[0] >= 1900) {
		return true;
	} else {
		return false;
	}
}

function _regExp(objValidator, strPattern) {
	var theVal = jQuery('#' + objValidator.clientId).val();
	var m = theVal.match(strPattern)
	return (m == null || m.length < 0) ? false : true;
}

/*
 * Custom Validator
 */
function customValidator(fPointer) {
	this.fPointer = fPointer;
}

customValidator.prototype.validate = function() {
	var theObj = (typeof(this.fPointer) == 'string') ? eval('new ' + this.fPointer) : this.fPointer;
	this.errorText = theObj.errorText;
	return theObj.isValid;
};

/*
 * RegExpValidator Validator
 */
function regExpValidator(strClientId, strErrorText, regExp_Pattern, blnAllowEmpty) {
	this.clientId  = strClientId;
	this.errorText = strErrorText;

	var strType = typeof(regExp_Pattern);

	if (strType.toLowerCase() == 'string') {
		try {
			var objRegExpL = new regExpLibrary();
			this.pattern = objRegExpL.getRegExp(regExp_Pattern);
		} catch(er) {
			strTyp = typeof(objRegExpL);
			if (strTyp.toLowerCase() != 'object') {
				alert('Please import RegExp Library, validation failed.');
				return false;
			}
		}
	} else {
		this.pattern = regExp_Pattern;
	}
	this.allowEmpty = (typeof(blnAllowEmpty) == 'boolean') ? blnAllowEmpty : false;
};

regExpValidator.prototype.validate = function() {
	if (jQuery.trim(jQuery('#' + this.clientId).val()) == '' && this.allowEmpty) return true;
	return _regExp(this, this.pattern);
};

/*
 * Inrange Validator
 */
function inRangeValidator(strClientId, strErrorText, rangeMin, rangeMax, dataType) {
	this.clientId  = strClientId;
	this.errorText = strErrorText;
	this.rangeMin  = rangeMin;
	this.rangeMax  = rangeMax;
	this.dataType  = (dataType) ? dataType : 'integer';
}

inRangeValidator.prototype.validate = function() {
	var theVal = jQuery('#' + this.clientId).val();
	switch (this.dataType.toLowerCase()) {
		case 'decimal':
			theVal = cc.toDecimal(theVal);
			break;
		case 'integer':
			theVal = parseInt(theVal);
			break;
	}
	return (theVal >= this.rangeMin && theVal <= this.rangeMax) ? true : false;
};

/*
 * Compare Validator
 */
function compareValidator(clientId1, clientId2, strOperator, strErrorText, dataType) {
	this.clientId1 = clientId1;
	this.clientId2 = clientId2;
	this.operator  = strOperator;
	this.errorText = strErrorText;
	this.dataType  = (dataType) ? dataType : 'integer';
}

compareValidator.prototype.validate = function() {
	var v1 = jQuery('#' + this.clientId1).val();
	var v2 = jQuery('#' + this.clientId2).val();

	switch (this.dataType.toLowerCase()) {
		case 'integer':
			v1 = parseInt(v1);
			v2 = parseInt(v2);
			break;
		case 'string':
			v1 = v1.toString();
			v2 = v2.toString();
			break;
		case 'handicap':
			v1 = cc.toHandicap(v1);
			v2 = cc.toHandicap(v2);
			break;
		default:
			v1 = v1.toString();
			v2 = v2.toString();
			break;
	}

	switch (this.operator) {
		case '!=': return (v1 != v2);
		case '<>': return (v1 != v2);
		case '>' : return (v1 > v2);
		case '>=': return (v1 >= v2);
		case '<' : return (v1 < v2);
		case '<=': return (v1 <= v2);
		case '=' : return (v1 == v2);
		case '==': return (v1 == v2);
		default:
			alert('( ' + this.operator + ' ) is not a valid compare operator!');
			return false;
	}
};

/*
 * Date Validator
 */
function dateValidator(strClientId, strErrorText, blnAllowEmpty, minDate, maxDate, strFormat) {
	this.clientId   = strClientId;
	this.errorText  = strErrorText;
	this.allowEmpty = blnAllowEmpty;
	this.minDate    = minDate;
	this.maxDate    = maxDate;
	this.strFormat  = (strFormat) ? strFormat : 'dd-mm-yyyy';
}

dateValidator.prototype.validate = function() {
	if (jQuery.trim(jQuery('#' + this.clientId).val()) == '' && this.allowEmpty) return true;

	changeInputDate(jQuery('#' + this.clientId)[0]);

	if (!new regExpValidator(this.clientId, this.errorText, 'date', this.allowEmpty).validate()) {
		return false;
	} else{
		return _validDate(this.clientId);
	}
};

/*
 * Time Validator
 */
function timeValidator(strClientId, strErrorText, blnAllowEmpty) {
	this.clientId   = strClientId;
	this.errorText  = strErrorText;
	this.allowEmpty = blnAllowEmpty;
}

timeValidator.prototype.validate = function() {
	if (jQuery.trim(jQuery('#' + this.clientId).val()) == '' && this.allowEmpty) return true;

	if (!_regExp(this, /^[0-2][0-9]:[0-5][0-9]$/)) {
		return false;
	} else {
		return _validHour(jQuery('#' + this.clientId).val());
	}
};

/*
 * Decimal Validator
 */
function decimalValidator(strClientId, strErrorText, blnAllowEmpty, intDecimals) {
	this.clientId    = strClientId;
	this.errorText   = strErrorText;
	this.allowEmpty  = (typeof(blnAllowEmpty) == 'boolean') ? blnAllowEmpty : false;
	this.intDecimals = (arguments[3]) ? intDecimals : 2;
}

decimalValidator.prototype.validate = function() {
	if (jQuery.trim(jQuery('#' + this.clientId).val()) == '' && this.allowEmpty) return true;

	if (this.intDecimals == 1) {
		return _regExp(this, /^\-*\d+((,|\.)\d{1,1})*$/);
	} else {
		return _regExp(this, /^\-*\d+((,|\.)\d{1,2})*$/);
	}
};

/*
 * Email Validator
 */
function emailValidator(strClientId, strErrorText, blnAllowEmpty) {
	this.clientId   = strClientId;
	this.errorText  = strErrorText;
	this.allowEmpty = (typeof(blnAllowEmpty) == 'boolean') ? blnAllowEmpty : false;
}

emailValidator.prototype.validate = function() {
	if (jQuery.trim(jQuery('#' + this.clientId).val()) == '' && this.allowEmpty) return true;

	/*
	 * Pattern Revised 2007-09-14
	 * The Official Standard: RFC 2822
	 */
	return _regExp(this, /^[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*@[a-zA-Z0-9]*[\w\.-]*[a-zA-Z0-9]\.[a-zA-Z][a-zA-Z\.]*[a-zA-Z]$/);
};

/*
 * Number Validator
 */
function numberValidator(strClientId, strErrorText, blnAllowEmpty, intMinValue, intMaxValue) {
	this.clientId   = strClientId;
	this.errorText  = strErrorText;
	this.allowEmpty = (typeof(blnAllowEmpty) == 'boolean') ? blnAllowEmpty : false;
	this.minValue   = (intMinValue == 'undefined' || intMinValue == null) ? 0 : intMinValue;
	this.maxValue   = (intMaxValue == 'undefined' || intMaxValue == null) ? null : intMaxValue;
}

numberValidator.prototype.validate = function() {
	if (jQuery.trim(jQuery('#' + this.clientId).val()) == '' && this.allowEmpty) return true;

	if (_regExp(this, /^-?\d+$/)) {
		var theVal = parseInt(jQuery('#' + this.clientId).val());
		if (this.minValue != null && this.maxValue != null) {
			if (theVal < this.minValue || theVal > this.maxValue) {
				return false;
			} else {
				return true;
			}
		} else if (this.minValue != null) {
			return (theVal < this.minValue) ? false : true;
		} else if (this.maxValue != null) {
			return (theVal > this.maxValue) ? false : true;
		} else {
			return true;
		}
	} else {
		return false;
	}
};

/*
 * Required Validator
 */
function requiredValidator(strClientId, strErrorText) {
	this.clientId  = strClientId;
	this.errorText = strErrorText;
}

requiredValidator.prototype.validate = function() {
	return (jQuery.trim(jQuery('#' + this.clientId).val()) == '') ? false : true;
};

/*
 * HCP Validator
 */
function hcpValidator(strClientId, strErrorText, blnAllowEmpty) {
	this.clientId   = strClientId;
	this.errorText  = strErrorText;
	this.allowEmpty = (typeof(blnAllowEmpty) == 'boolean') ? blnAllowEmpty : false;
}

hcpValidator.prototype.validate = function() {
	if (jQuery.trim(jQuery('#' + this.clientId).val()) == '' && this.allowEmpty) return true;

	var theVal = jQuery('#' + this.clientId).val();

	if (page.countryISOCode == 'ZA' && !_regExp(this, /^\+*\d+$/)) return false;
	if (!_regExp(this, /^\+*\d+((,|\.)\d{1,1})*$/)) return false;
	if (theVal.indexOf('+') == 0) theVal = theVal.replace('+', '-');
	if (cc.toDecimal(theVal) != 99 && cc.toDecimal(theVal) != 98) {
		if (!new inRangeValidator(this.clientId, '', -8, 36, 'decimal').validate()) {
			return false;
		} else {
			return true;
		}
	} else {
		return true;
	}
};

/*
 * AppliesTo Validator
 */
function appliesToValidator(strClientId, strErrorText) {
	this.clientId  = strClientId;
	this.errorText = strErrorText;
}

appliesToValidator.prototype.validate = function() {
	var theList = jQuery('#' + this.clientId).val();
	if (parseInt(theList.indexOf(';')) < 1) {
		return false;
	} else {
		return true;
	}
};

/*
 * Radio Validator
 */
function radioValidator(strClientId, strErrorText) {
	this.clientId  = strClientId;
	this.errorText = strErrorText;
}

radioValidator.prototype.validate = function() {
	return (jQuery('input[name="' + this.clientId + '"]:checked').length > 0) ? true : false;
};

/*
 * CheckBox Validator
 */
function requiredCheckbox(strClientIds, strErrorText, minChecked, maxChecked) {
	this.clientIds  = strClientIds;
	this.errorText  = strErrorText;
	this.minChecked = minChecked;
	this.maxChecked = maxChecked;
}

requiredCheckbox.prototype.validate = function() {
	var theVals = (!typeof(this.clientIds) == 'object') ? this.clientIds.split(',') : this.clientIds;
	var iChecked = 0;

	this.minChecked = (typeof(this.minChecked) == 'undefined') ? 1 : this.minChecked;
	this.maxChecked = (typeof(this.maxChecked) == 'undefined') ? theVals.length : this.maxChecked;

	if (this.maxChecked < this.minChecked) {
		this.errorText = 'Validation error: MaxValue < MinValue!';
		return false;
	}

	for (var i = 0; i < theVals.length; i++) {
		if (jQuery('#' + theVals[i]).prop('checked'))
			iChecked++;
	}

	if (iChecked >= this.minChecked && iChecked <= this.maxChecked) {
		return true;
	} else {
		return false;
	}
};

/*
 * PinCode Validator
 */
function pinCodeValidator(strClientId, strErrorText) {
	this.clientId  = strClientId;
	this.errorText = strErrorText;
}

pinCodeValidator.prototype.validate = function() {
	return _regExp(this, /^\d{4}$/);
};

/*
 * Runtime Validator
 */
function checkMaxLength(objField, intLength, strError) {
	if (objField.value.length > intLength - 1) {
		//Crop one to make sure the field is still editable
		objField.value = objField.value.substring(0, intLength - 1);
		if (strError.indexOf('%NumOfChars%') > 0) {
			alert(strError.replace('%NumOfChars%', intLength));
		} else {
			alert(strError);
		}
		return false;
	}
}

/*
 * MemberNumber Validator
 */
function memberNumberValidator(strClientId, strErrorText, blnAllowEmpty) {
	this.clientId   = strClientId;
	this.errorText  = strErrorText;
	this.allowEmpty = (typeof(blnAllowEmpty) == 'boolean') ? blnAllowEmpty : false;
}

memberNumberValidator.prototype.validate = function() {
	if (jQuery.trim(jQuery('#' + this.clientId).val()) == '' && this.allowEmpty) return true;
	return _regExp(this, /^\d{1,4}(\-)\d{1,}$/);
};

/*
 * GolfId Validator
 */
function golfIdValidator(strClientId, strErrorText, blnAllowEmpty) {
	this.clientId   = strClientId;
	this.errorText  = strErrorText;
	this.allowEmpty = (typeof(blnAllowEmpty) == 'boolean') ? blnAllowEmpty : false;
}

golfIdValidator.prototype.validate = function(){
	if (jQuery.trim(jQuery('#' + this.clientId).val()) == '' && this.allowEmpty) return true;
	return _regExp(this, /^\d{6}-\d{3}$/);
};

/*
 * GolfSe Password Validator
 */
function golfSePasswordValidator(strClientId, strErrorText) {
	this.clientId  = strClientId;
	this.errorText = strErrorText;
}

golfSePasswordValidator.prototype.validate = function() {
	/*
	 * Valid format: 4 digits
	 * Valid format: min. 6 characters, letters a-z, upper and lower case + 0-9.
	 *               must contain at least two digits
	 *               Example: aBc03F
	 */
	var pwd = jQuery.trim(jQuery('#' + this.clientId).val());
	var iPwd = 0;

	if (_regExp(this, /^\d{4}$/)) return true;

	if (_regExp(this, /^[a-zA-Z0-9]{6,}$/)) {
		// The RegExp format was valid now test if the password
		// contains at least two digits
		for (var i = 0; i < pwd.length; i++) {
			if (!isNaN(pwd.substr(i, 1))) {
				iPwd++;
			}
		}
		if (iPwd >= 2) return true;
	}
	return false;
};

