$(document).ready(function(){	
	/* Custom Clientside Validation Methods */
	jQuery.validator.addMethod("regex", regexMethod, jQuery.format("The value entered does not match the specified pattern ({0})"));
	jQuery.validator.addMethod("phoneUS", function(phone_number, element) { phone_number = phone_number.replace(/\s+/g, ""); return this.optional(element) || phone_number.length > 9 && phone_number.match(/^(1-?)?(\([2-9]\d{2}\)|[2-9]\d{2})-?[2-9]\d{2}-?\d{4}$/); }, "Please specify a valid phone number");
	jQuery.validator.addMethod("datecompare", dateCompareMethod, jQuery.format("Date does not conform to set validation rules"));
	jQuery.validator.addMethod("datecompare2", dateCompareMethod, jQuery.format("Date does not conform to set validation rules"));
	jQuery.validator.addMethod("datecompare3", dateCompareMethod, jQuery.format("Date does not conform to set validation rules"));
	jQuery.validator.addMethod("valuecompare", valueCompareMethod, jQuery.format("Does not conform to set validation rules"));
	jQuery.validator.addMethod("valuecompare2", valueCompareMethod, jQuery.format("Does not conform to set validation rules"));
	jQuery.validator.addMethod("futuredate", futureDateMethod, jQuery.format("Date must be in the future"));
	jQuery.validator.addMethod("pastdate", pastDateMethod, jQuery.format("Date must be in the past"));
	jQuery.validator.addMethod("notfuturedate", notFutureDateMethod, jQuery.format("Date can not be in the future"));
	jQuery.validator.addMethod("lessthanage", lessThanAgeMethod, jQuery.format("Must be younger than {0}"));
	jQuery.validator.addMethod("greaterthanage", greaterThanAgeMethod, jQuery.format("Must be older than {0}"));
	jQuery.validator.addMethod("notequalto", notEqualToMethod, jQuery.format("Must not be {0}"));
	jQuery.validator.addMethod("notequalto2", notEqualToMethod, jQuery.format("Must not be {0}"));
	
	jQuery.validator.addMethod("mustbeif", mustbeifMethod, jQuery.format("Does not conform to set validation rules"));
	jQuery.validator.addMethod("mustbeif2", mustbeifMethod, jQuery.format("Does not conform to set validation rules"));
	jQuery.validator.addMethod("mustnotbeif", mustnotbeifMethod, jQuery.format("Does not conform to set validation rules"));
	jQuery.validator.addMethod("mustnotbeif2", mustnotbeifMethod, jQuery.format("Does not conform to set validation rules"));
	
	jQuery.validator.addMethod("mustnotbe", mustnotbeMethod, jQuery.format("Does not conform to set validation rules"));
	jQuery.validator.addMethod("mustbe", mustbeMethod, jQuery.format("Does not conform to set validation rules"));
	jQuery.validator.addMethod("mustnotbe2", mustnotbeMethod, jQuery.format("Does not conform to set validation rules"));
	jQuery.validator.addMethod("mustnotbe3", mustnotbeMethod, jQuery.format("Does not conform to set validation rules"));
	jQuery.validator.addMethod("mustbe2", mustbeMethod, jQuery.format("Does not conform to set validation rules"));
});


/* ******************* Extra Validation Methods ******************** */
function regexMethod(value, element, params){
	var re = params.expression; 
	var a = true;
	if (jQuery.isFunction(params.active))
		a = params.active(element);
	else
		a = params.active;
	
	if (!a)
		return true;
	else
		return this.optional(element) || re.test(value);
}

function notEqualToMethod (value, element, params) { 
		var r = true;
		
		var a = true;
		if (jQuery.isFunction(params.active))
			a = params.active(element);
		else
			a = params.active;
		
		//console.log("*active:" + a + "  notEqualTo params.ComparePropertyName" + params.ComparePropertyName + "  value:" + value + "  not value==>"+ $("[name=" + params.ComparePropertyName + "]").val());
		if (params.ComparePropertyName && a){		
			r = value != $("[name=" + params.ComparePropertyName + "]").val();	
		}
		
		return this.optional(element) || r; 

}



