/*
 * 
 * @author Cosmobile
 * 
 * 
 *Add generic
 * 
 *Text:
 *    id*
 *    label*
 *    orientation (LEFT | TOP ) (default LEFT)
 *    lenght (in caratteri) (default 80)
 * 	  maxlenght (in caratteri) (default = lenght)
 * 	  minlenght (in caratteri) (default = 0)
 * 	  required (true | false ) (default false)
 *
 *File
 *
 *Div
 *
 *Hidden
 *
 *Price
 *
 *Date 
 *
 *Time 
 *
 *Number
 *
 *Password
 *
 *Combo
 *
 *ComboByUrl
 *
 *Radio
 *
 *Checkbox
 *
 *TextArea
 *
 *Captcha
 *
 *List
 * 
 *combo by url
 *
 *multicheckbox by url
 *
 *Autocompleter
 *
 *Autocombo
 *
 *AutocomboDynamic
 *
 *ColorPicker
 *
 * TODO:
 * Validation in multicheckbox
 */



var CosMooFC = new Class({
	Implements: [Events, Options],
	
	version:'0.3.0', //added create by url & default submit
	LEFT: 'left',
	TOP: 'top',
	RIGHT: 'right',
	groups: new Array(),
	
	options:
	{
		id:'',
		lang: 'it',
		method: 'post',
		action: '',
		root_path: '',
		afterSubmit: null
	},

	initialize: function(options)
	{
		this.setOptions(options);
		this.id = this.options.id;
		this.form = this.createForm(this.options.action, this.options.method);
		this.validationForm;
		if(this.options.lang=="ita" || this.options.lang=="it" || this.options.lang==null)
			FormValidator.language = "itIT";
		else if(this.options.lang=="eng" || this.options.lang=="en")
			FormValidator.language = "enUS";
			
	},
	
	
	add: function(json)
	{
		var obj = this;
		if (!json.input) json.input = 'text';
		var action = 'create'+json.input.substr(0,1).toUpperCase() + json.input.substr(1);
		var res = eval('obj.'+action+'(json)');
		var hidden = false
		if (json.input=='hidden') hidden = true; 
		return this.grab(json.id+'Content', res, hidden, json.group, json.classCnt); 
	},
	
	/*
	 * options: title, parent, className
	 */
	addGroup: function(name, options)
	{
		if (!options) options = {};
		if (!this.groups.contains(name)) this.groups.push(name);
		var group = new Element('div', {'id':this.id+name+'Group'});
		
		if (options.title) 
		{
			var titDiv = new Element('div', {'html':options.title});
			titDiv.addClass('GroupTitle');
			group.grab(titDiv);
		}
		
		group.addClass('Groups');
		var cntGroup = this.form;
		if (options.parent)
		{
			var parent = this.getGroup(options.parent);
			if (parent) cntGroup = parent;
		}
		
		if (options.className) group.addClass(options.className);
		cntGroup.grab(group);
	},
	
	removeGroup: function(name)
	{
		if (!this.groups.contains(name)) return; 
		this.groups.pop(name);
		var div = this.form.getChildren("#"+this.id+name+'Group');
		if (div.length!=0) div.destroy();
	},
	
	getGroup: function(name, parent)
	{
		if (!parent) parent = this.form;
		var obj = this;
		if (!this.groups.contains(name)) return false; 
		
		var div = parent.getChildren('#'+this.id+name+'Group');
		if (div.length>0) return div;
		//Else search into children
		div = parent.getChildren('.Groups');
		for(var i = 0; i<div.length; i++)
		{
			var res = this.getGroup(name, div[i]);
			if (res.length>0) return res;
		}
		
		return false;
		
	},
	
	getForm: function(){
		return this.form;
	},
	
	createForm: function(action, method)
	{
		var form = new Element('form',{'id':this.id+'Form', 'name':this.id+'Form','class':'forms','action':action, 'method':method});
		return form;
	},
	
	show: function(where)
	{
		$(where).set('html','');
		$(where).grab(this.form);
	},
	
	addValidation: function(){
		this.validationForm = new FormValidator(this.form);
	},
	
	grab: function(id,els, hidden, group, classCnt)
	{
		var obj = this;
		var div;
		var cnt = this.form;
		if (group)
		{
			var groupDiv = obj.getGroup(group);
			if (groupDiv) cnt = groupDiv;
		}
	
		if (hidden)
		{
			div = els;
		}
		else
		{
			if (id)
				div = new Element('div',{'id':id,'class':'formRow'});
			else
				div = new Element('div',{'class':'formRow'});
			els.each(function(el){div.grab(el);});
		}
		
		if (classCnt) div.addClass(classCnt);
		
		cnt.grab(div);
		return div;
	},
	
	/*
	 * TODO
	 */
	populate: function(data)
	{
		return false;
	},
	
	submitAction: function()
	{
		var obj = this;
		if (!this.options.action) return false;
		var req = new Request.JSON({
			async: false,
			url: obj.options.action,
			onComplete: function(json){
				if (json && json.result && json.result=='ok')
				{
					if (obj.options.afterSubmit) obj.options.afterSubmit(json);
					else
					{
						var sticky = new StickyWinFx.Modal({'content':'Dati salvati correttamente', 'destroyOnClose':true, 'className': 'alertWin'});
						(function(){sticky.hide()}).delay(2000);
					}
				}
				else
				{
					var content = 'Errore';
					if (json && json.msg) content+= ': '+json.msg;
					new StickyWinFx.Modal({'content':content, 'destroyOnClose':true, 'className': 'alertWin'});
				}
					
			},
			onError: function(){
				new StickyWinFx.Modal({'content':'Generic Error Failure', 'destroyOnClose':true, 'className': 'alertWin'});
			}
		});
		
		if (this.method=='get') req.get(this.form);
		else req.post(this.form);
	},
	
	createEmptyRow: function(opt){
		var div = new Element('div', {
			'class': 'emptyRow'
		});

		if (opt.height!=null) div.setStyle('height',opt.height);
		return [div];
	},
	
	createDiv: function(opt){
		return [new Element('div', {'id':opt.id,'class':opt.classcss,'html':opt.html})];
	},
	
	createHidden: function(opt){
		var hidden = new Element('input',{'id':opt.id,'type':'hidden','value':opt.value, 'name':opt.name || opt.id});
		return hidden;
	},
	
	createSubmit: function(opt){
		var obj = this;
		if(opt.type=="button" || !opt.type)
			var valid = new Element('input',{'id':obj.id+'Submit','type':'button','value':opt.value});
		else if(opt.type=="img")
			var valid = new Element('input',{'id':obj.id+'Submit','type':'image','src':opt.value});
		else if(opt.type=="html")
			var valid = new Element('div',{'id':obj.id+'Submit', 'html':opt.value, 'style':'cursor: pointer;'});
		
		valid.addEvent('click',function(){
			if(!obj.validationForm || obj.validationForm.validate()==true)
			{
				if (opt.submitAction)
					opt.submitAction();
				else obj.submitAction();
			}
		});
		
		return [valid];
	},
	
	createReset: function(opt){
		var obj = this;
		var button = new Element('input',{'id':opt.id,'type':'reset','value':opt.value});
		if(opt.className)
			button.set("class", opt.className);
		return [button];
	},
	
	createButton: function(opt){
		var obj = this;
		var button = new Element('input',{'id':opt.id,'type':'button','value':opt.value});
		if(opt.className)
			button.set("class", opt.className);
		
		if (opt.action)
		{
			button.addEvent('click', function(ev){
				if($type(opt.action=='string')) eval(opt.action);
				else opt.action();
			});
		}
		return [button];
	},
	
	getLabel: function(opt){
		var label = new Element('label',{'id':opt.id+'Label','class':'tfcLabel'});
		if (opt.orientation)
		{
			if (opt.orientation == this.LEFT)
			{
				label.setStyle('display','block');
				label.setStyle('float','left');
			}
			
			if (opt.orientation == this.RIGHT)
			{
				label.setStyle('display','block');
				label.setStyle('float','right');
			}
			
			if (opt.orientation == this.TOP)
			{
				label.setStyle('display','block');
			}
		}
		label.set('html',opt.label);
		return label;
	},
	
	createText: function(opt)
	{
		if (!opt.id || !opt.label) alert('Manca label o id in addText!!');
		
		var text = new Element('input',{'type': 'text', 'id': opt.id, 'name': opt.id, 'value': opt.value});
		var label = this.getLabel(opt);
		
		if (opt.width)
		{
			text.setStyle('width',opt.width);
		}
		//else text.setStyle('width',80);
		
		var validatorprops = new Hash();
		if (opt.maxLength){
			text.addClass('maxLength');
			validatorprops.include('maxLength',opt.maxLength);
		}else{
			validatorprops.include('maxLength',text.get('size'));
		}
		if (opt.minLength){
			text.addClass('minLength');
			validatorprops.include('minLength',opt.minLength);
		}		
		if (validatorprops.getLength()!=0)
			text.setProperty('validatorprops',JSON.encode(validatorprops));

		if (opt.email){
			text.addClass('validate-email');
			validatorprops.include('validate-email',opt.email);
		}
		
		if (opt.required){
			text.addClass('required');
			validatorprops.include('required',opt.required);
		}
		
		if (opt.readonly){
			text.set('readonly', opt.readonly);
		}	
		
		return [label,text];
	},
	
	createCombo: function(opt)
	{	
		if (!opt.id || !opt.label) alert('Manca label o id in addComboByUrl!!');
		
	    var combo = new Element('select',{'id': opt.id, 'name': opt.id});
		var label = this.getLabel(opt);
		if(opt.firstOption)
			var firstOption=opt.firstOption;
		else
			var firstOption='-- --- ---';
		var option = new Element('option',{'id':'re_none'+ opt.id, 'name': opt.id, 'value':'','html':firstOption});
		combo.grab(option);
		if(opt.width)
			var width=opt.width;
		else
			var width='149';					
		combo.setStyle('width',width+'px');
		
		if (opt.opts)
		{
			opt.opts.each(function(op,index){
				var option = new Element('option',{'id':'re_'+opt.id+'_'+op.id,'value':op.id,
				'html':op.description});
				if (op.id==opt.value) option.set('selected', 'selected');
				combo.grab(option);
			});
		}
		
		if (opt.required){
			combo.addClass('required');
			
		}
		
				
		return [label,combo];

	},
	
	//ComboByUrl
	createComboByUrl: function(opt)
	{	
		if (!opt.id || !opt.label) alert('Manca label o id in addComboByUrl!!');
		
	    var combo = new Element('select',{'id': opt.id, 'name': opt.id});
		var label = this.getLabel(opt);
		if(opt.firstOption)
			var firstOption=opt.firstOption;
		else
			var firstOption='-- --- ---';
		var option = new Element('option',{'id':'re_none'+ opt.id, 'name': opt.id, 'value':'','html':firstOption});
		combo.grab(option);
		if(opt.width)
			var width=opt.width;
		else
			var width='149';					
		combo.setStyle('width',width+'px');
		var req = new Request.JSON({
						url: opt.url+'?rand=' + $random(0, 99999),
						encode: 'utf-8',
						async:false,
						onComplete: function(resp){
							if(resp.opts)
							{
								resp.opts.each(function(op,index){
									var option = new Element('option',{'id':'re_'+op.id,'value':op.id,
									'html':op.description});
									if (op.id==opt.value) option.set('selected', 'selected');
									combo.grab(option);
								});
							}
						}
					}).post({
						'requestType': opt.reqType
					});
		
		
		if (opt.required){
			combo.addClass('required');
			
		}
		
				
		return [label,combo];

	},
	//TextArea
	createTextArea: function(opt)
	{	
		if (!opt.id || !opt.label) alert('Manca label o id in addText!!');
		
		var text = new Element('textarea',{'id': opt.id, 'name': opt.id, 'html': opt.value});
		var label = this.getLabel(opt);
		
		if (opt.width){
			text.setStyle('width',opt.width);
		}
		else if (opt.cols){
			text.set('cols',opt.cols);
		}else
			text.set('cols',50);
		if (opt.rows){
			text.set('rows',opt.rows);
		}else
			text.set('rows',5);
		
		var validatorprops = new Hash();
		if (opt.maxLength){
			text.addClass('maxLength');
			validatorprops.include('maxLength',opt.maxLength);
		}else{
			validatorprops.include('maxLength',text.get('size'));
		}
		if (opt.minLength){
			text.addClass('minLength');
			validatorprops.include('minLength',opt.minLength);
		}		
		if (validatorprops.getLength()!=0)
			text.setProperty('validatorprops',JSON.encode(validatorprops));

		if (opt.required){
			text.addClass('required');
			validatorprops.include('required',opt.required);
		}
		
		if (opt.readonly){
			text.set('readonly', opt.readonly);
		}
		
		return [label,text];
	},
	
	//Password
	createPassword: function(opt)
	{	
		if (!opt.id || !opt.label) alert('Manca label o id in addPassword!!');
		
		var text = new Element('input',{'id': opt.id, 'type': 'password', 'name': opt.id, 'value': opt.value});
		var label = this.getLabel(opt);
		
		var validatorprops = new Hash();
		
		if (opt.width){
			text.setStyle('width',opt.width);
		}else
			text.setStyle('width',80);
		
		if (opt.maxLength){
			text.addClass('maxLength');
			validatorprops.include('maxLength',opt.maxLength);
		}else{
			validatorprops.include('maxLength',text.get('size'));
		}
		if (opt.minLength){
			text.addClass('minLength');
			validatorprops.include('minLength',opt.minLength);
		}		
		if (validatorprops.getLength()!=0)
			text.setProperty('validatorprops',JSON.encode(validatorprops));

		if (opt.required){
			text.addClass('required');
			validatorprops.include('required',opt.required);
		}
		
		if (opt.readonly){
			text.set('readonly', opt.readonly);
		}
		
		return [label,text];
	},
	
	//Captcha
	createCaptcha: function(opt)
	{	
		var obj = this;
		var idcaptcha;
		var req = new Request.JSON({
			url: opt.url+'?rand=' + $random(0, 99999),
			encode: 'utf-8',
			async:false,
			onComplete: function(rsp){
				idcaptcha = rsp.idcaptcha;
			}
		}).post();
		var el = this.createText(opt);
		var captchaInput = new Element('div', {'id':opt.id+'Input'});
		captchaInput.grab(el[0]);
		captchaInput.grab(el[1]);
		var captchaCnt = new Element('div', {'id':opt.id+'Cnt'});
		var captchaImg = new Element('img', {'id':opt.id+'Img', 'src':opt.urlImg+idcaptcha+'.png', 'align':'absmiddle'});
		captchaImg.setStyle('border', '1px solid');
		captchaImg.setStyle('margin-left', '5px');
		captchaImg.setStyle('vertical-align', 'top');
		captchaCnt.grab(captchaImg);
		captchaCnt.grab(new Element('input', {'id':opt.id+'Id', 'name':opt.id+'Id', 'value': idcaptcha, 'type': 'hidden'}));
		captchaCnt.grab(new Element('div', {'html':'<a href="javascript: void(null);" onclick="refreshCaptcha()">clicca qui</a> per ottenere una nuova immagine', 'id':'captchaText'}));

		return [captchaInput, captchaCnt];
	},
	
    //Date
	createDate: function(opt)
	{	
		var el = this.createText(opt);
		if (!opt.immagine) opt.immagine = this.options.root_path+'immagini/calendarImg.gif';
		el[2] = new Element('img', {'class':'calendarImg', 'src':opt.immagine, 'align': 'absmiddle'});
		if (!opt.width) el[1].setStyle('width', 100);
		
		var dp = new DatePicker(el[1], {
			  format: '%d/%m/%Y',
			  'weekStartOffset': 1
			});
		el[2].addEvent("click", function(){el[1].focus();})
		return el;
	},
	
    //File
	createFile: function(opt)
	{
		if (!opt.id || !opt.label) alert('Manca label o id in addFile!!');
		this.form.set('enctype','multipart/form-data');
		
		var text = new Element('input',{'type': 'file', 'id': opt.id, 'name': opt.id, 'value': opt.value});
		var label = this.getLabel(opt);
		
		var validatorprops = new Hash();
		if (opt.required){
			text.addClass('required');
			validatorprops.include('required',opt.required);
		}
		
		if (opt.readonly){
			text.set('readonly', opt.readonly);
		}	
		
		return [label,text];
	},

	//Price
	createPrice: function(opt)
	{
		var el = this.createText(opt)
		el[1].addEvent('change',function(){
			//TODO: approssimare e forzare n. decimali (a seconda della specifica di opt)
		});
		el[1].addClass('validate-numeric');
		return el;
	},
	
	//time
	createTime: function(opt)
	{
		if (!opt.step) opt.step = 5;
		if (!opt.minHour) opt.minHour = 0;
		if (!opt.maxHour) opt.maxHour = 24;
		
		opt.lenght = 5;
		opt.maxLength = 5;
		var el = this.createText(opt);
		el[1].addClass('isTime');
		el[1].addClass('minMaxTime');
		
		el[1].store('minHour', opt.minHour);
		el[1].store('maxHour', opt.maxHour);
		
		el[1].addEvent('focus', function(ev){
			$$('.timeOptCnt').each(function(el){el.destroy();});
			
			var div = new Element('div');
			div.addClass('timeOptCnt');
			div.setStyles({
				'position':'absolute',
				'z-index':20000
			});
			
			var hour = opt.minHour;
			var min = 0;
			var count=0;
			var scrollTo = null;
			do
			{
				var divHour = new Element('div', {'class':'divHour'});
				var txt = '';
				if (hour<10) txt+='0';
				txt+=hour+':';
				if (min<10) txt+='0';
				txt+=min;
				
				divHour.set('html', txt);
				
				if (txt==this.value)
				{
					scrollTo = divHour;
					divHour.addClass('selected');
				}
				
				min+=opt.step;
				if (min>=60)
				{
					hour++;
					min=0;
				}
				
				count++;
				div.grab(divHour);
				
				divHour.addEvent('click', function(ev){
					el[1].value = this.get('html');
					this.getParent().destroy();
				});
				
				
			}while(hour<opt.maxHour || hour==opt.maxHour && min==0);
			
			var coords = this.getPosition(this.getParent().getParent());
			var dim = this.getSize();
			div.setStyles({
				'top':coords.y,
				'left':coords.x+dim.x+5
			});
			
			div.addEvent('keyup', function(ev){
				if (ev.key!='esc') return;
				this.destroy();
			});
			
			div.inject(this.getParent().getParent());
			
			
			new Fx.Scroll(div, {'duration':0, 'offset':{'y':-40}}).toElement(scrollTo);

			this.store('timeDiv', div);
		});
		
		el[1].addEvent('keyup', function(ev){
			if (ev.key!='esc') return;
			var div = this.retrieve('timeDiv');
			div.destroy();
		});
		
		return el;
	},
	
	//Number
	createNumber: function(opt)
	{
		var el = this.createText(opt)
		el[1].addClass('validate-numeric');
		return el;
	},
	
	//Radio
	createRadio: function(opt)
	{	
		var obj = this;
		var divRadio = new Element('div',{'id':opt.id+'Div'});
		divRadio.addClass('tfcRadioList');
		
		if (!opt.id || !opt.label || !opt.opts) alert('Manca label o id o opts in Radio!!');
		obj._fillMultiField('radio', opt.opts, divRadio, opt);
		
		var label = this.getLabel(opt);

		return [label, divRadio];
	},
	
	//RadioByUrl
	createRadioByUrl: function(opt)
	{	
		var obj = this;
		var divRadio = new Element('div',{'id':opt.id+'Div'});
		divRadio.addClass('tfcRadioList');
		if (!opt.id || !opt.label || !opt.url) alert('Manca label o id o url in Radio!!');
		
		if (opt.jsonp)
		{
			var req = new Request.JSONP({
				url: opt.url+'?rand=' + $random(0, 99999),
				data: {
					'requestType': opt.reqType
				},
				encode: 'utf-8',
				async:false,
				onComplete: function(rsp){
					obj._fillMultiField('radio', rsp.opts, divRadio, opt);
				}
			}).send();
		}
		else
		{
			var req = new Request.JSON({
				url: opt.url+'?rand=' + $random(0, 99999),
				encode: 'utf-8',
				async:false,
				onComplete: function(rsp){
					obj._fillMultiField('radio', rsp.opts, divRadio, opt);
				}
			}).post({
				'requestType': opt.reqType
			});
		}
		var label = this.getLabel(opt);

		return [label, divRadio];
	},
	
	//checkbox
	createCheckbox: function(opt)
	{	
		if (!opt.id || !opt.label) alert('Manca label o id in Checkbox!!');
		if(!opt.value)	opt.value=1;
		var nullvalue;
		if(isNaN(opt.value))	nullvalue='';
		else	nullvalue=0;
		
		var hiddenCheck = new Element('input',{'type': 'hidden', 'id': opt.id, 'name': opt.id, 'value': nullvalue});
		var check = new Element('input',{'type': 'checkbox', 'id': opt.id, 'name': opt.id, 'value': opt.value});
		var label = this.getLabel(opt);
		
		if (opt.checkValue && opt.value == opt.checkValue) check.set('checked','checked');
		
		if (opt.orientation)
		{
			if (opt.orientation == this.LEFT)
			{
				label.setStyle('display','block');
				label.setStyle('float','left');
			}
			
			if (opt.orientation == this.RIGHT)
			{
				label.setStyle('display','block');
				label.setStyle('float','right');
			}
			
			if (opt.orientation == this.TOP)
			{
				label.setStyle('display','block');
			}
		}
		label.set('html',opt.label);
		
		var validatorprops = new Hash();
		if (validatorprops.getLength()!=0)
			check.setProperty('validatorprops',JSON.encode(validatorprops));
		
		if (opt.isChecked){
			check.addClass('isChecked');
			validatorprops.include('isChecked',opt.isChecked);
		}	
		
		if (!opt.width) check.setStyle('width', 20);
		
		return[label, hiddenCheck, check];
	},
	
	//MultiCheckboxByUrl
	createMultiCheckboxByUrl: function(opt)
	{	
		var obj = this;
		var divMultiCheck = new Element('div',{'id':opt.id+'Div'});
		divMultiCheck.addClass('tfcCheckList');
		if (!opt.id || !opt.label || !opt.url) alert('Manca label o id o url in MultiCheckbox!!');
		
		if (opt.jsonp)
		{
			var req = new Request.JSONP({
				url: opt.url+'?rand=' + $random(0, 99999),
				data: {
					'requestType': opt.reqType
				},
				encode: 'utf-8',
				async:false,
				onComplete: function(rsp){
					obj._fillMultiField('checkbox', rsp.opts, divMultiCheck, opt);
				}
			}).send();
		}
		else
		{
			var req = new Request.JSON({
				url: opt.url+'?rand=' + $random(0, 99999),
				encode: 'utf-8',
				async:false,
				onComplete: function(rsp){
					obj._fillMultiField('checkbox', rsp.opts, divMultiCheck, opt);
				}
			}).post({
				'requestType': opt.reqType
			});
		}
		var label = this.getLabel(opt);
		/*
		
		var validatorprops = new Hash();
		if (validatorprops.getLength()!=0)
			check.setProperty('validatorprops',JSON.encode(validatorprops));
		
		if (opt.isChecked){
			check.addClass('isChecked');
			validatorprops.include('isChecked',opt.isChecked);
		}	*/
		return [label, divMultiCheck];
	},
	
	//MultiCheckbox
	createMultiCheckbox: function(opt)
	{	
		var obj = this;
		var divMultiCheck = new Element('div',{'id':opt.id+'Div'});
		divMultiCheck.addClass('tfcCheckList');
		
		if (!opt.id || !opt.label || !opt.opts) alert('Manca label o id o opts in MultiCheckbox!!');
		obj._fillMultiField('checkbox', opt.opts, divMultiCheck, opt);
		
		var label = this.getLabel(opt);

		return [label, divMultiCheck];
	},
	
	_fillMultiField: function(type, json, cnt, opt)
	{
		var obj = this;
		if (!opt.name) opt.name = opt.id;
		json.each(function(op,index){
			var check = new Element('input',{'type': type, 'id': opt.id+'_'+op.id, 'name': opt.name+'[]', 'value': op.value});
			if (op.checked) check.set('checked', 'checked');
			else if(opt.checkValues && opt.checkValues.contains(op.id))
			{
				check.set('checked', 'checked');
			}
			
			check.setStyle('float','left');
			
			var subLabel = obj.getLabel({'id':opt.id+'_'+op.id, 'label':op.description, 'orientation':obj.LEFT});
			subLabel.addClass('tfcList');
			
			var divCheck = new Element('div',{'id':opt.id+'_'+op.id+'Div'});
			
			
			divCheck.grab(check);
			divCheck.grab(subLabel);
			
			
			cnt.grab(divCheck);
		});
		cnt.grab(new Element('div',{'styles':{'clear':'both'}}));	
	},
	
	createAutocompleter: function(opt)
	{
		if (!opt.id || !opt.label) alert('Manca label o id in addText!!');
		var obj = this;
		
		var text = new Element('input',{'type': 'text', 'autocomplete':'off', 'id': opt.id, 'name': opt.id, 'value': opt.value});
		var label = this.getLabel(opt);
		
		if (opt.width)
		{
			text.setStyle('width',opt.width);
		}
		else
			text.setStyle('width',80);
		
		var validatorprops = new Hash();
				
		if (opt.required){
			text.addClass('required');
			validatorprops.include('required',opt.required);
		}
		
		if (opt.readonly){
			text.set('readonly', opt.readonly);
		}	
		else
		{
			var tokens = opt.opts;
		    var completer1 = new Autocompleter.Local(text, tokens, {
		    	  'delay': 100,
		    	  'zIndex': opt.zIndex,
		    	  'filterSubset': false,
		    	  'filterTokens': function() {
		    	  var regex = new RegExp(this.queryValue.escapeRegExp(), 'i');
		    	  return this.tokens.filter(function(token){
		    		  return (regex.test(token[0]) || regex.test(token[1]));
		    	  });
		      },
		      'injectChoice': function(choice) {
		    	  var el = new Element('li');
		    	  el.set('html',this.markQueryValue(choice[0]));
		    	  el.adopt(new Element('span', {'class': 'example-info'}).set('html',this.markQueryValue(choice[1])));
		    	  el.inputValue = choice[0];
		    	  this.addChoiceEvents(el).injectInside(this.choices);
		      }
		      });
		 }
	     return [label,text];
	},
	
	
	createAutocombo: function(opt)
	{
		if (!opt.id || !opt.label) alert('Manca label o id in Autocombo!!');
		var obj = this;
		
		var fakeValue;
		var realValue;
		
		if (opt.value)
		{
			fakeValue = opt.value[0];
			realValue = opt.value[1];
		}
		
		var text = new Element('input',{'type': 'text', 'autocomplete':'off', 'id': opt.id+'Text', 'value': fakeValue});
		var input = new Element('input',{'type': 'hidden', 'id': opt.id, 'name': opt.id, 'value': realValue});
		var label = this.getLabel(opt);
		
		if (opt.width)
		{
			text.setStyle('width',opt.width);
		}
		else
			text.setStyle('width',80);
		
		var validatorprops = new Hash();
				
		if (opt.required){
			text.addClass('required');
			validatorprops.include('required',opt.required);
		}
		
		if (opt.readonly){
			text.set('readonly', opt.readonly);
		}	
		else
		{
			var tokens = null;
			if (opt.opts) tokens = opt.opts;
			else if (opt.url)
			{
				var req = new Request.JSON({
					url: opt.url,
					async: false,
					onComplete: function(resp)
					{
						resp.opt.each(function(el)
						{
							//TODO: converti in formato [[],[],[]]
						});
					}
				}).post();
			}
		    var completer1 = new Autocompleter.Local(text, tokens, {
		    	  'delay': 100,
		    	  'zIndex': opt.zIndex,
		    	  'width': 'auto',
		    	  'filterSubset': true,
		    	  'filterTokens': function() {
		    	  var regex = new RegExp(this.queryValue.escapeRegExp(), 'i');
		    	  return this.tokens.filter(function(token){
		    		  return (regex.test(token[0]));
		    	  });
		      },
		      'injectChoice': function(choice) {
		    	  var el = new Element('li');
		    	  el.set('html',this.markQueryValue(choice[0]));
		    	  //el.adopt(new Element('span', {'class': 'example-info'}).set('html',this.markQueryValue(choice[1])));
		    	  el.inputValue = choice[0];
		    	  el.store('idVal',choice[1])
		    	  this.addChoiceEvents(el).injectInside(this.choices);
		      }
		      });
	    	
		    input.store('completer',completer1);
		    input.addClass('isAutocombo');
		    
		    completer1.addEvent('select', function(el, sel,selection){
	    		$(opt.id).value = $(sel).retrieve('idVal');
	    	});
	    	
	    	completer1.addEvent('blur', function(el){
	    		el = $(el);
	    		var ok = false;
	    		var id = 0;
	    		opt.opts.each(function(token){
	    			if (token[0]==el.value)
	    			{
	    				id = token[1];
	    				ok = true;
	    			}
	    		});
	    		
	    		if (ok)
	    		{
	    			if ($(opt.id).value!=id) $(opt.id).value = id;
	    		}
	    		else $(opt.id).value = 0;
	    	});
		 }
		
		
	     return [label,text, input];
	},
	
	
	createAutocomboDynamic: function(opt)
	{
		if (!opt.id || !opt.label || !opt.url) alert('Manca label o id o url in AutocomboDynamic!!');
		var obj = this;
		
		var fakeValue;
		var realValue;
		
		if (opt.value)
		{
			fakeValue = opt.value[0];
			realValue = opt.value[1];
		}
		
		var text = new Element('input',{'type': 'text', 'autocomplete':'off', 'id': opt.id+'Text', 'value': fakeValue});
		var input = new Element('input',{'type': 'hidden', 'id': opt.id, 'name': opt.id, 'value': realValue});
		var label = this.getLabel(opt);
		
		if (opt.width)
		{
			text.setStyle('width',opt.width);
		}
		else
			text.setStyle('width',80);
		
		var validatorprops = new Hash();
				
		if (opt.required){
			input.addClass('required');
			validatorprops.include('required',opt.required);
		}
		
		var completer1;
		
		if (opt.readonly){
			text.set('readonly', opt.readonly);
		}	
		else
		{
			var tokens = new Array();
			var onDigitF = null;
			if (opt.opts) tokens = opt.opts;
			else if (opt.url)
			{
				onDigitF = function()
				{
					if (!this.req)
						this.req = new Request.JSON({
							url: opt.url,
							async: false,
							onComplete: function(resp)
							{
								completer1.tokens = resp;
							}
						});
					else
					{
						this.req.cancel();
					}
					
					
					if (!text.retrieve('lastValue') || !text.retrieve('lastValue').contains(this.lastValue) || text.get('value').length<3)
						this.req.post({'filter':text.get('value')});
					text.store('lastValue', text.get('value'));
				};

			}
			
			
			completer1 = new Autocompleter.Local(text, tokens, {
		    	  'delay': 100,
		    	  'zIndex': opt.zIndex,
		    	  'width': 'auto',
		    	  'TextDigit': function(){onDigitF()},
		    	  'filterSubset': true,
		    	  'injectChoice': function(choice) {
			    	  var el = new Element('li');
			    	  el.set('html',this.markQueryValue(choice[0]));
			    	  //el.adopt(new Element('span', {'class': 'example-info'}).set('html',this.markQueryValue(choice[1])));
			    	  el.inputValue = choice[0];
			    	  el.store('idVal',choice[1])
			    	  this.addChoiceEvents(el).injectInside(this.choices);
			      }
		      });
			
			completer1.options.TextDigit();
	    	
		    input.store('completer',completer1);
		    input.addClass('isAutocombo');
		    
		    completer1.addEvent('select', function(el, sel,selection){
	    		$(opt.id).value = $(sel).retrieve('idVal');
	    	});
	    	
	    	completer1.addEvent('blur', function(el){
	    		el = $(el);
	    		var ok = false;
	    		var id = 0;

	    		this.tokens.each(function(token){
	    			
	    			if (token[0]==el.value)
	    			{
	    				id = token[1];
	    				ok = true;
	    			}
	    		});
	    		
	    		if (ok)
	    		{
	    			if ($(opt.id).value!=id) $(opt.id).value = id;
	    		}
	    		else $(opt.id).value = 0;
	    	});
		 }
		
		
	     return [label,text, input];
	},
	
	
	
	createColorPicker: function(opt){
		var els = this.createText(opt);
		var label = els[0];
		var text = els[1];
		var imgPick = new Element('img',{'src':'img/colorpicker.png','alt':'Scegli il colore', 'title':'Scegli il colore'});
		var picker = new Element('div');
		picker.grab(imgPick);
		text.setStyle('float','left');
		text.set('readonly','readonly');
		
		var start = 0;
		if (opt.start) start = opt.start;
		
		var stop = 256;
		if (opt.stop) stop = opt.stop;
		
		var step = 68;
		if (opt.step) step = opt.step;
		
		picker.addEvent('click',function(){
			
			if (this.win)
			{
				this.win.show();
			}
			else
			{
				var divCnt = new Element('div', {'id':'picker'+opt.id});
				divCnt.setStyle('overflow','hidden');
				
				for(var r = start;r<stop;r+=step)
					for(var g = start;g<stop;g+=step)
						for(var b = start;b<stop;b+=step)
						{
							var divCol = new Element('div',{'id':'rgb('+r+','+g+','+b+')'});
							divCol.setStyle('background-color','rgb('+r+','+g+','+b+')');
							divCol.setStyle('float','left');
							divCol.addClass('unpickedColor');
							
							if (text.value == divCol.get('id').rgbToHex())
							{
								divCol.addClass('pickedColor');
							}
							
							divCol.addEvent('click',function(){
								$$('.pickedColor').each(function(el2){ el2.removeClass('pickedColor')});
								this.addClass('pickedColor');
							})
							
							divCnt.grab(divCol);
						}
				
				this.win = new StickyWin({
					  content: StickyWin.ui('Scegli il colore', divCnt, {
					    width: '400px',
					    buttons: [
					      {
					        text: 'Chiudi', 
					        onClick: function(){}
					      },
					      {
						        text: 'Rimuovi', 
						        onClick: function(){
					    	  		text.set('value','');
					      		}
						  },
					      {
					        text: 'Scegli', 
					        onClick: function(){
							  var selEl = $$('.pickedColor');
							  if (selEl.length)
							  {
								  var selCol = selEl[0].get('id');
								  text.set('value',selCol.rgbToHex());
							  }
						  	}
					      }
					    ]
					  })
					});
				}
		});
		
		return [label, text, picker];
	},
	
	
	/*
	 * It evaluates a JSON like this:
	 *  
	 *  {
	 *  	voices: 
	 *  	[
	 *  		"id":id,
	 *  		... //all requested fields,
	 *  		"input": text|password|emptyRow|...
	 *  	]
	 *  }
	 */
	createByJSON: function(json)
	{
		var obj = this;
		json.voices.each(function(voice, index){             
         	if (voice.orientation) voice.orientation = eval('obj.'+voice.orientation.toUpperCase());         	
         	//var action = 'add'+voice.input.substr(0,1).toUpperCase() + voice.input.substr(1);
         	//eval('obj.'+action+'(voice)');
         	obj.add(voice);
         });
	},
	
	createByUrl: function(url, post)
	{
		var obj = this;
		if (!this.options.action) this.options.action = url;
		var r = new Request.JSON({
		       url: url,
		       async: false,
		       onComplete: function(json){
				  obj.createByJSON(json);    
				  obj.addValidation();
				  obj.fireEvent('createdByUrl');
		       }
		   }).post(post);
	},
	
	/* 
	 * FUNZIONI PER LA RETROCOMPATIBILITA'
	 */
	
	addDiv: function(opt)
	{		
		opt.input = 'div';
		this.add(opt);
	},
	
	addText: function(opt)
	{		
		opt.input = 'text';
		this.add(opt);
	},
	
	addEmptyRow: function(opt)
	{		
		if (!opt) opt = {};
		opt.input = 'emptyRow';
		this.add(opt);
	},
	
	addHidden: function(opt)
	{		
		opt.input = 'hidden';
		this.add(opt);
	},
	
	addSubmit: function(opt)
	{		
		opt.input = 'submit';
		this.add(opt);
	},
	
	addButton: function(opt)
	{		
		opt.input = 'button';
		this.add(opt);
	},
	
	addReset: function(opt)
	{		
		opt.input = 'reset';
		this.add(opt);
	},
	
	addCombo: function(opt)
	{		
		opt.input = 'combo';
		this.add(opt);
	},
	
	addComboByUrl: function(opt)
	{		
		opt.input = 'comboByUrl';
		this.add(opt);
	},
	
	addTextArea: function(opt)
	{		
		opt.input = 'textArea';
		this.add(opt);
	},
	
	addPassword: function(opt)
	{		
		opt.input = 'password';
		this.add(opt);
	},
	
	addCaptcha: function(opt)
	{		
		opt.input = 'captcha';
		this.add(opt);
	},
	
	addDate: function(opt)
	{		
		opt.input = 'date';
		this.add(opt);
	},
	
	addFile: function(opt)
	{		
		opt.input = 'file';
		this.add(opt);
	},
	
	addPrice: function(opt)
	{		
		opt.input = 'price';
		this.add(opt);
	},
	
	addTime: function(opt)
	{		
		opt.input = 'time';
		this.add(opt);
	},
	
	addNumber: function(opt)
	{		
		opt.input = 'number';
		this.add(opt);
	},
	
	addCheckbox: function(opt)
	{		
		opt.input = 'checkbox';
		this.add(opt);
	},
	
	addMultiCheckboxByUrl: function(opt)
	{		
		opt.input = 'multiCheckboxByUrl';
		this.add(opt);
	},
	
	addAutocompleter: function(opt)
	{		
		opt.input = 'autocompleter';
		this.add(opt);
	},
	
	addAutocombo: function(opt)
	{		
		opt.input = 'autocombo';
		this.add(opt);
	},
	
	addColorPicker: function(opt)
	{		
		opt.input = 'colorPicker';
		this.add(opt);
	}
	
});


