CoreValidationMethods = {
    
	 setupValidation: function(formId, rules, messages, onErrorCallback, submitCallback, highlightErrorCallBack) {
        $(formId).validate({
            debug: false,
            onkeyup: false,
            rules: rules,
            messages: messages,
			errorElement: "span",
            errorPlacement: function(error, element) { CoreErrorHandling.displayFieldError(error, element);},
            invalidHandler: function(form, validator) {
					if (onErrorCallback) { onErrorCallback(); }
               CoreErrorHandling.updateErrorSummary();
					return false;
            },
			highlight: function(element) {
               CoreErrorHandling.highlightError(element);
               if (highlightErrorCallBack) { highlightErrorCallBack(); }
            },
			unhighlight: function(element) {
				CoreErrorHandling.unhighlightError(element);
			},
            success: function(element) { CoreErrorHandling.success(element); element.required = false; },
            submitHandler: function(form){
				if(typeof(submitCallback) == 'function') submitCallback(form);
				form.submit();
			}
        });
    },

	 // begin validation methods
	 
	 patternMatches: function(value, element, pattern) {
        return pattern.test(value);
    },

    lessThan: function(value, element, params) {
		var ld;
		if(typeof(params) == 'object') {
			ld = params.ld;
			params = params.val;
		}
		if(value !== "" && !(value == ld && CoreFunctions.isLuckyDip($(element).attr('id')))) {
			value = (value.substr(0,1) != "0") ? value : value - "0";
			return parseInt(value) < params;
		} 
		return true;
    },

    greaterThan: function(value, element, params) {
		var ld;
		if(typeof(params) == 'object') {
			ld = params.ld;
			params = params.val;
		}
		if(value !== "" && !(value == ld && CoreFunctions.isLuckyDip($(element).attr('id')))) {
			value = (value.substr(0,1) != "0") ? value : value - "0";
			return parseInt(value) > params;
		}
		return true;
    },

	valueEqualTo: function(value, element, param) {
        return value === $(param).val();
    },
    
    isNotEqualTo: function(elementValue, checkValue) {
        return elementValue != checkValue;
    },
    
    isNullOrEmpty: function(elementId) {
        var elementValue = $(elementId).val();
        var trimmedElementValue = $.trim(elementValue);
        $(elementId).val(trimmedElementValue);
        if (elementValue == null || elementValue === '') { return true; }
        if (navigator.appName === "Microsoft Internet Explorer" && elementValue === 'null') { return true; }
        return false;
    },
	
	isNumericAndTwoDigits: function(value, element, params) {
		var ld;
		if(typeof(params) == 'object') {
			ld = params.ld;
			params = params.val;
		}		 
		if(value == "" || (value == ld && CoreFunctions.isLuckyDip($(element).attr('id')))) { return true };
		if(CoreFunctions.isNumeric(value)) {
			$(element).val(CoreFunctions.padNumberToTwoDigits(value));
			return true;
		}		 
		return false;
	},
	
	isLDAndNumber: function(value, element, params) {
		if(CoreFunctions.isLuckyDip($(element).attr('id')) && value != params.ld) return;
		return true;
	},
	
	 
	 // begin date validations
	
	firstDrawRequired: function(value, element) {
		if(CoreFunctions.isDatePickerOpen()) return true;
		if(value == '' || value == 'DD/MM/YYYY') return false;
		return true;
	},
	
	lastDrawRequired: function(value, element) {
		if(CoreFunctions.isDatePickerOpen()) return true;
		if(value == '' || value == 'DD/MM/YYYY') return false;
		return true;
	},
	
	validDate: function(dateSelected, element, required) {
        if (required) { return Date.parse(dateSelected) != null; }
        return false;
    },

    isDateNotInThePast: function(value, element) {
        var dateToCheck = Date.parseExact(value, "d/M/yyyy");
        return (dateToCheck == null) ? false : dateToCheck.compareTo(Date.today()) >= 0;
    },
	 
	isDateNotInTheFuture: function(value, element) {
		if(value == '') return true; // an empty calendar will be refilled so this is valid
		if(CoreFunctions.isDatePickerOpen()) return true;
        var dateToCheck = Date.parseExact(value, "d/M/yyyy");
        return (dateToCheck == null) ? false : dateToCheck.compareTo(Date.today()) <= 0;
    },

    isDateNotAfterXDays: function(value, element, param) {
        var dateInXDays = Date.today().add(param).days();
        var dateToCheck = Date.parseExact(value, "d/M/yyyy");

        return (dateToCheck == null) ? false : dateToCheck.compareTo(dateInXDays) <= 0;
    },
	 
	 isDateNotBeforeXDays: function(value, element, param) {
		if(value == '') return true; // an empty calendar will be refilled so this is valid
		if(CoreFunctions.isDatePickerOpen()) return true;
        var dateInXDays = Date.today().add(param).days();
        var dateToCheck = Date.parseExact(value, "d/M/yyyy");
	    return (dateToCheck == null) ? false : dateToCheck.compareTo(dateInXDays) >= 0;
    },

    dateGreaterThan: function(value, element, param) {
        var dateValue = Date.parseExact(value, "d/M/yyyy");
        var dateToCompare = Date.parseExact($(param).val(), "d/M/yyyy");
        return dateValue.isAfter(dateToCompare);
    },

    dateLessThan: function(value, element, param) {
        var dateValue = Date.parseExact(value, "d/M/yyyy");
        var dateToCompare = Date.parseExact($(param).val(), "d/M/yyyy");
        return dateValue.isBefore(dateToCompare);
    },
	 
	 dateGreaterThanOrEqualTo: function(value, element, param) {
		if(value == '' || $(param).val() == 'DD/MM/YYYY') return true; // an empty calendar will be refilled so this is valid	and we can't compare if the other value is default
		if(CoreFunctions.isDatePickerOpen()) return true;
		var dateValue = Date.parseExact(value, "d/M/yyyy");
        var dateToCompare = Date.parseExact($(param).val(), "d/M/yyyy");
        if(dateToCompare != null && (dateValue.isAfter(dateToCompare) || dateValue.compareTo(dateToCompare) == 0)) {
			return true;
		};
		return false;
    },

    dateLessThanOrEqualTo: function(value, element, param) {
		if(value == '' || $(param).val() == 'DD/MM/YYYY') return true; // an empty calendar will be refilled so this is valid	and we can't compare if the other value is default
		if(CoreFunctions.isDatePickerOpen()) return true;
        var dateValue = Date.parseExact(value, "d/M/yyyy");
        var dateToCompare = Date.parseExact($(param).val(), "d/M/yyyy");
        if(dateValue.isBefore(dateToCompare) || dateValue.compareTo(dateToCompare) == 0) {
			return true;  
		};
		return false;
    },

    isValidDateAndCorrectsFormat: function(value, element) {
        var parsedDate = Date.parse(value);
        var dateIsValid = parsedDate !== null;
        if (dateIsValid) {
            $(element).val(parsedDate.toString("dd/MM/yyyy"));
        }
        return dateIsValid;
    },
	 
	 betweenDates: function(dateSelected, element, dates) {
        return Date.parse(dateSelected) >= Date.parse(dates[0]) && (Date.parse(dateSelected) < Date.parse(dates[1]));
    },
	 
	 minimumDate: function(dateSelected, element, minDate) {
        return Date.parse(dateSelected) >= Date.parse(minDate);
    },
	
	formatDateSelect: function(value, element) {
		var date = $(element).val();
		if(!/[0-9]{2}\/[0-9]{2}\/[0-9]{4}/.test(date)) { // test for well formated (but not necessarily valid) date
			date = date.split('/');
			if(date.length == 3) { // if it's not three then the date hasn't been typed well at all
				date[0] = (date[0].length < 2) ? '0' + date[0] : date[0];
				date[1] = (date[1].length < 2) ? '0' + date[1] : date[1];
				date[2] = (date[2].length < 4) ? '20' + date[2] : date[2];
			}
			$(element).val(date.join('/'));
		}
		return true;
	},
	 
	/* specific game validations */
	
	// param.min / param.min = min and max slot number to scan
	mustBeUniqueOnDrawLineMatrix: function(value, element, param) {
		if(value != "") {
			var testValue = CoreFunctions.padNumberToTwoDigits(value);
			var valueCount = 0;
			var currentName = $(element).attr("name");
			var matrix = (currentName.indexOf("matrix1") != -1) ? "matrix1" : "matrix2";
			if(currentName.indexOf("numbersChosen") != -1) matrix = 'numbersChosen';
			$(element).parent().parent().find("input[type=text][name*="+matrix+"]").each(function() {
				if(typeof(param) == 'object') {
					var slot = $(this).attr('id').substr(3, 1);
					if(!(CoreFunctions.isLuckyDip($(this).attr('id')) && value == param.ld) && slot >= param.min && slot <= param.max && testValue == CoreFunctions.padNumberToTwoDigits($(this).val())) { valueCount++; }
				} else {
					if(testValue == CoreFunctions.padNumberToTwoDigits($(this).val())) { valueCount++; }
				}
			});
			$(element).val(CoreFunctions.padNumberToTwoDigits(value));
			return (valueCount > 1) ? false : true;
		}
		return true;
	},
	 
	numberBoxesShouldBeFilled: function(value, element) {
		var emptyCount = $(element).parent().parent().find("input[type=text][value='']").length;
		if(($(element).is(":checked")) && (emptyCount > 0)) {
			return false;
		  }
		  return true;
	},
	 
	requiredIfSiblingsHaveValue: function(value, element) {
		var filledCount = $(element).parent().parent().find("input[type=text][value!='']").length;
		var totalCount = $(element).parent().parent().find("input[type=text]").length;
		if(($(element).val() == "") && (filledCount > 0) && (filledCount != totalCount)) {
			return false;
		}
		return true;
	},
	 
	isValidDreamNumber: function(value, element, param) {
		if(value == "") { return true };
		if(CoreFunctions.isNumeric(value) && (value.length == param)) {
			return true;
		}
		return false;
	},
	/*
	atLeastOnePlus5BoardExists: function(value, element) {
		plus5Box = $(element).parent().parent().find("input[id=cb_tb_cdd_plus5]");		
		if(plus5Box.is(":checked")) {
			var thisForm = plus5Box.form;
			if($(thisForm).find(".fivesboxreplaced input:checked").length) {
				return true;
			}
			return false;
		}
		return true;
	},
	*/
	isDaySelected: function(value, element) {
		if((value.replace(/_/g,'')).length > 0) return true;
	},
	 
	areWeeksSelected: function(value, element) {
		if(value > 0) return true;
	},
	 
	hasWholeBoard: function(value, element, params) {
		return fullBoards = CoreForms.fullBoards(element, params.boards, params.numbers);
	}
    
};

