$extend( FY.FormTools, {

	_invalidFields: [],
	_inlineRequired: true,
	
	initValidationHint: function( data )
	{
		var $field = $( data.field );
		var $hint = $( data.field + '_hint' );
		var defaultValue = '(required)';
		
		if ( !$field )
			return;
		
		// Add inline required
		if ( FY.FormTools._inlineRequired ) {
			$field.value = defaultValue;
			$field.setStyle( 'color', '#999999' );
		}
			
		// Style changes
		var switchToError = function() {
		
			if ( !$hint )
				return;
		
			$hint.removeClass( 'suggestion' ).removeClass( 'valid' ).addClass( 'error' ).set( 'html', data.errorMsg ).show();
		};
		
		var switchToSuggestion = function() {
		
			if ( !$hint )
				return;
		
			if ( data.hintMsg )
				$hint.removeClass( 'error' ).removeClass( 'valid' ).addClass( 'suggestion' ).set( 'html', data.hintMsg ).show();
			else
				$hint.hide();
		};
		
		var switchToValid = function() {
		
			if ( !$hint )
				return;
		
			$hint.removeClass( 'error' ).removeClass( 'suggestion' ).addClass( 'valid' ).set( 'html', '' ).show();
		};
		
		// Invalid fields
		var addInvalidField = function() {		
			if ( !this._invalidFields.contains( data.field ) )
				this._invalidFields.push( data.field );
				
		}.bind( this );
		
		var removeInvalidField = function() {
			if ( this._invalidFields.contains( data.field ) )
				this._invalidFields.erase( data.field );
			
		}.bind( this );
		
		// Generic focus event
		$field.addEvent( 'focus', function() {
				
			if ( data.hint )
				$hint.show();
			
			if ( $field.value != defaultValue )
				return;
				
			$field.value = '';
							
			$field.setStyle( 'color', '#4D4D4D' );
				
    	}.bind( this ) );
		
		// Other events
		switch( data.type )
		{
			/* Length */
			case 'length':
			
				$field.addEvents({
    				
    				'blur': ( function() {
    					if ( defaultValue && $field.value == defaultValue )
    					{
    						switchToError();
    						addInvalidField();
       						$hint.show();
    					}
      					else if ( !$field.value.length && !data.notRequired ) {
    						switchToError();
    						addInvalidField();
       						$hint.show();
       						
       						$field.value = defaultValue;
							$field.setStyle( 'color', '#999999' );
							
       					} else if ( $field.value.length && $field.value != defaultValue ) {
       						removeInvalidField();
       						switchToValid();
       					} else {
       						switchToSuggestion();
       					}
       					
    				}.bind( this ) )
    				
				}, this );
				
			break;
			
			/* Numeric */
			case 'numeric':
			
				$field.addEvents({
    				
    				'blur': ( function() {
						if ( defaultValue && $field.value == defaultValue )
    					{
    						switchToError();
    						addInvalidField();
       						$hint.show();
    					}
      					else if ( $field.value.length > 0 && !/^ *[0-9]+ *$/.test( $field.value ) ) {
    						switchToError();
    						addInvalidField();
    						$hint.show();
    						
    					} else if ( !$field.value.length && !data.notRequired ) {
    						switchToError();
    						addInvalidField();
       						$hint.show();
       						
       						$field.value = defaultValue;
							$field.setStyle( 'color', '#999999' );
       						
       					} else if ( $field.value.length ) {
       						removeInvalidField();
       						switchToValid();
       					} else {
       						switchToSuggestion();
       					}
       					
    				}.bind( this ) )
    				
				}, this );
				
			break;
			
			/* DOB */
			case 'dob':
			
				$field.addEvents({
    				
    				'blur': ( function() {
    				    if ( defaultValue && $field.value == defaultValue )
    					{
    						switchToError();
    						addInvalidField();
       						$hint.show();
    					}
      					else if ( $field.value.length > 0 && !$field.value.match( /(0[1-9]|[12][0-9]|3[01])[- /.](0[1-9]|1[012])[- /.](19|20)\d\d/ ) ) {
    						switchToError();
    						addInvalidField();
       						$hint.show();
       						
       					} else if ( !$field.value.length && !data.notRequired ) {
    						switchToError();
    						addInvalidField();
       						$hint.show();
       						
       						$field.value = defaultValue;
							$field.setStyle( 'color', '#999999' );
       						
     					} else if ( $field.value.length ) {
       						removeInvalidField();
       						switchToValid();
       					} else {
       						switchToSuggestion();
       					}
       					
    				}.bind( this ) )
    				
				}, this );
				
			break;
		
			/* Email */
			case 'email':
			
				$field.addEvents({
    				
    				'blur': ( function() {
    					if ( defaultValue && $field.value == defaultValue )
    					{
    						switchToError();
    						addInvalidField();
       						$hint.show();
    					}
      					else if ( $field.value.length > 0 && !/^[\w\-]+(\.[\w\-]+)*@[\w\-]+\.([\w\-]+\.)*[a-z]{2,}$/i.test( $field.value ) ) {
    						switchToError();
    						addInvalidField();
       						$hint.show();
       						
       					} else if ( !$field.value.length && !data.notRequired ) {
    						switchToError();
    						addInvalidField();
       						$hint.show();
       						
       						$field.value = defaultValue;
							$field.setStyle( 'color', '#999999' );
       						
     					} else if ( $field.value.length ) {
       						removeInvalidField();
       						switchToValid();
       					} else {
       						switchToSuggestion();
       					}
       					
    				}.bind( this ) )
    				
				}, this );
				
			break;
		
			default:
			
				$field.addEvents({
    				
    				'blur': ( function() {
      					$hint.hide();
      					
    				}.bind( this ) )
    				
				}, this );
			
			break;
		
		}
		
		return $field;
	
	}

});