FormValidator.resources = {
	'enUS': {
		required:'This field is required.',
		isChecked:'This input field must be checked',
		isAutocombo:'The value inserted is not within the list of possibilities',
		isTime: 'Insert a valid time format',
		minMaxTime: 'Inserire a time between {min}:00 and {max}:00',
		minLength:'Please enter at least {minLength} characters (you entered {length} characters).',
		maxLength:'Please enter no more than {maxLength} characters (you entered {length} characters).',
		integer:'Please enter an integer in this field. Numbers with decimals (e.g. 1.25) are not permitted.',
		numeric:'Please enter only numeric values in this field (i.e. "1" or "1.1" or "-1" or "-1.1").',
		digits:'Please use numbers and punctuation only in this field (for example, a phone number with dashes or dots is permitted).',
		alpha:'Please use letters only (a-z) with in this field. No spaces or other characters are allowed.',
		alphanum:'Please use only letters (a-z) or numbers (0-9) only in this field. No spaces or other characters are allowed.',
		dateSuchAs:'Please enter a valid date such as {date}',
		dateInFormatMDY:'Please enter a valid date such as MM/DD/YYYY (i.e. "12/31/1999")',
		email:'Please enter a valid email address.',
		url:'Please enter a valid URL such as http://www.google.com.',
		currencyDollar:'Please enter a valid $ amount. For example $100.00 .',
		oneRequired:'Please enter something for at least one of these inputs.',
		errorPrefix: 'Error: ',
		warningPrefix: 'Warning: '
	},
	'itIT': {
		required:'Il campo deve essere compilato',
		isChecked:'La casella deve essere selezionata',
		isAutocombo:'Il campo inserito non e\' tra quelli disponibili',
		isTime: 'Inserire un orario valido',
		minMaxTime: 'Inserire un orario compreso tra le {min}:00 e le {max}:00',
		minLength:'Devono essere inseriti almeno {minLength} caratteri (ne hai inseriti {length}).',
		maxLength:'Possono essere inseriti al massimo {maxLength} caratteri (ne hai inseriti {length}).',
		integer:'Questo campo richiede un intero. Numeri decimali (es. 1.25) non sono consentiti.',
		numeric:'Questo campo richiede valori numerici (es. "1" o "1.1" o "-1" o "-1.1").',
		digits:'Questo campo richiede solo valori numerici con separatori (ad esempio, un numero di telefono con linette o punti).',
		alpha:'Inserire solo lettere (a-z) in questo campo. Spazi e altri caratteri non sono consentiti.',
		alphanum:'Inserire solo lettere (a-z) o numeri (0-9) in questo campo. Spazi e altri caratteri non sono consentiti.',
		dateSuchAs:'Inserire una data valida come {date}',
		dateInFormatMDY:'Inserire una data valida in formato MM/GG/AAAA (es. "12/31/1999")',
		email:'Inserire un indirizzo email valido.',
		url:'Inserire un url valido (es. http://www.google.com)',
		currencyDollar:'Inserire un importo in dollari valido. Ad esempio $100.00 .',
		oneRequired:'Compilare almeno uno di questi campi.',
		errorPrefix: 'Errore: ',
		warningPrefix: 'Attenzione: '
	}
};
FormValidator.language = "itIT";

