/**
 *  Form Validotor
 * This validator created for validation forms on some value:
 * 	Valid Phone
 * 	Valid EMail
 *	Valid Float
 *	Valid Integer
 *	Valid Date
 *	Valid Time
 *  Valid IP
 *  Valid URL
 *	Valid Selected Option
 *	Checked checkbox or radiobutton
 * 	Correct start and end date
 *	Correct start and end time
 *  @author Vlad Romanenko <vladam@users.sourceforge.net>
 *  @author Alexander Simonov <devil@gentoo.org.ua>
 *  @version 1.5
 */
 
/**
 * RegExp's for common validators
 */

/**
 * Valid phone is 
 */
var greValidPhone = /^\+?([\d ]*\([\d ]+\))?[\d ]+$/;
/*
 * Valid email like asimonov@hostopia.com may be root@localhost
 * Note: May be it must be all without @localhost ?
 * If yes then 
 * var greValidEmail = /^([a-z0-9_]|\\-|\\.)+@(([a-z0-9_]|\\-)+\\.)+[a-z]{2,4}$/;
 */
//var greValidEmail = /^\w+[\w\.\+\-]*\@\w+(\.[\w\-]+)*$/;
var greValidEmail = /^([a-z0-9_]|\-|\.)+@(([a-z0-9_]|\-)+\.)+[a-z]{2,4}$/;

/**
 * Valid Float is -1.4 or 1,6 
 */
var greValidFloat = /^-?\d*[\.,]?\d*$/;

/**
 * Valid Integer is -12 or 234
 */
/*
var greValidInteger = /^-?\d*$/;
*/
var greValidInteger = /^\d{1,}$/;

/**
 * Valid Date like 2004-12-01 or 2004-09-3 or 2004-9-17
 */
var greValidDate = /^20[0-4][0-9](\-|\/|\.)(0[1-9]|[1-9]|1[0-2])\1([1-9]|0[1-9]|[1-2][0-9]|3[0-1])$/;
/**
 *  Valid time like 9:46 or 12:59 without PM or AM
 */
var greValidTime = /^([1-9]|1[0-2]):[0-5]\d$/;

/**
 * Valid IP adress like 192.168.1.10 or 212.1.67.18
 */
 
var greValidIP = /^([1-9]|0[1-9]|[1-9][0-9]|00[1-9]|0[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-4])\.\1\.\1\.\1$/;

/**
 * Valid URL
 */
 
var greURL = /^http:\/\/.{3,}$/;


/**
 * Helper form validation function.
 * @usage <form onsubmit="return FormValidate(this, validationRules);">
 * @param validationRules Sample code:
 * var validationRules = [
 *	{field: "phone", validator: new RequiredValidator(),
 *		msg: "Please, fill out your phone number"},
 *	{...}
 * ];
 */
function FormValidate(form, validationRules) {

	for( var i = 0; i < validationRules.length; i++ ) {
		var rule = validationRules[i];
		if( !(rule instanceof Object) )
			continue;

		var field = form.elements[rule.field];

		try {
			if( !rule.validator.IsValid(field.value) ) {
				if( field.select ) { field.select(); }
				if( field.focus  ) { field.focus();  }
				alert(rule.msg);
				return false;
			}
		} catch( e ) {
			alert("Bad validator call for field '"+rule.field+"':\n" + e);
			return false;
		}
	}
	return true;
}

/**
 * Base validation object, describes Validator interface.
 */
function Validator() {

	this.IsValid = function(value) {
	}
}

/**
 * Non-empty value validator.
 * Note that other validators allow empty values and return true.
 * Should we trim white space before validation?
 */
function RequiredValidator() {

	this.IsValid = function(value) {

		return (value != "");
	}
}

RequiredValidator.prototype = new Validator();

/**
 * Regular expression validator.
 */
function RegExpValidator(re) {

	this.re = re;

	this.IsValid = function(value) {

		if( value == "" ) {
			return true;
		} else {
			return this.re.test(value);
		}
	}
}

RegExpValidator.prototype = new Validator();

/**
 * Email validator.
 */
function EmailValidator() {

	this.base = RegExpValidator;
	this.base(greValidEmail);
}

EmailValidator.prototype = new RegExpValidator();

/**
 * Phone number validator.
 */
function PhoneValidator() {

	this.base = RegExpValidator;
	this.base(greValidPhone);
}

PhoneValidator.prototype = new RegExpValidator();

/**
 * Float number validator.
 */
function FloatValidator() {

	this.base = RegExpValidator;
	this.base(greValidFloat);
}

FloatValidator.prototype = new RegExpValidator();

/**
 * Date validator.
 */
function DateValidator() {

	this.base = RegExpValidator;
	this.base(greValidDate);
}

DateValidator.prototype = new RegExpValidator();
/**
 * Time validator.
 */
function TimeValidator() {

	this.base = RegExpValidator;
	this.base(greValidTime);
}

TimeValidator.prototype = new RegExpValidator();

/**
 * IP adress validator.
 */
function IPAdressValidator() {

	this.base = RegExpValidator;
	this.base(greValidIP);
}
IPAdressValidator.prototype = new RegExpValidator();

/**
 * HTTP URL validator.
 */
function URLValidator() {

	this.base = RegExpValidator;
	this.base(greURL);
}

URLValidator.prototype = new RegExpValidator();

/**
 * Compare validator.
 * Compares value to other controls value.
 * Is valid when values are equal.
 */
function CompareValidator(controlToCompare) {

	this.controlToCompare = controlToCompare;

	this.IsValid = function(value) {

		return (value == this.GetValueToCompare());
	}

	this.GetValueToCompare = function() {

		var control = document.getElementById(this.controlToCompare);
		if( typeof(control) == 'undefined' )
			throw "Control '"+this.controlToCompare+"' not found";
		return control.value;
	}
}

