OT_Autocompleter = Class.create();
OT_Autocompleter.prototype = {
	/*Costruttore*/
	initialize: function(sourceId, hiddenTargetId, optionsContainerId, url, options){
		this.source = sourceId;							/*Id dell'elemento sorgente per l'autocomplete*/
		this.hiddenTarget = hiddenTargetId;				/*Id dell'elemento che verrà popolato con l'id dell'option selezionata*/
		this.optionsContainer = optionsContainerId;		/*Elemento contenitore delle options, risultato dell'autocomplete*/
		this.url = url;									/*Url da richiamare per ottenere le options*/
		this.lastValue = '';							/*Tiene traccia dell'ultimo valore inserito nel source*/
		
		//inizializzazione dei parametri opzionali
		if(options){
			this.options = {										/*Parametri opzionali*/
				parameterName: options.parameterName || sourceId,	/*Nome con cui verrà inviato il parametro da aggiungere all'url*/
				characters: options.characters || 2					/*Numero di caratteri in seguito al quale inviare le richieste per l'autocomplete*/
			};
		}
		else{
			this.options = {
				parameterName: sourceId,
				characters: 2
			};
		}
	},
	
	/*Rende visibile le options, risultato della richiesta per l'autocomplete
			event:			l'evento che ha richiamato la funzione;
			moreParameters:	parametri aggiuntivi da inviare con l'url;
	*/
	showChoiches: function(event, moreParameters){
		if(moreParameters == undefined){
			moreParameters = '';
		}
		//reset del valore dell'elemento hidden
		$(this.hiddenTarget).value = "";
		
		if($(this.source).value.length >= this.options.characters){
		    //il numero di caratteri digitati è tale per cui la richiesta deve essere inviata; controllo sul tasto premuto
		    if (window.event){
		        //IE
		        key = window.event.keyCode;
		    }
		    else{
		        key = event.which;
		    }
		    if ($(this.source).value != this.lastValue){
				//la stringa inserita è effettivamente cambiata; invio della richiesta
				this.lastValue = $(this.source).value;
				var autoCompleterInstance = this;
				var ajaxRequest = new Ajax.Request(
					this.url, 
					{
						method: 'get', 
						//Per le richieste in get, viene aggiunto un paramtero random per evitare il caching di IE
						parameters: this.options.parameterName + "=" + $(this.source).value + moreParameters + "&sid=" + Math.random(),
						asynchronous: false,
						onComplete: function(originalRequest){autoCompleterInstance.populateOptionsContainer(originalRequest);}
					}
				);
			}
			else if(key == 40 || key == 38){
				//il tasto premuto è 'freccia su/giu'; focus sulla voce corrispondente
				this.focusOption(key);
			}
			else if(key == 13){
				//il tasto premuto è 'invio'; valorizzazione degli elementi in base alla option in cui c'è focus
				this.selectFocusedOption();
			}
		}
		else{
			//numero di caratteri non sufficiente per inviare la richiesta
			Element.hide(this.optionsContainer);
			$(this.optionsContainer).innerHTML = "";
			this.lastValue = '';
		}
	},
	
	/*Visualizza come attiva la option precedente/successiva in base al tasto digitato (freccia su/giu)*/
	focusOption: function(key){
		if($(this.optionsContainer).getElementsByTagName('li').length != 0){
			var lastFocused = $(this.optionsContainer).getElementsByClassName('focused');
			if(key == 40){
				//freccia giu
				if(lastFocused.length == 0){
					//nessun elemento attualmente attivo; focus sul primo
					$(this.optionsContainer).getElementsByTagName('li')[0].className = 'focused';
				}
				else{
					//passaggio del focus sull'elemento successivo
					lastFocused[0].className = '';
					var nextElement = lastFocused[0].nextSiblings()[0];
					if(nextElement != null){
						nextElement.className = 'focused';
					}
				}
			}
			else{
				//freccia su
				if(lastFocused.length == 0){
					//nessun elemento attualmente attivo; focus sull'ultimo
					$(this.optionsContainer).getElementsByTagName('li')[$(this.optionsContainer).getElementsByTagName('li').length - 1].className = 'focused';
				}
				else{
					//passaggio del focus sull'elemento precedente
					lastFocused[0].className = '';
					var previousElement = lastFocused[0].previousSiblings()[0];
					if(previousElement != null){
						previousElement.className = 'focused';
					}
				}
			}
		}
	},
	
	/*Popola i valori degli elementi opportuni in base alla option in cui c'è il focus*/
	selectFocusedOption: function(){
		var lastFocused = $(this.optionsContainer).getElementsByClassName('focused');
		if(lastFocused.length != 0){
			var id = encodeURIComponent(lastFocused[0].id);
			var textValue = encodeURIComponent(lastFocused[0].getElementsByTagName('a')[0].innerHTML);
			eval(lastFocused[0].getAttribute('onclick'));
			this.populateTarget(id, textValue);
		}
	},
	
	/*Alla ricezione della risposta dal server, popola il contenitore delle options*/
	populateOptionsContainer: function(xmlObject){
		var currentAutocompleter = this;
		$(this.optionsContainer).innerHTML = xmlObject.responseText;
		var listElements = $(this.optionsContainer).getElementsByTagName('li');
		for(var i=0; i<listElements.length; i++){
			//creazione option; se presente un evento onclick, questo non viene sovrascitto
			var currentElementOnclick = listElements[i].getAttribute('onclick');
			listElements[i].onclick = function(){eval(currentElementOnclick);currentAutocompleter.populateTarget(encodeURIComponent(this.id), encodeURIComponent(this.getElementsByTagName('a')[0].innerHTML));};
		}
		if($(this.optionsContainer).style.display == 'none'){
			//new Effect.Appear(this.optionsContainer);
			Element.show(this.optionsContainer);
		}
	},
	
	/*Resetta gli elementi per dell'autocomplete; richiamato opzionalmente quando il souce non ha più il focus*/
	reset: function(){
		if($(this.hiddenTarget).value == ''){
			$(this.source).value = '';
			this.lastValue = '';
			Element.hide(this.optionsContainer);
		}
	},
	
	/*Popola i valori dell'elemnto text (sorgente dell'autocomplete) e dell'hidden*/
	populateTarget: function(id, textValue){
		$(this.hiddenTarget).value = decodeURIComponent(id);
		$(this.source).value = decodeURIComponent(textValue);
		Element.hide(this.optionsContainer);
		$(this.optionsContainer).innerHTML = '';
		this.lastValue = '';
	}
};

