;(function($) {
	 
	$.fn.extend({
		YggdrasilValidation: function(options, callBack) {
			
			return this.each(function() {
				if (typeof options == "string") {
					/*
					var sort = $.data(this, "sortable");
					if (sort) sort[options].apply(sort, args);
					*/
					alert('Csak obj -ot adhatsz meg confignak!!!!!!!!');
				} else {
					new $.YggdrasilValidationCore(this, options, callBack);
				
				}
			});		
		}
	});
	
	
	
	$.YggdrasilValidationCore = function(element, options , callBack ) {
		//Initialize needed constants
		var self = this;		
		this.element = $(element);
		this.options = $.extend({}, options);
		
		this.formId = this.element.attr('id');
		this.filedType = '';
		
		this.fieldData=[];
		this.data={};
		
		this.callBack=callBack;
				
		
		var o = this.options;
		$.extend(o, {
			
			/*** Debug options ***/
			debug: this.options.debug || false,
			debugType: this.options.debugType ||'console',
			debugLevel: this.options.debugLevel || 1,
			debugTagId: this.options.debugTagId || '#jsDebug',
			
			/*** Get/send validation data options ***/
			validateUrl: this.options.validateUrl ||'/validation',
			validString: this.options.validString ||'isValid',
			postDataPrefix: this.options.postDataPrefix ||'data',
			
			/*** Error Display options ***/
			validFailedDisplayType: this.options.validFailedDisplayType || 'class_text',
			validFailedClass: this.options.validFailedClass || 'yggdrasil_valid_failed',				
			validFailedClassText: this.options.validFailedClassText || 'yggdrasil_valid_failed_text',				
			validFailedSpanPrefix: this.options.validFailedSpanPrefix || 'span_',	
			validFailedOterContener: this.options.validFailedOterContener || $('p.error')			
		});
		
			
		this.setFiledType( this.formId );
		
			
		self.log('bindEvent: submit:#' +  self.formId, 2 );
		
		this.element.bind('submit', function(event){
			
			
			self.clearFailedValidation();
			
			self.getFormData();
		
			if( self.fieldData.length < 1){
				self.log('kitoltetlen form' , 3 );
			}
			else{
				self.sendValidation( event );
			}
			return false;
		});
		
	};
	
	
	
	$.extend($.YggdrasilValidationCore.prototype, {
		
				
		setFiledType: function( formId ){
			
			this.log('setFiledType: ' +  this.formId, 2 );
			
			this.filedType=formId;
			
			this.log('filedType:' +  this.filedType );
			
			return this.filedType;
		},
				
		getFormData: function(){
			this.log( 'getFormData' , 2);
			_self=this;
			data=new Array();
			logText= new String( "formData:\n" );
			
			this.element.find(':input').not(':disabled').each(function(i){
				
				field=$(this);
				fieldName=field.attr('name');
				fieldType=field.attr('type');
								
				if( fieldType != 'submit' ){
				 
					switch( fieldType ){
						
						case 'radio':
						case 'checkbox':
							
							if( field.attr('checked') == true ){
								fieldValue=_self.getFieldData(field);
							}
							
						break;
						
						default:
							fieldValue=_self.getFieldData(field);
						break;
					}
					
					convertName= _self.fieldNameConvert( fieldName )
					logText+= convertName  + ' => "' + fieldValue + '" ' + "\n";
					
					data.push({name: convertName, value:fieldValue });
				}
			});
			_self.log( logText );
			this.fieldData=data;
			return this.fieldData;
						
		},
		
		getFieldData: function( field ){
			return $.trim( field.val() );	
		},
		
		fieldNameConvert: function( fieldName ){
			brakePoint=fieldName.indexOf('[');
			if( brakePoint > 0 ){
				baseName=fieldName.substring(0, brakePoint );
				outherName=fieldName.substring( brakePoint, fieldName.length);
			}
			else{
				baseName=fieldName;
				outherName='';
			}
			
			convertName= this.options.postDataPrefix + '[' + baseName + ']' + outherName;
			this.log( 'fieldNameConvert:' + fieldName + '=>' + convertName );
			return convertName;
		},
		
		
		sendValidation: function( event ){
			this.log('send validation: #' +this.formId, 2 );
			_self=this;
			var data = this.fieldData;
			data.push({name: 'type', value: this.filedType });
			
			$.post( this.options.validateUrl, data, function( res ){
				//$('#jsDebug').prepend(res);
				if( _self.isValidationFailed(res) ){
					_self.displayFailedValidation(res);
				}
				else{
					_self.sendValidForm( event );
				}
				    
			},'json'); 
		},
		
		isValidationFailed: function( res ){

			if( typeof res =='object' && res[ this.options.validString ] === true  ){
				this.log( '#' + this.formId + ' form is valid ' , 2 );
				return false;
			}
			else if( typeof res =='object' && res[ this.options.validString ] === false ){
				alert( 'Validation Faild!' );
				return false;
			}
			else{
				this.log( '#' + this.formId + ' form is not valid ' , 3 );
				return true;
			}
		},
		
		displayFailedValidation: function( res ){
			this.log('displayFailedValidation', 2 );
			_self=this;
			errorFiledNames = new Array();
			logText=new String( "errorText:\n" );
			
			
			
			for( i in res ){
				errorFiledNames.push(i)
				logText+= i + ' => ' + res[i] + "\n";
			}
			
			this.log( logText );
			
			this.element.find(':input').filter(":enabled").each(function(i){
				
				field=$(this);
				fieldName=field.attr('name');
				
				if( $.inArray(fieldName, errorFiledNames ) > -1 ){
					
					switch( _self.options.validFailedDisplayType ){
						
						case 'text':
							_self.displayFailedValidationText( field, res[fieldName] );
						break;
						
						case 'class':
							_self.displayFailedValidationClass( field );
						break;
						
						case 'class_outer' :
							_self.displayFailedValidationClass( field );
							_self.displayFailedValidationOuter( res[fieldName] + "<br />" );
						break;
						
						case 'class_text':
						default:
							_self.displayFailedValidationClass( field );
							_self.displayFailedValidationText( field, res[fieldName] );
						break;
					}
				}
			});	
		},
		
		
		displayFailedValidationText: function( field, text ){
			
			str='<span class="' + this.options.validFailedClassText + '" id="'+ this.options.validFailedSpanPrefix + field.attr('id') +'" >'+text+"</span>";
			field.after( str );
		},
		
		displayFailedValidationClass: function( field ){
			field.addClass( this.options.validFailedClass );
		},
		
		displayFailedValidationOuter: function( text ){
			_self.options.validFailedOterContener.append( text );
		},
		
		clearFailedValidation: function(  ){
			this.log( 'clearFailedValidation', 2 );
			this.element.find('.' + this.options.validFailedClass ).removeClass( this.options.validFailedClass );
			this.element.find('.' + this.options.validFailedClassText ).remove();
			this.options.validFailedOterContener.empty();	
		},
		
		sendValidForm: function( event ){
			
			if( typeof this.callBack == 'function' ){
				this.callBack( event, this );
				//this.callBack.call( this );
			}
			else{
			
				this.element.unbind('submit');
				this.element.submit();		
			}
		},
		
/*************************************************************/		
		/**** LOGS ****/
		
		log: function( text , level ){
			
			if(!level) level=1;
			
			if( this.options.debug == true  && this.options.debugLevel <= level){
				
				switch( this.options.debugType ){
					
					case 'console':
						this.log_console(text, level);
					break;
					
					case 'print':
						this.log_print(text,level);
					break;
					
					default:
						this.log_alert(text,level);
					break;
				}
			}
			
		},
		
		log_console: function( text , level ){
			
			try{
				switch( level) {
					case 1:
						console.log( text );
					break;
					
					case 2:
						console.info( text );
					break;
					
					case 3: 
						console.warn( text );
					break;
					
					default:
						console.error( text ); 
					break;
				}
			}
			catch(error){
				//this.log_alert(text,level);
				this.log_print(text,level);
			}
			
		},
		
		log_print: function( text , level ){
			
			str='<p>' + text + '</p>';
			$(this.options.debugTagId).prepend(str);
		},
		
		log_alert: function( text , level ){
			
			switch( level) {
				case 1:
					str='Log';
				break;
				
				case 2:
					str='Info';
				break;
				
				case 3: 
					str='Warn!';
				break;
				
				default:
					str='Error!!!'; 
				break;
			}
			
			alert( str +"\n\n"+ text );
		}		
	});
	
})(jQuery);