function futureDateMethod(value, element){
	var r = false;
	if (value.length > 0) {
		var d1 = new Date.parse(value);
		var d2 = Date.today();
		r = d1 > d2;
	} else {
		r = true;
	}
	return this.optional(element) || r;
}

function pastDateMethod(value, element){
	var r = false;
	if (value.length > 0) {
		var d1 = new Date.parse(value);
		var d2 = Date.today();
		r = d1 < d2;
	} else {
		r = true;
	}
	return this.optional(element) || r;
}

function notFutureDateMethod(value, element){
	var r = false;	
	if (value.length > 0) {
		var d1 = new Date.parse(value);
		var d2 = Date.today();
		r = d1 <= d2;
	} else {
		r = true;
	}
	return this.optional(element) || r;
}

function dateCompareMethod(value, element, params){
	var r = false;

	var a = true;
	if (jQuery.isFunction(params.active))
		a = params.active(element);
	else
		a = params.active;
	
	var skip = false;
	//console.log('------------- compare:' + value + ' and:' + params.date2);

	if (a && value.length > 0 && params.date2 && params.date2.length > 0) {
		
		// If the value passed in for date2 is not a date; try to look it up by name
		if (!isDate(params.date2)){
			var jquerySearchStr = 'input[name=' + params.date2 + ']';
			//console.log(jquerySearchStr + " : " + $(jquerySearchStr).val());
			if ($(jquerySearchStr) && $(jquerySearchStr).val() && $(jquerySearchStr).val().length > 0 && isDate($(jquerySearchStr).val())){
				var d2 = new Date.parse($(jquerySearchStr).val());
			} else {
				skip = true;
			}	
		} else {
			var d2 = new Date.parse(params.date2);
		}
		
		if (!skip && d2){
			var d1 = new Date.parse(value);
			var m = params.method;
			try {
				switch (m) {
					case "lt":
						r = d1.compareTo(d2) == -1;
						break;
					case "lte":
						r = d1.compareTo(d2) == -1 || d1.compareTo(d2) == 0;
						break;
					case "gt":
						r = d1.compareTo(d2) == 1;
						break;
					case "gte":
						r = d1.compareTo(d2) == 1 || d1.compareTo(d2) == 0;
						break;
					case "eq":
						r = d1.compareTo(d2) == 0;
						break;
					case "neq":
						r = d1.compareTo(d2) != 0;
						break;
					default:
						r = true;
				}
			} catch(e) {}
			//console.log("Is " + d1.toString("M/d/yyyy") + " " + m + " " + d2.toString("M/d/yyyy") + " - " + r);
		} else {
			
			r = true;
		}
	}
	else {
		r = true;
	}
	return this.optional(element) || r;
}


function valueCompareMethod(value, element, params){
	var r = false;
	var a = true;
	
	if (jQuery.isFunction(params.active))
		a = params.active(element);
	else
		a = params.active;
	
	var skip = false;
	var v1 = parseInt(trimNumber(value));
	//console.log("int value:" + v1);
	if (a && value.length > 0 && params.field2 && params.field2.length > 0) {
		var jquerySearchStr = 'input[name=' + params.field2 + ']';
	
		if ($(jquerySearchStr) && $(jquerySearchStr).val() && $(jquerySearchStr).val().length > 0){
			var v2 = parseInt($(jquerySearchStr).val());
		} else {
			skip = true;
		}	
		if (!skip){
			r = compareTwoValues(v1, v2, params.method);
		} else {
			r = true;
		}
	}
	else {
		r = true;
	}
	return this.optional(element) || r;
}

