/**
    jQuery plugin
	jx.validate
    
	@author: faeb187
*/
( function( $ ){

	$.fn.validate = function( opt ){
		
		var $self = $( this );
		
		opt = opt || {};
		
		//field validation
		switch( $self[ 0 ].tagName ){
            
            case "INPUT":
            case "SELECT":
            case "TEXTAREA": return fieldValid( $self );
		
    		case "FORM": return formValid( $self );
		
		    default: return false;
		}
		
		/**
			validates form field
			@author: faeb187
		*/
		function fieldValid( $fld, $frm ){
				
			//input < minlength
			if( $fld.val().length < $fld.attr( 'minlength' ) ){ error( $fld ); return false; }
            
			//field must be a number
			if( $fld.hasClass( 'number' ) && !isNumber( $fld.val() ) ){ error( $fld ); return false; }
            
			//field is a zip (fill cities)
			if( $fld.hasClass( "zip" ) && $fld.attr( 'fill' ) ){
				
				$fill = $( '#' + $fld.attr( 'fill' ) );
				$fill.val( Zip[ $fld.val() ] || $fill.val() );
			}
				
			//field must be an email address
			if( $fld.hasClass( "email" ) && !isEmail( $fld.val() ) ){ error( $fld ); return false; }
            
			//field must be a date
			if( $fld.hasClass( "date" ) && !isDate( $fld.val() ) ){ error( $fld ); return false; }
            
			//field must be a password
			if( $fld.hasClass( "password" ) || $fld.hasClass( "password2" ) ){
				
				var compare = $fld.attr( 'compare' );
				
				//compare passwords (second password field)
				if( compare && !isPassword2( $fld.val(), $( "#" + compare ).val() ) ){ error( $fld ); return false; }
                
				//password field (check strength)
				else if( !isPassword( $fld.val() ) ){ error( $fld ); return false; }
			}
			//field requires remote validation
			if( $fld.attr( 'remote' ) ){
				
				//workaround for async: false
				//to avoid undefined returns
				return ( function(){
					
					var valid = false;
					
					$.ajax({
				
						url: $fld.attr( 'remote' ),
						data: { val: $fld.val() },
						success: function( res ){
							
							if( !res ) error( $fld );
                            
                            //remove error
							else {
                                
                                var $err = $( '#validate_err_' + $fld.attr( 'id' ) );
								
								$err.fadeOut( "fast", function(){ $err.remove(); });
								valid = true;
							}
						},
						async: false
					});
					return valid;
				})();
			}
            
            //group of radio buttons
            if( $fld.attr( 'type' ) == "radio" )
                
                if( !$( 'input[name=' + $fld.attr( 'name' ) + ']:checked', $frm ).length ){ error( $fld ); return false; }
            
			//field is valid
			if( !$fld.attr( 'remote' ) ){
                
                var $err = $( '#validate_err_' + $fld.attr( 'id' ) );
				
                //remove error
				$err.fadeOut( "fast", function(){ $err.remove(); });
                
				return true;
			}
		}
		
		/**
			validates form
			@author: faeb187
		*/
		function formValid( $frm ){
			
			var valid = true;
			
			//check fields
			$( '.required', $frm ).each( function(){
				
				//field not valid
				if( !fieldValid( $( this ), $frm ) )
					valid = false;
			});
			return valid;
		}
		
		/**
			displays error
			@author: faeb187
		*/
		function error( $fld ){
		
			var err = $fld.attr( "err" );
			
			if( !err ) return;
            
            var id = "validate_err_" + $fld.attr( 'id' ),
            	left = opt.error && opt.error.left ? opt.error.left : null,
            	right = opt.error && opt.error.right ? opt.error.right : null,
            	top = opt.error && opt.error.top ? opt.error.top : null,
            	bottom = opt.error && opt.error.bottom ? opt.error.bottom : null;
            
            //error already active
            if( $( '#' + id )[ 0 ] ) return;
            
            var $err = $( '<div/>',{ id: id, 'class': "validate_err" }).hide();
            
            //position of error (todo make this better)
            if( !left && !right ) $err.css( "left", $fld.offset().left + parseInt( $fld.css( 'width' ) ) );
            else {
            
            	if( left ) $err.css( "left", left );
            	if( right ) $err.css( "right", right );
            }
            if( !top && !bottom ) $err.css( "top", $fld.offset().top - 4 );
            else {
            
            	if( top ) $err.css( "top", top );
            	if( bottom ) $err.css( "bottom", bottom );
           	}
            
            //append error to body
            $( 'body' ).append( $err.text( err ) );
            
            //fadeIn error
            $err.fadeIn( "fast" );
		}
		
		/**
			validation functions
			@author: faeb187
		*/
		function isNumber( val ){ return ( val - 0 ) == val && val.length > 0; }
		function isEmail( val ){ return val.search( /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/ ) != -1; }
		function isDate( val ){ return val.search( /^\d\d\.\d\d\.\d\d\d\d/ ) != -1; }
		function isPassword( val ){ return true; }
		function isPassword2( val2, val ){ return val2 === val; }
	};
})( jQuery );