FormValidator.add('isChecked', {
	errorMsg: function(element, props){
		return FormValidator.getMsg('isChecked');
	}, 
	test: function(element) {
		return element.checked;
	}
});

FormValidator.add('isAutocombo', {
	errorMsg: function(element, props){
		return FormValidator.getMsg('isAutocombo');
	}, 
	test: function(element) {
		el = $(element);
		completer = el.retrieve('completer');
		var res = false;
		completer.tokens.each(function(token){
			if (token[1]==el.value)
			{
				res = true;
			}
		});
		
		return res;
		
	}
});

FormValidator.add('isTime', {
	errorMsg: function(element, props){
		return FormValidator.getMsg('isTime');
	}, 
	test: function(element) {
		var val = element.value;
		var firstNumber = '';
		var i;
		for(i =0; i<2, i<val.length; i++)
		{
			var c = val.charAt(i);
			if (c==':' || c=='.') break;
			else c = Number(c);
			if (isNaN(c)) return false;
			firstNumber+=''+c;
		}
		while (firstNumber.length<2) firstNumber = '0'+firstNumber;
		
		if (Number(firstNumber)>23) return false;
		
		var secondNumber = '';
		i++;
		for(i; i<val.length; i++)
		{
			var c = val.charAt(i);
			c = Number(c);
			if (isNaN(c)) return false;
			secondNumber+=''+c;
			if (secondNumber.length==2) break;
		}
		while (secondNumber.length<2) secondNumber = '0'+secondNumber;
		if (Number(secondNumber)>59) return false;
		
		element.value = firstNumber+':'+secondNumber;
		
		return true;
	}
});