jQuery.validator.addMethod("patternMatches", CoreValidationMethods.patternMatches);
jQuery.validator.addMethod("lessThan", CoreValidationMethods.lessThan);
jQuery.validator.addMethod("greaterThan", CoreValidationMethods.greaterThan);
jQuery.validator.addMethod("valueEqualTo", CoreValidationMethods.valueEqualTo);
jQuery.validator.addMethod("isNotEqualTo", CoreValidationMethods.isNotEqualTo);
jQuery.validator.addMethod("isNullOrEmpty", CoreValidationMethods.isNullOrEmpty);
jQuery.validator.addMethod("firstDrawRequired", CoreValidationMethods.firstDrawRequired);
jQuery.validator.addMethod("lastDrawRequired", CoreValidationMethods.lastDrawRequired);
jQuery.validator.addMethod("validDate", CoreValidationMethods.validDate);
jQuery.validator.addMethod("isNumericAndTwoDigits", CoreValidationMethods.isNumericAndTwoDigits);
jQuery.validator.addMethod("isLDAndNumber", CoreValidationMethods.isLDAndNumber);
jQuery.validator.addMethod("isDateNotInThePast", CoreValidationMethods.isDateNotInThePast);
jQuery.validator.addMethod("isDateNotInTheFuture", CoreValidationMethods.isDateNotInTheFuture);
jQuery.validator.addMethod("isDateNotAfterXDays", CoreValidationMethods.isDateNotAfterXDays);
jQuery.validator.addMethod("isDateNotBeforeXDays", CoreValidationMethods.isDateNotBeforeXDays);
jQuery.validator.addMethod("dateGreaterThan", CoreValidationMethods.dateGreaterThan);
jQuery.validator.addMethod("dateLessThan", CoreValidationMethods.dateLessThan);
jQuery.validator.addMethod("dateGreaterThanOrEqualTo", CoreValidationMethods.dateGreaterThanOrEqualTo);
jQuery.validator.addMethod("dateLessThanOrEqualTo", CoreValidationMethods.dateLessThanOrEqualTo);
jQuery.validator.addMethod("isValidDateAndCorrectsFormat", CoreValidationMethods.isValidDateAndCorrectsFormat);
jQuery.validator.addMethod("betweenDates", CoreValidationMethods.betweenDates);	
jQuery.validator.addMethod("minimumDate", CoreValidationMethods.minimumDate);
jQuery.validator.addMethod("formatDateSelect", CoreValidationMethods.formatDateSelect);
jQuery.validator.addMethod("mustBeUniqueOnDrawLineMatrix", CoreValidationMethods.mustBeUniqueOnDrawLineMatrix);
jQuery.validator.addMethod("numberBoxesShouldBeFilled", CoreValidationMethods.numberBoxesShouldBeFilled);
jQuery.validator.addMethod("requiredIfSiblingsHaveValue", CoreValidationMethods.requiredIfSiblingsHaveValue);
jQuery.validator.addMethod("isValidDreamNumber", CoreValidationMethods.isValidDreamNumber);
//jQuery.validator.addMethod("atLeastOnePlus5BoardExists", CoreValidationMethods.atLeastOnePlus5BoardExists);
jQuery.validator.addMethod("isDaySelected", CoreValidationMethods.isDaySelected);
jQuery.validator.addMethod("areWeeksSelected", CoreValidationMethods.areWeeksSelected);
jQuery.validator.addMethod("hasWholeBoard", CoreValidationMethods.hasWholeBoard);