OT_Combo = Class.create();
OT_Combo.prototype = {
	/*Costruttore*/
	initialize: function(sourceId, targetId, url, options){
		this.source = sourceId;		/*Id del combo box sorgente*/
		this.target = targetId;		/*Id del combo box destinatario*/
		this.url = url;				/*Url da richiamare per ottenere le options per il combo box destinatario*/
		
		//inizializzazione dei parametri opzionali
		if(options){
			this.options = {
				parameterName: options.parameterName || sourceId,				/*Nome con cui verrà inviato il parametro da aggiungere all'url*/
				firstOptionSelect: options.firstOptionSelect || 'true',			/*Indica se visualizzare o no come prima option '--select--'*/
				targetFirstOptionValue: $(this.target).options[0].text || '',	/*Prima option attualmente presente nel combo box di destinazione*/
				autoSelectSingleOption: options.autoSelectSingleOption || 'true'/*Selezionare o meno il primo option se singolo*/
			};
		}
		else{
			//se non personalizzati, inizializzazione con i valori di default
			this.options = {
				parameterName: sourceId,
				firstOptionSelect: 'true',
				targetFirstOptionValue: $(this.target).options[0].text || '',
				autoSelectSingleOption: 'true'
			};
		}
	},
	
	/*Invia all'url la richiesta per ottenere le option con cui popolare la combo box di destinazione*/
	populateSelect: function(){
		if($(this.source).value == '0' || $(this.source).value == ' '){
			//selezione della option senza valore; reset in cascata delle altre combo box
			$(this.target).options[0] = new Option(this.options.targetFirstOptionValue, ' ');
			$(this.target).options.length = 1;
			$(this.target).disabled = true;
			if($(this.target).onchange){
				$(this.target).onchange();
			}
		}
		else{
			//invio della richiesta per ottenere le option con cui popolare la combo box di destinazione
			var comboInstance = this;
			var ajaxRequest = new Ajax.Request(
				this.url, 
				{
					method: 'get',
					asynchronous: false,
					//Per le richieste in get, viene aggiunto un paramtero random per evitare il caching di IE
					parameters: this.options.parameterName + "=" + $(this.source).value + "&sid=" + Math.random(),
					onComplete: function(originalRequest){comboInstance.showTargetOptions(originalRequest);}
				}
			);
		}
	},
	
	/*Popola e attiva la combo box di destinazione*/
	showTargetOptions: function(xmlObject){
		//visualizzazione della prima option, precedentemente nascosta e reset dei valori della combo box di destinazione
		Element.show($(this.target).options[0]);
		$(this.target).options.length = 1;
		
		if(this.options.firstOptionSelect == 'true'){
			//inserimento, se richiesto, della prima option con valore 0 e testo '--select--'
			var firstOptionElement = Builder.node('option', {value: $(this.target).value});
			firstOptionElement.text = '--seleziona--';
			$(this.target).options[$(this.target).options.length] = firstOptionElement;
		}
		//inserimento delle option in base all'xml ritornato dall'url
		var xmlResponse = xmlObject.responseXML;
		var elements = xmlResponse.getElementsByTagName('element');
		if(elements.length == 0){
			var optionElement = Builder.node('option', {value: ' '});
			optionElement.text = 'nessuna corrispondenza';
			$(this.target).options[$(this.target).options.length] = optionElement;
		}
		else{
			for(var i = 0; i < elements.length; i++){
				var elementData = elements[i].firstChild.data;
				var elementId = elements[i].getAttribute('id');
				var optionElement = Builder.node('option', {value: elementId});
				optionElement.text = decodeURIComponent(elementData.replace(/\+/g," "));
				$(this.target).options[$(this.target).options.length] = optionElement;
			}
		}
		$(this.target).options[0] = null;
		$(this.target).options[0].selected = true;
		$(this.target).disabled = false;
		
		if(elements.length == 1 && this.autoSelectSingleOption == 'true'){
			$(this.target).options[$(this.target).options.length - 1].selected = true;
		}
		
	},
	
	repopulateTarget: function(targetValue){
		$(this.source).onchange();
		$A($(this.target).options).each(function(optionElement){
			if(optionElement.value == targetValue){
				optionElement.selected = true;
				$break;
			}
		});
	}
	
};

OT_DraggableBox = Class.create();
OT_DraggableBox.prototype = {
	initialize: function(url, boxId, options){
		this.url = url;
		this.boxId = boxId;
		
		if(options){
			this.options = {
				parameters: options.parameters || ''
			};
		}
		else{
			this.options = {
				parameters: ''
			};
		}
	},
	
	show: function(){
		var currentBoxId = this.boxId;
		var ajaxUpdater = new Ajax.Updater(
		this.boxId + "_content",
		this.url,
		{
			method: 'get',
			evalScripts: true,
			//Per le richieste in get, viene aggiunto un paramtero random per evitare il caching di IE
			parameters: this.options.parameters == '' ? "sid=" + Math.random() : this.options.parameters + "&sid=" + Math.random(),
			onSuccess: function(){
				Element.show(currentBoxId);
				new Draggable(currentBoxId, {handle: 'draggable_' + currentBoxId});
			}
		});
	}
};