FormValidator.add('minMaxTime', {
	errorMsg: function(element, props){
		var min = element.retrieve('minHour');
		var max = element.retrieve('maxHour');
		return FormValidator.getMsg('minMaxTime').substitute({
			'min':min,
			'max':max
		});
	}, 
	test: function(element) {
		var val = element.value;
		
		var min = element.retrieve('minHour');
		var max = Number(element.retrieve('maxHour'));
		
		if (min<10) min = '0'+min;
		if (max<10) max = '0'+max;
		
		if (val<min+':00' || val > max+':00' ) return false;
		
		return true;
	}
});

MooTools.lang.set('it-IT', 'Date', {

	months: ['Gennaio', 'Febbraio', 'Marzo', 'Aprile', 'Maggio', 'Giugno', 'Luglio', 'Agosto', 'Settembre', 'Ottobre', 'Novembre', 'Dicembre'],
	days: ['Domenica', 'Lunedi', 'Martedi', 'Mercoledi', 'Giovedi', 'Venerdi', 'Sabato'],
	dateOrder: ['date', 'month', 'year', '/'],
	shortDate: '%d/%m/%Y',
	shortTime: '%H:%M',
	AM: 'AM',
	PM: 'PM',

	/* Date.Extras */
	ordinal: function(dayOfMonth){
		//1st, 2nd, 3rd, etc.
		return (dayOfMonth > 3 && dayOfMonth < 21) ? 'th' : ['th', 'st', 'nd', 'rd', 'th'][Math.min(dayOfMonth % 10, 4)];
	},

	lessThanMinuteAgo: 'less than a minute ago',
	minuteAgo: 'about a minute ago',
	minutesAgo: '{delta} minutes ago',
	hourAgo: 'about an hour ago',
	hoursAgo: 'about {delta} hours ago',
	dayAgo: '1 day ago',
	daysAgo: '{delta} days ago',
	lessThanMinuteUntil: 'less than a minute from now',
	minuteUntil: 'about a minute from now',
	minutesUntil: '{delta} minutes from now',
	hourUntil: 'about an hour from now',
	hoursUntil: 'about {delta} hours from now',
	dayUntil: '1 day from now',
	daysUntil: '{delta} days from now'

});

MooTools.lang.setLanguage('it-IT');