var i4_Validator = {
	instances: [],

	get: function(form_id) {
		
		// check if form_id is id of a form-element. else its a form_element -> get real form id
		if ($(form_id).tagName.toUpperCase() != 'FORM') {
			form_id = $(form_id).up('form').readAttribute('id');	
		}
		
		var instance = this.get_instance_by_form_id(form_id);
		if (instance == null) {
			instance = new i4_Validator_instance();
			instance.set_form_id(form_id);
			this.instances.push([form_id, instance]);
		}
		
		return instance;
	},
	
	get_instance_by_form_id: function(form_id){
		var instance = null;
	
		this.instances.each( function(item){
			if(item[0] == form_id){
				instance = item[1];
			}
		});
		
		// console.log(instance);
		
		return instance;
	}
}

var i4_Validator_instance = Class.create({ 
	list: [],
	invalid_list: [],
	disable_list: [],
	
	from_id: '',
	
	before_submit_function: false,
	after_loaded_function: false,
	
	initialize: function() {
		this.list = new Array(); // bug?
		this.invalid_list = new Array(); // bug?
		this.disable_list = new Array(); // bug?
	},
	
	set_form_id: function(id) { this.form_id = id; return this; },

	add: function(item){
		this.list.push(item);
		return this;
	}, // i4_Validator_instance.add()

	remove: function(id) {
		this.list.each((function(item) {
			if (item.element_id == id) {
				this.list = this.list.without(item);
			}
		}).bind(this));
		return this;
	}, // i4_Validator_instance.remove()
	
	clear: function() {
		this.list.clear();
		this.invalid_list.clear();
		this.after_loaded_function = null;
		this.before_submit_function = null;
	}, // i4_Validator_instance.clear()
	
	start_observing: function() {
		// alert(this.list.inspect());
		this.list.each((function(item){
			// alert(item.inspect());
		    // observing
		    // log(item);
		    item.event_name.each((function(event_name){
		    
		    	$(item.element_id).on(event_name, (function(){
		    		
		    		this.check_item(item);
					this.update_style(item);	
					
					if (item.check_element && item.check_element.size() > 0) {
						item.check_element.each((function(element) {
							var check_item = this.get_item(element);

							this.check_item(check_item);
							this.update_style(check_item);
						}).bind(this));
					}
					
					this.update_submit();
					
		    	}).bind(this)); // on
		    	
		    }).bind(this));
		    
		}).bind(this));	
		
		if (this.after_loaded_function) {
			eval('i4_Validator.'+this.form_id+'_after_loaded_function()');
		}

		this.check_form();
	}, // i4_Validator_instance.start_observing()
	
	/*
	* check if the whole form is valid
	*/
	check_form: function() {
		this.invalid_list.clear();
				
		this.list.each((function(item){
			this.check_item(item);
		}).bind(this));
		    
		this.update_style();	
		this.update_submit();
	
	}, // i4_Validator_instance.check_form()
	
	/*
	* check if item is valid
	*/
	check_item: function(item) {
		if (item != '') {
			var function_string = 'this.'+item.function_name+'("'+item.element_id+'", '+Object.toJSON(item.function_parameter)+')';
		    // alert(function_string);
		    if(!eval(function_string)){
		        this.set_invalid(item.element_id);
		    } else {
		        this.set_valid(item.element_id);
		    }
		}
	}, // i4_Validator_instance.check_item()
	
	set_invalid: function(element_id) {
		this.invalid_list.push(element_id);
		this.invalid_list = this.invalid_list.uniq();
	}, // i4_Validator_instance.set_invalid()
	
	set_valid: function(element_id) {
		this.invalid_list = this.invalid_list.without(element_id);
	}, // i4_Validator_instance.set_valid()
	
	/**
	* updates all classnames
	*/
	update_style: function() {
		this.list.each((function(item){
			this.update_item_style(item);
		}).bind(this));
	}, // i4_Validator_instance.update_style()
	
	/**
	* updates just a item classname
	*/
	update_item_style: function(item) {
		if(this.invalid_list.indexOf(item.element_id) < 0) {
		    $(item.element_id).addClassName("valid");
		    $(item.element_id).removeClassName("invalid");
		} else {
		    $(item.element_id).addClassName("invalid");
		    $(item.element_id).removeClassName("valid");
		}

		// is empty and not required -> no color
		if(this.is_empty(item.element_id) && !item.function_parameter.required) {
		    $(item.element_id).removeClassName("invalid");
		    $(item.element_id).removeClassName("valid");
		}
	}, // i4_Validator_instance.update_item_style()
	
	update_submit: function() {
		var button = $$("#"+this.form_id+" button[type='submit']")[0];
		var button = $(this.form_id).down("button[type='submit']");
		
		if(this.invalid_list.size() == 0){
			if(button) {
				button.removeClassName("invalid");
				button.addClassName("valid");
				button.setStyle({ "cursor": "pointer"});
			}
			
			$(this.form_id).onsubmit = (function(){
			
			    if (/AppleWebKit|MSIE/.test(navigator.userAgent)) {
			    	// safari submit bug
			    	new Ajax.Request("/ping/close", { asynchronous:false });
			    }
			    
			    if (this.before_submit_function) {
			    	eval('i4_Validator.'+this.form_id+'_before_submit_function()');
			    }
			    			    
			    return true;
			}).bind(this)
		} else {
			if(button) {
				button.removeClassName("valid");
				button.addClassName("invalid");
				button.setStyle({ "cursor": "default"});
			}
			$(this.form_id).onsubmit = function(){return false;}
		}
		
	}, // i4_Validator_instance.update_submit()
	
	disable: function(element_id) {
		var disabled_item = this.get_item(element_id);
		
		if (disabled_item != '') {
			this.disable_list.push(disabled_item);
			this.list = this.list.without(disabled_item);
		}
		
	}, // i4_Validator_instance.disable()
	
	enable: function(element_id) {
		var enabled_item = '';
		this.disable_list.each(function(item){
			if (item.element_id == element_id) {
				enabled_item = item;
			}
		});
		
		if(enabled_item != '') {
			this.list.push(enabled_item);
			this.disable_list = this.disable_list.without(enabled_item);
		}

	}, // i4_Validator_instance.enable()
	
	get_item: function(element_id) {
		var result = '';
		this.list.each(function(item){
			if (item.element_id == element_id) {
				result = item;
			}
		});
		
		return result;
	}, // i4_Validator_instance.get_item()
	
	after_loaded: function(func){
		var after_loaded = 'i4_Validator.'+this.form_id+'_after_loaded_function = '+func;
		eval(after_loaded);
		this.after_loaded_function = true;
		return this;
	}, // i4_Validator_instance.after_loaded()
	
	before_submit: function(func){
		var before_submit = 'i4_Validator.'+this.form_id+'_before_submit_function = '+func;	
		eval(before_submit);	
		this.before_submit_function = true;
		return this;
	}, // i4_Validator_instance.before_submit()
	
	is_empty: function(id) {
		var result = false;
		
		if ($(id).getValue() == '') {
			result = true;
		}
		
		return result;
	}, // i4_Validator_instance.is_empty()
	
	is_valid_string: function(id, parameter) {
		var result = true;
		var value = $(id).getValue();
		// log(parameter.required);
		
		if (value == "") {
			result = false;
		}

		if (parameter.max_length && value.length > parameter.max_length) {
			result = false;
		}
		
		if (parameter.min_length && value.length < parameter.min_length) {
			result = false;
		}
		
		if (parameter.disallow_words) {
			parameter.disallow_words.each(function(item){
				if (value == item) {
					result = false;
				}
			});
		}
		
		if (parameter.character_invalid) {
			parameter.character_invalid.each(function(item){
				if (value.include(item)) {
					result = false;
				}
			});
		}
		
		if (parameter.rejected_start_string) {
			parameter.rejected_start_string.each(function(item){
				if (value.startsWith(item)) {
					result = false;
				}
			});
		}
		
		if(parameter.required == 0 && value == "") {
			result = true;
		}
		
		return result;
	}, // i4_Validator_instance.is_valid_string()
	
	is_valid_integer: function(id, parameter) {
		var result = true;
		var value = $(id).getValue();
		
		// alert(value+' '+parameter.max_length);
		
		if (value == "") {
			result = false;
		}
		
		if(isNaN(value)){
			result = false;
		}

		if (parameter.max_length && value > parameter.max_length) {
			result = false;
		}
		
		if (parameter.min_length && value < parameter.min_length) {
			result = false;
		}
		
		if(parameter.required == 0 && value == "") {
			result = true;
		}
		
		return result;
	}, // i4_Validator_instance.is_valid_integer()
	
	is_valid_url: function(id, parameter) {
		var result = true;
		var value = $(id).getValue();
		
		// alert(value+' '+parameter.required);
		
		if (value == "") {
			result = false;
		}
		
		/*
		if (value.match(/^(http|https|ftp):\/\/((\w[\w\-]*)(\.\w[\w\-]*)*)(:([0-9]+))?\/?/i) == null) {
			result = false;
		}
		*/
		
		if (!value.startsWith('http://')) {
			result = false;
		}
		
		if(parameter.required == 0 && value == "") {
			result = true;
		}
		
		return result;
	}, // i4_Validator_instance.is_valid_url()
	
	is_valid_mail: function(id, parameter) {
		var result = true;
		var value = $(id).getValue();
				
		if (value == "") {
			result = false;
		}
		
		if (value.match(/^[_a-z0-9äáàâçëéèêïíìîiñöóòôüúùû-]+([._a-z0-9äáàâçëéèêïíìîiñöóòôüúùû+-]+)*@[a-z0-9äáàâçëéèêïíìîiñöóòôüúùû+-]+(.[a-z0-9\-äáàâçëéèêïíìîiñöóòôüúùû]+)*\.([a-z]{2,4})$/i) == null) {
			result = false;
		}
		
		
		if(parameter.required == 0 && value == "") {
			result = true;
		}
		
		return result;
	}, // i4_Validator_instance.is_valid_mail()
	
	is_valid_file: function(id, parameter) {
		var result = true;
		var value = $(id).getValue();
				
		if (value == "") {
			result = false;
		}

		if (parameter.extensions) {
			var ext_valid = false;
			var splitted = value.split(".");
			var ext = splitted[splitted.length-1];
			parameter.extensions.each(function(item){
				if (ext.toLowerCase() == item.toLowerCase()) {
					ext_valid = true;
				}
			});
			
			if (!ext_valid) {
				result = false;
			}
		}
		
		// if file uploaded before
		if($(id+'_preview') && value == "") {
			result = true;
		}
		
		if(parameter.required == 0 && value == "") {
			result = true;
		}
		
		return result;
	}, // i4_Validator_instance.is_valid_file()
	
	is_valid_date: function(id, parameter) {
		var result = true;
		var value = $(id).getValue();
				
		if (value == "") {
			result = false;
		}
		
		var check_date = new Date();
		var year = '';
		var month = '';
		var day = '';
		
		var splitted_en = value.split("-");
		var splitted_de = value.split(".");
		if(splitted_en.size() == 3){
			year = splitted_en[0]; 
			month = splitted_en[1]; 
			day = splitted_en[2]; 
		}else if(splitted_de.size() == 3){
			year = splitted_de[2]; 
			month = splitted_de[1]; 
			day = splitted_de[0]; 	
		}
		
		check_date = new Date(year, month, day);
		if (check_date == 'Invalid Date') {
			result = false;
		}

		if(year == '' || month == '' || day == ''){
			result = false;
		}
		if(month < 1 || month > 12){
			result = false;	
		}
		if(year < 1000 || year > 9999){
			result = false;
		}
		if((check_date.getMonth()+1) != month && day > 32){
			result = false;
		}

		if(parameter.required == 0 && value == '') {
			result = true;
		}

		return result;
	}, // i4_Validator_instance.is_valid_date()
	
	is_valid_time: function(id, parameter) {
		var result = true;
		var value = $(id).getValue();
				
		if (value == "") {
			result = false;
		}
		
		var splitted = value.split(":");
		
		if (splitted.size() > 1 && splitted.size() < 4) {
			var hour = splitted[0];
			var minutes = splitted[1];
			var seconds = 0;
			if (splitted.size() == 3) {
				seconds = splitted[2];
			}
			
			if (hour < 0 || hour > 23 || isNaN(hour)) {
				result = false;
			}
			if (minutes < 0 || minutes > 59 || isNaN(minutes)) {
				result = false;
			}
			if (seconds < 0 || seconds > 59 || isNaN(seconds)) {
				result = false;
			}
			
		} else {
			result = false;
		}
		
		if(parameter.required == 0 && value == '') {
			result = true;
		}

		return result;
	}, // i4_Validator_instance.is_valid_time()

	is_valid_compare: function(id, parameter) {
		var result = true;
		var value = $(id).getValue();

		if (parameter.compare_field && parameter.compare_field != '') {
			var compare_value = $(parameter.compare_field).getValue();
			result = (compare_value == '') || (value == compare_value);
		}

		if (parameter.required == 1 && value == "") {
			result = false;
		}
		return result;
	}, // i4_Validator::is_valid_compare()

	is_valid_callback: function(id, parameter) {
		// log(id);
		var result = false;
		var value = $(id).getValue();
		// log(value);
		var paramater_value = $H();
		$H(parameter.parameter).each((function(item) {
			paramater_value.set(item.key, $(item.value).getValue());
		}).bind(this));
		if (parameter.callback_plugin != '') {
			// alert(parameter.callback_plugin);
			new Ajax.Request(parameter.url+'?js='+parameter.plugin+'&call='+parameter.action+'&value='+value+(paramater_value.size() == 0 ? '' : '&'+paramater_value.toQueryString()), {
			  onSuccess: (function(response) {
			  	// log(response.responseText);
				if (response.responseText == 1) {
					this.set_valid(id);
				} else {
					this.set_invalid(id);
				}

				this.update_item_style(this.get_item(id));
				this.update_submit();

			  }).bind(this)
			});
		}

		if (parameter.required == 1 && value == "") {
			result = false;
		}
		return result;
	} // i4_Validator::is_valid_callback()
		
}); // i4_Validator_instance