function compareTwoValues(v1, v2, m) {
	var r = true;
	//console.log("is " + v1 + " " + m + " " + v2 + "?");
	
	switch (m) {
		case "lt":
			r = v1 < v2;
			break;
		case "lte":
			r = v1 <= v2;
			break;
		case "gt":
			r = v1 > v2;
			break;
		case "gte":
			r = v1 >= v2;
			break;
		case "eq":
			r = v1 == v2;
			break;
		case "neq":
			r = v1 != v2;
			break;
	}
	//console.log("actual result:" + r);
	return r;	
}

/* :::::::::::::: LESS THAN AGE :::::::::::::: */
function lessThanAgeMethod(value, element, params){

	var r = false;
	
	var a = true;
	if (jQuery.isFunction(params.active))
		a = params.active(element);
	else
		a = params.active;
	
	if (a && value.length > 0 && params.age) {
		var d1 = new Date.parse(value);
		if (params.refdatefield)
		{
			try{
				var refdateval = $('input[name=' + params.refdatefield + ']').val();
			} catch(e){}
		}
			
		if (refdateval && isDate(refdateval))
			var d2 = new Date.parse(refdateval);
		else
			var d2 = new Date.today();
		
		if (d1.add(params.age).years() <= d2)
			r = false;
		else
			r=true;
	}
	return this.optional(element) || r;
}

/* :::::::::::::: GREATER THAN AGE :::::::::::::: */
function greaterThanAgeMethod(value, element, params){
	var r = false;
	
	var a = true;
	if (jQuery.isFunction(params.active))
		a = params.active(element);
	else
		a = params.active;
	
	if (a && value.length > 0 && params.age) {
		var d1 = new Date.parse(value);
		if (params.refdatefield)
		{
			try{
				var refdateval = $('input[name=' + params.refdatefield + ']').val();
			} catch(e){}
		}
			
		if (refdateval && isDate(refdateval))
			var d2 = new Date.parse(refdateval);
		else
			var d2 = new Date.today();
		
		if (d1.add(params.age).years() > d2)
			r = false;
		else
			r=true;
	}
	return this.optional(element) || r;
}


function mustbeifMethod(value, element, params){
	var r = true;
	var valueFound = false;
	var jquerySearchStr = "";
	var a = true;
	
	if (jQuery.isFunction(params.active))
		a = params.active(element);
	else
		a = params.active;
	
	if (a && params.method && params.method.length > 0 && params.field1 && params.value2 && params.mustbelist) {
		
		// Find Value in Form
		jquerySearchStr = 'select[name=' + params.field1 + ']';
		if ($(jquerySearchStr).length > 0){
			valueFound = true;
		} else {
			jquerySearchStr = 'input[name=' + params.field1 + ']';
			if ($(jquerySearchStr).length > 0){
				valueFound = true;
			}
		}
		
		//console.log("mustbeif: " + params.field1 + " - " + params.fieldtype + " - " + jquerySearchStr);

		if (valueFound) {
			
			if (params.fieldtype && params.fieldtype == 'string'){
				var v1 = $(jquerySearchStr).val();
				var v2 = params.value2;
			} else {
				var v1 = parseInt($(jquerySearchStr).val());
				var v2 = parseInt(params.value2);
			}
			
			var c = compareTwoValues(v1, v2, params.method);
			
			//console.log("mustbeif: " + params.field1 + " = " + v1 + " and " + v2 + " - " + params.method + " condition met: " + c + " list:" + params.mustbelist);
			
			if (c) {
				r = false;	
				//Condition Met
				var mblArray = params.mustbelist.split(",");
				for (var i = 0; i < mblArray.length; i++ ){
					//console.log('---> List Item:' + mblArray[i] + "  Value:" + value);
					if(mblArray[i] == ':null:' && value.length == 0){
						r = true;
						break;
					} else if (mblArray[i] == value){
						r = true;
						break;					
					}
				}
			}
		}
	}
	return r;
}


