
var keshVal = new Class({
	Implements: [Options, Events],
	options: {
		validateOnBlur: true,
		errorClass: 'error',
		errorMsgClass: 'error-msg',
		okMsgClass: 'ok-msg',
		dateFormat: 'dd/MM/yy',
		onFail: false,
		onSuccess: true,
		showErrorsInline: true,
		showErrorsListClass: 'error-list',
		pleaseWait: 'please wait...',
		
		text: '*',
		password: '*',
		radio: '*',
		checkbox: '*',
		select: '*',
		file: '*',
		textarea: '*',
		
		url: false,
		updater: 'updater',
		onlySubmit: false,
		submitandback: 0,
		useAjaxSubmit: true
	},
	
	onSuccess: function() {
		
		$(this.form).grab(new Element('input', {type:'hidden', name:'submitandback', value:this.submitandback}));
		
		if (this.options.useAjaxSubmit)
		{
			var url = (this.options.url) ? this.options.url : $(this.form).action;
			var req = new Request.HTML({
				method: 'post',
				url: url,
				data:$(this.form).toQueryString()+'&tkn='+Math.random(),
				update:$(this.options.updater),
				onRequest: function() {
					this.buttonDisable();
				}.bind(this),
				onComplete: function(responseTree, responseElements, responseHTML, responseJavaScript ) {
					responseJavaScript;
					if($chk(enable_btn))
						if (enable_btn) this.buttonEnable();
				}.bind(this)
			}).send();
		}
		else
		{
			this.form.submit();
		}
	},
	
	onFail: function() {
	},
	
	initialize: function(form, options){
		
		this.setOptions(options);
		
		this.form = form;
		this.button = $(this.form).getElement('*[type=submit]');
		this.elements = $(this.form).getElements('.required');
		this.list = [];
		
		/* on blur */
		if (!this.options.onlySubmit){
			if (this.options.validateOnBlur){
				this.elements.each(function(el){
					el.addEvent('blur', function(e){
						this.validate(el);
						this.validateEqual(el);
						this.ulList();
					}.bind(this));
				}.bind(this));
			}
		}
		
		/* on submit */
		$(this.form).addEvent('submit', function(e){
			this.formSubmit(e);
		}.bind(this));
		
		/* on saveandback */
		$$('.saveandback').addEvent('click', function(e){
			this.submitandback = 1;
			this.formSubmit(e);
		}.bind(this));
	},
	
	validateEqual: function(el) {
		this.valid = true;
		this.equal_val = null;
		if (el.hasClass('equal')){
			$$('.equal').each(function(x){
				if (this.equal_val == null)
					this.equal_val = x.get('value');
				if (this.equal_val != x.get('value')) 
					this.valid = false;
			}.bind(this));
			if (!this.valid){
				if (!$chk($('error-email-not-equal'))){
					var li = new Element('li').set('id', 'error-email-not-equal');
					var label = new Element('label').setProperty('for', el.id).set('text', 'Email addresses must match!');
					$(this.options.updater).grab(li.grab(label));
				}
			}
			else
				if ($chk($('error-email-not-equal')))
					$('error-email-not-equal').dispose();
		}
		return this.valid;
	},
	
	formSubmit: function(e){
		var event = new Event(e);
		var doSubmit = true;
		this.elements.each(function(el) {
			if((!this.validate(el)) || (!this.validateEqual(el))){
				event.stop();
				doSubmit = false;
			}
		}.bind(this));
		if (doSubmit) {
			if (this.options.onSuccess) {
				event.stop();
				this.onSuccess();
			}
			else
				this.buttonDisable();
		}
		else {
			this.ulList();
			if (this.options.onFail)
				this.onFail();
		}
	},
	
	ulList: function(){
		if ($chk($('error-ul')))
			$('error-ul').dispose();
		if (!this.options.showErrorsInline){	
			var ulList = new Element('ul').addClass(this.options.showErrorsListClass).set('id', 'error-ul');
			var tlist = [];
			this.list.each(function(el){
				var li = new Element('li');
				var label = new Element('label').setProperty('for', el.id).set('text', this.getElementTitle(el));
				if (!tlist.contains(el.name)){
					ulList.grab(li.grab(label));
					tlist.include(el.name);
				}
			}.bind(this));
			ulList.inject(this.form, 'top');
		}
	},
	
	getElementTitle: function(el){
		if ($chk(el.title))
			return el.title;
		else
			return this.options[el.type];
	},
	
	validate: function(el){
		var valid = true;
		if (el.type == 'radio'){
			var lrad = $A(this.form[el.name]);
			this.clearMsg(lrad.getLast());
		}
		else
			this.clearMsg(el);
		switch(el.type){
			case 'file':
			case 'text':
			case 'password':
			case 'textarea':
			case 'select-one':
				if(el.value != ''){
					
					if(el.hasClass('email')){
						var regEmail = /^[A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/;
						if(el.value.toUpperCase().match(regEmail)){
							valid = true;
						}else{
							valid = false;
							this.setMsg(el, 'Please provide correct e-mail address!');
						}
					}
					
					if (el.hasClass('username')){
						var regAN = /^[A-Z0-9_]{4,20}$/;
						if (el.value.length < 4 || el.value.length > 20)
						{
							valid = false;
							this.setMsg(el, 'Username must be from 4 to 20 letters!');
						}
						else if (el.value.toUpperCase().match(regAN)){
							valid = true;
						}else{
							valid = false;
							this.setMsg(el, 'Please provide alphanumeric expression!');
						}
						
					}
					
					if (el.hasClass('aphanumeric')){
						var regANum = /^[A-Z0-9_]{0,2000}$/;
						
						if (el.value.toUpperCase().match(regANum)){
							valid = true;
						}else{
							valid = false;
							this.setMsg(el, 'Please provide alphanumeric expression!');
						}
					}
					
					if(el.hasClass('integer')){
						var regInt = /^\d+$/;
						var result = el.value.match(regInt);
						if(result){
							valid = true;
						}else{
							valid = false;
							this.setMsg(el, 'Please provide integer number!');
						}
					}
					
					
					if(el.hasClass('number')){
						var regNum = /[-+]?[0-9]*\.?[0-9]+/;
						
						if(el.value.match(regNum)){
							
							valid = true;
						}else{
							valid = false;
							this.setMsg(el, 'Please provide number!');
						}
					}
					
					if(el.hasClass('postcode')){
						var regPC = /^([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([A-Za-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z])))) [0-9][A-Za-z]{2})$/
						if(el.value.match(regPC)){
							valid = true;
						}else{
							valid = false;
							this.setMsg(el, 'Please provide correct postcode!');
						}
					}
					
					if(el.hasClass('date')){
						var d = Date.parseExact(el.value, this.options.dateFormat);
						if(d != null){
							valid = true;
						}else{
							valid = false;
							this.setMsg(el, 'Please provide correct date format: '+this.options.dateFormat.toLowerCase());
						}
					}
					
				}else{
					valid = false;
					this.setMsg(el);
				}
				break;
				
			case 'checkbox':
				if(!el.checked){
					valid = false;
					this.setMsg(el);
				}else{
					valid = true;
				}
				break;
				
			case 'radio':
				var rad = $A(this.form[el.name]);
				var ok = false;
				rad.each(function(e,i){
					if(e.checked){
						ok = true;
					}
				});
				if(!ok){
					valid = false;
					this.setMsg(rad.getLast(), 'Please select an option!');
				}else{
					valid = true;
					this.clearMsg(rad.getLast());
				}
				break;
				
		}
		
		if (!this.options.showErrorsInline) {
			if (valid) {
				this.list.erase(el);
			}
			else
			{
				this.list.include(el);
			}
		}
		return valid;
	},
	
	setMsg: function(el, msg){
		if (msg == undefined)
			msg = this.getElementTitle(el);
		if (this.options.showErrorsInline){
			el.error = new Element('span').addClass(this.options.errorMsgClass).set('text', msg);
			el.error.inject(el.getParent(), 'bottom');
			el.addClass(this.options.errorClass);
		}
	},
	
	clearMsg: function(el){
		el.removeClass(this.options.errorClass);
		if($chk(el.error)){
			el.error.dispose();
		}
	},
	
	buttonDisable: function(){
		if (!this.button.retrieve('original'))
			this.button.store('original', this.button.get('value'));
		this.button.setProperty('value',this.options.pleaseWait);
		this.button.setProperty('disabled', true);
		this.button.addClass('disabled');
	},
	
	buttonEnable: function(){
		this.button.setProperty('value', this.button.retrieve('original'));
		this.button.setProperty('disabled', false);
		this.button.removeClass('disabled');
	}
});

