/*																																										*/
if( typeof pln == 'undefined' || typeof nvi == 'undefined' ){

	/**
	 @requires pln.js
	 @description if not found, alert the developers and do nothing;
	*/
	if( typeof pln == 'undefined' ) alert( "This file required the PLN Javascript Library ( pln.js ) and it need to be loaded before this file." );
	if( typeof nvi == 'undefined' ) alert( "This file required the NVI CORE ( nvi.core.js ) and it need to be loaded before this file." );

}else{



	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	/**
	 @name 			Input Validation Class
	 @version		1.00
	*/
	function class_nvi_input_validation( id , errorMessage , validationFunction ){
		
		var _validationId = id ;
		var _errorMessage = errorMessage ;
		var _validationFunction = validationFunction ;
		
		if( !pln.isString( _validationId ) ){
			return nvi.logManager.log( 'The unique id that should be use for this instance of the input validation is undefined or not a String' , 'Error' , 'class_nvi_input_validation' , ' ' );
		}
		if( !pln.isFunction( _validationFunction ) ){
			return nvi.logManager.log( 'The validation function used for this instance ( ' + _validationId + ' ) of the input validation class object is undefined or not a function' , 'Error' , 'class_nvi_input_validation' , ' ' );
		}
		
		//this.__constructor = function(){}
		
		this.toString = function(){ return "Nvi Input Validation Class" ; }

		/**
		 @public
		 @description	Public pointer to the validationFunction
		 @return		Boolean ; True if the validation was successfull, else false
		*/		
		this.validate = _validationFunction ;

		/**
		 @public
		 @description	Return the id of this validation object, this is usefull if you want to remove a validation object from an input instance
		 @return		String ; Return the validation id of this validation object
		*/
		this.getId = function(){
			return _validationId ;
		}

		/**
		 @public
		 @description	Return the error message passed by the user to the constructor
		 @return		String ; Return the error message of this validation object
		*/
		this.getErrorMessage = function(){
			return _errorMessage ;
		}	

	}

	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	//
	// Constant Validation Function Library

	// Required
	// Validate if the value is not empty
	class_nvi_input_validation.__required = function(){
		return function( value ){
			return !pln.isEmpty( value ) ;
		}
	}
	
	// Integer
	// Validate if the value is an Integer
	class_nvi_input_validation.__integer = function(){
		return function( value ){
			// We consider that if the element value is empty, we do not need to 
			// validate it. An error will be raised if the input have a required 
			// validation object, so we dont care about an empty value here.
			if( pln.isEmpty( value ) ) return true ; 
			return value.match( /^(-|\+)?\d+$/gi ) != null ;
		}
	}
	
	// Float
	// Validate if the value is an Float
	class_nvi_input_validation.__float = function(){
		return function( value ){
			// We consider that if the element value is empty, we do not need to 
			// validate it. An error will be raised if the input have a required 
			// validation object, so we dont care about an empty value here.
			if( pln.isEmpty( value ) ) return true ; 
			return value.match( /^(-|\+)?\d+\.?\d+$/gi ) != null ;
		}
	}	
	
	// Date
	// Validate if the value is a Date an formatted in the proper date format
	class_nvi_input_validation.__date = function( dateFormat ){
		
		var _dateFormat = pln.isString( dateFormat ) ? dateFormat : 'mm/dd/yyyy' ;
		var _indexes = { day : null , month : null , year : null } ;
		
		var _regexp = {
			day : null ,
			month : null ,
			year : null ,
			format_separator : /[^a-z]/gi ,
			integer_separator : /[^\d|-]/gi ,
			compiled : ''
		}
		
		var elementCollection = _dateFormat.split( _regexp.format_separator ) ;	
		var separatorCollection = _dateFormat.match( _regexp.format_separator ) ;		
		for( var i = 0 ; i < elementCollection.length ; i++ ){

			var currentSchema = elementCollection[ i ] ;
			var limit = currentSchema.split( '' ).length ;
			
			_regexp.day = new RegExp( '^[d|j]{' +limit+ '}$' , 'gi' ) ;
			_regexp.month = new RegExp( '^[m]{' +limit+ '}$' , 'gi' ) ;
			_regexp.year = new RegExp( '^[y|a]{' +limit+ '}$' , 'gi' ) ;
			
			var isDay = _regexp.day.test( currentSchema ) ;
			var isMonth = _regexp.month.test( currentSchema ) ;
			var isYear = _regexp.year.test( currentSchema ) ;
			
			if( isDay ) _indexes.day = i ;
			if( isMonth ) _indexes.month = i ;
			if( isYear ) _indexes.year = i ;
			
			var separator = separatorCollection[ i ] ;
			if( typeof separator != 'undefined' ){
				separator = separator.replace( '/' , '\/' ) ;
				separator = separator.replace( '.' , '\.' ) ;
				
			}else{
				separator = '' ;
			}
			if( isYear ) _regexp.compiled += "(-?\\d{1,4})" ;
			if( isMonth ) _regexp.compiled += "([0-9]|[0][0-9]|[1][012])" ;
			if( isDay ) _regexp.compiled += "([0-9]|[0][0-9]|[1|2][0-9]|[3][01])" ;
			_regexp.compiled += separator ;
		}

		_regexp.compiled = new RegExp( '^' + _regexp.compiled + '$' , 'gi' ) ;
		
		return function( value ){
			if( pln.isEmpty( value ) ) return true ;
			if( _regexp.compiled.test( value ) ){
				var year = Number( value.split( _regexp.integer_separator )[ _indexes.year ] ) ;
				var month = Number( value.split( _regexp.integer_separator )[ _indexes.month ] ) - 1 ;
				var day = Number( value.split( _regexp.integer_separator )[ _indexes.day ] ) ;
				if( year == 0 || month == 0 || day == 0 ) return false ;
				var dayLimit = 32 - new Date( year , month , 32 ).getDate() ;
				if( day > dayLimit ) return false ;
			}else{
				return false ;
			}
			return true ;
		}
	}
	
	// Url
	// Validate if the value is valid url
	class_nvi_input_validation.__url = function(){
		return function( value ){
			// We consider that if the element value is empty, we do not need to 
			// validate it. An error will be raised if the input have a required 
			// validation object, so we dont care about an empty value here.
			if( pln.isEmpty( value ) ) return true ; 		
			return value.match( /^((file|ftp|https?):\/\/)?[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&amp;:\/~\+#]*[\w\-\@?^=%&amp;\/~\+#]){1,}$/gi ) !=null ;
		}
	}
	
	// Email
	// Validate if the value is valid email address
	class_nvi_input_validation.__email = function(){
		return function( value ){
			// We consider that if the element value is empty, we do not need to 
			// validate it. An error will be raised if the input have a required 
			// validation object, so we dont care about an empty value here.
			if( pln.isEmpty( value ) ) return true ; 		
			return value.match( /^([\w-]+)(\.[\w-]+)*@([a-z\d-]+)(\.[a-z\d-]+)*(\.[a-z]{2,4})$/gi ) != null ;
		}
	}
	
	// Match
	// Validate if the value of two input match
	class_nvi_input_validation.__match = function( inputId ){
		var _inputId = pln.isString( inputId ) ? inputId : null ;
		return function( value ){
			// We consider that if the element value is empty, we do not need to 
			// validate it. An error will be raised if the input have a required 
			// validation object, so we dont care about an empty value here.
			if( pln.isEmpty( value ) ) return true ; 		
			var element = pln.node.getById( _inputId ) ;
			if( pln.isHtmlElement( element ) ){
				var valueToMatch = element.value ;
				if( pln.isset( valueToMatch ) && value == valueToMatch ) return true ;
			}
			return false ;
		}
	}
	
	// Range
	// Validate if the value is in range with the limits defined by the user
	class_nvi_input_validation.__range = function( minimumLimit , maximumLimit ){
		var _minimumLimit = pln.isNumber( minimumLimit ) ? minimumLimit : null ;
		var _maximumLimit = pln.isNumber( maximumLimit ) ? maximumLimit : null ;
		return function( value ){
			// We consider that if the element value is empty, we do not need to 
			// validate it. An error will be raised if the input have a required 
			// validation object, so we dont care about an empty value here.
			if( pln.isEmpty( value ) ) return true ; 		
			if( pln.isNumber( _minimumLimit ) && pln.isNumber( _maximumLimit ) ){
				var value = pln.isNumber( value )? value : pln.isString( value ) ? Number( value ) : null ;
				if( pln.isNumber( value ) && value >= _minimumLimit && value <= _maximumLimit ) return true ;
			}
			return false ;
		}
	}

	
	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////	
}


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/*

	Exemple of custom validation function

	This is how a validation should be. If a validation function is used without 
	using the outer/inner function model, i will probably not work ( Unless the validation 
	function is not executed and is only the pointer to the validation function 
	used ex: myFunction will work, 	myFunction() will not work ).

	1) The outer function should always return a function
	2) The inner validation function should always return a boolean, true or false
	
	function myValidationFunction( param1 , param2 , etc ){
	
		var _param1 = param1 ;
		var _param2 = param2 ;
	
		return function( inputId ){
			
			if( _param1 == _param2 ) return true ;
			return false ;
			
		}
	
	}


*/