function mustnotbeifMethod(value, element, params){
	var r = true;
	var valueFound = false;
	var jquerySearchStr = "";
	
	var a = true;
	if (jQuery.isFunction(params.active))
		a = params.active(element);
	else
		a = params.active;
	
	if (a && params.method && params.method.length > 0 && params.field1 && params.value2 && params.mustnotbelist) {

		// Find Value in Form
		jquerySearchStr = 'select[name=' + params.field1 + ']';
		if ($(jquerySearchStr).length > 0){
			valueFound = true;
		} else {
			jquerySearchStr = 'input[name=' + params.field1 + ']';
			if ($(jquerySearchStr).length > 0){
				valueFound = true;
			}
		}
		//console.log("mustbeif: " + params.field1 + " - " + params.fieldtype + " - " + jquerySearchStr);
		
		if (valueFound) {
			
			if (params.fieldtype && params.fieldtype == 'string'){
				var v1 = $(jquerySearchStr).val();
				var v2 = params.value2;
			} else {
				var v1 = parseInt($(jquerySearchStr).val());
				var v2 = parseInt(params.value2);
			}
			
			//console.log("mustnotbeif: " + v1 + " - " + v2 + " - " + params.method);
			
			var c = compareTwoValues(v1, v2, params.method);
			//console.log("mustnotbeif: " + v1 + " - " + v2 + " - " + params.method + " = " + c);
			if (c) {
				//Condition Met
				var mblArray = params.mustnotbelist.split(",");
				for (var i = 0; i < mblArray.length; i++ ){
				  //console.log(mblArray[i]);
					if(mblArray[i] == ':null:' && value.length == 0){
						r = false;
						break;
					} else if (mblArray[i] == value){
						r = false;
						break;						
					}
				}
			}
		}
	}
	return r;
}

function mustnotbeMethod(value, element, params){
	var r = true;
	var a = true;
	if (jQuery.isFunction(params.active))
		a = params.active(element);
	else
		a = params.active;
	if (a && params.mustnotbelist) {
		var mblArray = params.mustnotbelist.split(",");
		for (var i = 0; i < mblArray.length; i++ ){
			if(mblArray[i] == ':null:' && value.length == 0){
				r = false;
				break;
			} else if (mblArray[i] == value){
				r = false;	
				break;						
			}
		}
	}
	return r;
}


function mustbeMethod(value, element, params){
	var r = true;
	var a = true;
	if (jQuery.isFunction(params.active))
		a = params.active(element);
	else
		a = params.active;

	if (a && params.mustbelist) {
		r = false;
		var mblArray = params.mustbelist.split(",");
		for (var i = 0; i < mblArray.length; i++ ){
			if(mblArray[i] == ':null:' && value.length == 0){
				r = true;
				break;
			} else if (mblArray[i] == value){
				r = true;
				break;					
			}
		}
	}
	return r;
}


/* UTILS */


function isDate(dateStr) {
	var datePat = /^(\d{1,2})(\/|-)(\d{1,2})(\/|-)(\d{4})$/;
	var matchArray = dateStr.match(datePat); // is the format ok?
	
	if (matchArray == null) {
	return false;
	}
	
	month = matchArray[1]; // p@rse date into variables
	day = matchArray[3];
	year = matchArray[5];
	
	if (month < 1 || month > 12) { // check month range
	return false;
	}
	
	if (day < 1 || day > 31) {
	return false;
	}
	
	if ((month==4 || month==6 || month==9 || month==11) && day==31) {
	return false;
	}
	
	if (month == 2) { // check for february 29th
	var isleap = (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));
	if (day > 29 || (day==29 && !isleap)) {
	return false;
	}
	}
	return true; // date is valid
}

function trimNumber(s) {
  while (s.substr(0,1) == '0' && s.length>1) { s = s.substr(1,9999); }
  return s;
}