CompareValidator.prototype = new Validator();

/**
* Checkbox and Radiobutton validator 
* @param id of element
*/
function CheckBoxValidator(element_name) {
	
	this.element_name = element_name;
	
	this.IsValid = function(value) {
		return ( value == this.GetValueToCheck());
	}
	
	this.GetValueToCheck = function() {
		var checkbox_obj = document.getElementById(this.element_name);
		if (checkbox_obj.checked) {
			return false;
		}
		return checkbox_obj.value;
	}
	
}

CheckBoxValidator.prototype = new Validator();


/**
* Select Option validator 
* first option is not valid string like "Choose ....."
*/
function SelectOptionValidator(element_name) {
	
	this.element_name = element_name;
	
	this.IsValid = function(value) {
		return ( value == this.GetValueToSelect() );
	}
	
	this.GetValueToSelect = function() {
		var select_obj = document.getElementById(this.element_name);
		if ( select_obj.selectedIndex == 0) {
			return false;
		}
		return select_obj.value;
	}
}

SelectOptionValidator.prototype = new Validator();

/**
* Check correct start and end date
* start_date is a date string like YYYY-MM-DD or YYYY-M-D
*/
function CorrectDateValidator(start_date,end_date)
{
	/**
	 * Variables
	 */
	this.start_date = start_date;
	this.end_date = end_date;
	
	this.IsValid = function() {
		return (this.CheckValues())
	}
	
	this.CheckValues = function() {
		/**
		 * Getting variables objects
		 */
		var start_date_obj = document.getElementById(this.start_date);
		var end_date_obj = document.getElementById(this.end_date);
		/**
		 * Getting variables values
		 */
		var start_date_string = new String(start_date_obj.value).split('-');
		var end_date_string = new String(end_date_obj.value).split('-');
		var start_year = start_date_string[0];
		var end_year = end_date_string[0];
		var start_month = start_date_string[1];
		var end_month = end_date_string[1];
		var start_day = start_date_string[2];
		var end_day = end_date_string[2];
		/**
		   *if month is a single char when converting to two chars
		   */
		start_month = ( start_month > 9 ? start_month : "0" + start_month );
		/**
		   *if month is a single char when converting to two chars
		   */
		end_month = ( end_month > 9 ? end_month : "0" + end_month );
		/**
		   *if day is a single char when converting to two chars
		   */
		start_day = ( start_day > 9 ? start_day : "0" + start_day );
		/**
		   *if day is a single char when converting to two chars
		   */
		end_day = ( end_day > 9 ? end_day : "0" + end_day );
		/**
		 * start year must be not lesser end year
		 */
		if (start_year <= end_year ) {
			/**
			 * if it is one year
			 */
			if ( start_year == end_year ) {
				/*
			 	* if it is one month
			 	*/
				if ( start_month == end_month ) {
					/*
				 	* start day must be lesser end day
				 	*/
					if ( start_day == end_day || start_day > end_day ) { 
						return false;
					}
				}
				/**
				 * if start month more whan end
				 */
				if ( start_month > end_month ) {
					return false;
				}
			}
		}
		/**
		 * If start year more than end
		 */
		else {
			return false;
		}
		return true;
	}
}
CorrectDateValidator.prototype = new Validator();

/**
 * Check correct start and end time
 * There parametres - is a id value of hours
 * hour may be one or two chars
 * mins MUST be TWO chars value
 */
function CorrectTimeValidator(start_hour,end_hour,start_min,end_min,start_am,end_am)
{
	/**
	 * Variables
	 */
	this.start_hour = start_hour;
	this.end_hour = end_hour;
	this.start_min = start_min;
	this.end_min = end_min;
	this.start_am = start_am;
	this.end_am = end_am;
	
	this.IsValid = function() {
		return (this.CheckValues())
	}
	
	this.CheckValues = function() {
		/**
		 * Get the variables objects
		 */
		var start_hour_obj = document.getElementById(this.start_hour);
		var end_hour_obj = document.getElementById(this.end_hour);
		var start_min_obj = document.getElementById(this.start_min);
		var end_min_obj = document.getElementById(this.end_min);
		var start_am_obj = document.getElementById(this.start_am);
		var end_am_obj = document.getElementById(this.end_am);
		/**
		 * Get the variables value
		 */
		var start_hour_value = start_hour_obj.options[start_hour_obj.selectedIndex].value;
		var end_hour_value = end_hour_obj.options[end_hour_obj.selectedIndex].value;
		var start_min_value = start_min_obj.options[start_min_obj.selectedIndex].value;
		var end_min_value = end_min_obj.options[end_min_obj.selectedIndex].value;
		/**
		 * If it is Post Meridian time
		 */
		if (start_am_obj.checked) {
			start_hour_value += 12;
		}
		if (end_am_obj.checked) {
			end_hour_value += 12;
		}
		/**
		 * if value is single char then converting to two chars
		 */
		start_hour_value = ( start_hour_value > 9 ? start_hour_value : "0" + start_hour_value );
		/**
		 * if value is single char then converting to two chars
		 */
		end_hour_value = ( end_hour_value > 9 ? end_hour_value : "0" + end_hour_value );
		/**
		 * End hour must be more then start hour
		 */
		if ( start_hour_value > end_hour_value ) {
					return false;
		}
		else {
			/**
			 * If start and end hourse is one value
			 */
			if ( start_hour_value == end_hour_value ) {
				/**
				 * If start min and end min is one value or start min more than end
				 */
				if (start_min_value == end_min_value || start_min_value > end_min_value ) {
					return false;
				}
			}
		}
		return true;
	}
}
CorrectTimeValidator.prototype = new Validator();

