if(!ch){
	var ch = {};
}
if(!ch.exmachina){
	ch.exmachina = {};
}
if(!ch.exmachina.bravofly){
	ch.exmachina.bravofly = {};
}
/**
 * Oggetto principale dell'applicazione
 * @namespace ch.exmachina.bravofly.pricesearch
 */

ch.exmachina.bravofly.pricesearch = {
	/**
	 * Url del servizio di autocompletamento per le aree geografiche
	 * @type {String}
	 * @default ""
	 */
	_geoCompleteUrl: "",
	/**
	 * Url del servizio di autocompletamento per gli aeroporti
	 * @type {String}
	 * @default
	 */
	_airportCompleteUrl: "",
	/**
	 * Url del servizio che fornisce informazioni riguardo alla distanza oraria di raggiungibilita'
	 * @type {String}
	 * @default ""
	 */
	_airportReachabilityUrl: "",
	/**
	 * Lingua per l'applicazione
	 * @type {String}
	 * @default "EN"
	 */
	_currentLanguage: "EN",
	/**
	 * Visibilita' dello knob
	 * @type {boolean}
	 * @default true
	 */
	_isKnobVisible: true,
	/**
	 * Testo da mostrare nei campi relativi alle aree geografiche quando non sono ancora stati modificati
	 * @type {String}
	 * @default ""
	 */
	_areaPrompt: "",
	/**
	 * Testo da mostrare nei campi nazione quando l'utente non ha ancora effettuato modifiche dopo la loro creazione
	 * @type {String}
	 * @defaul ""
	 */
	_nationPrompt: "",
	/**
	 * Url a cui puntare per il servizio di autocompletamento delle nazioni
	 * @type {String}
	 * @default ""
	 */
    _nationCompleteUrl: "",
	/**
	 * Cache che contiene i mesi restituiti dal server
	 * @type {Array}
	 * @default []
	 */
    _cachedMonths: [],
	/**
	 * Specifica se la sezione dei mesi deve essere disabilitata o meno
	 * @type {Boolean}
	 * @default true
	 */
    _monthsDisabled: true,
	/**
	 * Mesi disponibili per la scelta dei voli
	 * @type {Array}
	 * @default []
	 */
    _availableMonths: [],
	/**
	 * Messaggi localizzati per il calendario
	 * @type {Array}
	 * @default []
	 */
	_calMessages: [],
	/**
	 * Riferimento al knob, se presente
	 * @type {Object}
	 * @default null
	 */
	_distanceHash: {
			1: {
				start: 1,
				end: 5
			},
			6: {
				start: 6,
				end: 12
			},
			13: {
				start: 13,
				end: 19
			},
			20: {
				start: 20,
				end: 26
			}
    },
    knob: null,
	/**
	 * Restituisce soltanto il tipo di questo oggetto: modificare per ottenere informazioni utili in caso di debug
	 * @returns {String}
	 */
	toString: function(){
		return "[ch.exmachina.bravofly.pricesearch]";
	},
	/**
	 * Contiene la funzione unescapeHTML che restituisce (approssimativamente) l'innerText del nodo
	 * @type {Object}
	 */
	utils: {
		_node: document.createElement("div"),
		unescapeHTML: function(/**String*/s){
			ch.exmachina.bravofly.pricesearch.utils._node.innerHTML = s;
			return ch.exmachina.bravofly.pricesearch.utils._node.innerText || s.unescapeHTML();
		}
	},
	/* members */
	/* price chooser */
	/**
	 * Istanza del pricechooser per questa applicazione
	 * @type {ch.exmachina.bravofly.PriceChooser}
	 * @default {}
	 */
	priceChooser: {},
	/* groups, new implementation */
	/**
	 * Gruppo di campi che fa riferimento all'oggetto knob relativo alla distanza oraria dall'aeroporto di partenza
	 * @type {ch.exmachina.bravofly.FieldGroup}
	 * @default {}
	 */
	departureKnobGroup: {},
	/**
	 * Gruppo di campi relativo agli aeroporti di partenza
	 * @type {ch.exmachina.bravofly.FieldGroup}
	 * @default {}
	 */
	departureAirportsGroup: {},
	/**
	 * Gruppo di campi relativo alle aree geografiche di partenza
	 * @type {ch.exmachina.bravofly.GeographicGroup}
	 * @default {}
	 */
	departureAreaGroup: {},
	/**
	 * Gruppo che fa riferimento ai campi degli aeroporti di partenza
	 * @type {ch.exmachina.bravofly.FieldGroup}
	 * @default {}
	 */
	returnAirGroup: {},
	/**
	 * Gruppo riferito ai campi area per il volo di ritorno
	 * @type {ch.exmachina.bravofly.GeographicGroup}
	 * @default {}
	 */
	returnAreaGroup: {},
	/* counters */
	/**
	 * Contatore dei giorni selezionati per la partenza
	 * @type {Number}
	 * @default 0
	 */
	selectedDepDays: 0,
	/**
	 * Contatore di giorni selezionati per il ritorno
	 * @type {Number}
	 * @default 0
	 */
	selectedRetDays: 0,
	/**
	 * Contatore dei mesi selezionati
	 * @type {Number}
	 * @default 0
	 */
	selectedMonths: 0,
    /*numero massimo dei messi che si possono selezionare */
    maxSelectableMonths: 5,
    /*numero massimo dei messi selezionati all'inizio*/
    initSelectedMonths: 3,

	/* tabs */
	/**
	 * Contiene tutte le informazioni sui gruppi di tab e loro stato nell'applicazione
	 * @type {Object}
	 * @default {}
	 */
	tabGroups: {
		partenzaGroup: {
			selected: "ta_partenzaTab0",
			disabled: false,
			tabs: {
				aeroportiZonaRadio: {
					panel: "ta_partenzaTab0",
					fields: [
						"departureAirports0",
						"departureAirports1",
						"departureAirports2"
					]
				},
				aeroportiManualeRadio: {
					panel: "ta_partenzaTab1",
					fields: [
						"departureGeographicalArea0",
						"departureGeographicalArea1"
					]
				}
			}
		},
		ritornoGroup: {
			disabled: false,
			selected: "ta_ritornoTab1",
			tabs: {
				ta_aeroportoRitornoRadio: {
					panel: "ta_ritornoTab0",
					fields: [
						"arrivalAirports0",
						"arrivalAirports1",
						"arrivalAirports2"
					]
				},
				ta_areaRitornoRadio: {
					panel: "ta_ritornoTab1",
					fields: [
						"arrivalGeographicalArea0",
						"arrivalGeographicalArea1"
					]
				}
			}
		}
	},

	/* methods */
	/**
	 * Recupera la configurazione iniziale: traduzioni, url e altri dati disponibili soltanto a runtime
	 */
	_setCfg: function(){
		var cfg = this.cfg;
		var self = this;

		$("ta_loading_msg").setStyle({
			display: "block"
		});
		new Ajax.Request(cfg.name + '.action', {
        //new Ajax.Request('/pricefinder/pricesearch_search_page_cfg.jsp', {
			asynchronous: false,
	  		method: 'GET',
	  		parameters: {"ts": (new Date()).getTime()}, // avoid caching in IE
			evalJSON: true,
			onSuccess: function(transport){
//                if(!self.isValidData(transport)){ return; }
				var d = transport.responseJSON;
				// refactor
				self.assistant.messages = d["assistant"];

				self._currentLanguage = d["currentLanguage"];
				self._prompts = d["prompts"];
				self._geoCompleteUrl = d["geoCompleteUrl"];
				self._airportCompleteUrl = d["airportCompleteUrl"];
				self._airportReachabilityUrl = d["airportReachabilityUrl"];
				self._nationCompleteUrl = d["nationCompleteUrl"];
				self._geoSelectUrl = d["geoSelectUrl"];
				self._areaPrompt = d["areaPrompt"];
				self._nationPrompt = d["nationPrompt"];
				self._priceList = d["priceList"];
                self._nationCompleteUrl = d["nationCompleteUrl"];
                self._availableMonths = d["availableMonths"];
                self._monthMap = d["monthMap"];
                self._calMessages = d["calendar"];
                self.enabledButton = d["buttonEnable"];
                self.disabledButton = d["buttonDisable"];
				$("ta_loading_msg").setStyle({
					display: "none"
				});
			},
			onFailure: function(){
//				window.alert("Failure loading the configuration file");
				$("ta_loading_msg").setStyle({
					display: "none"
				});
			},
			onException: function(req, exc){
//				window.alert("[pricefinder] Error loading external cfg file! " + exc);
				$("ta_loading_msg").setStyle({
					display: "none"
				});
			}
		});
	},
	/**
	 * Oggetto che espone le funzioni dell'assistente, quali il posizionamento del fumetto e i vari metodi di
	 * visualizzazione dei messaggi
	 * @type {Object}
	 */
	assistant: {
		locked: false,
		_lastPosition: "",
		_isFirstMessage: true,
		initialLock: false,
		visible: false,
		currentMessage: "",
		hideInfo: function(){
			this.visible = false;
			new Effect.Fade("ta_tooltip", {
				duration: 0
			});
		},
		showError: function(args){
			$("ta_tooltip_text").removeClassName("ta_tooltip_content_inside");
			$("ta_tooltip_text").addClassName("ta_tooltip_content_inside_error");
            args.type = "error";
			this.showInfo(args);
		},
		showInfo: function(args){
			//if(this.visible){ return; }
			this.visible = true;
			var message = args.msg,
				aTop = args.top,
				aLeft = args.left,
				lastPosition = args.position,
				force = args.force,
				dir = args.dir,
				duration = args.duration,
				type = args.type || "info"
			;
			//if((/*this._lastPosition === lastPosition && */!force)/* || this._initialLock*/){ return; }
			if(this._isFirstMessage){
				this._initialLock = true;
			}
			if(type === "info" ){
				$("ta_tooltip_text").removeClassName("ta_tooltip_content_inside_error");
				$("ta_tooltip_text").addClassName("ta_tooltip_content_inside");
			}else{
				$("ta_tooltip_text").removeClassName("ta_tooltip_content_inside");
				$("ta_tooltip_text").addClassName("ta_tooltip_content_inside_error");
			}
			var self = this;
			var al = $("ta_tooltip");
			for(var i = 0, d = ["top", "right", "bottom", "left" ]; i < d.length; i++){
				al.removeClassName("ta_tooltip_" + d[i]);
			}
			if(dir){
				al.addClassName("ta_tooltip_" + dir);
			}
			clearTimeout(this._assistantTimeout);
			this.bSay(message);
			with(al.style){
				top = aTop;
				left = aLeft;
			}
			new Effect.Appear("ta_tooltip", {
				duration: .5
			});
//			this._assistantTimeout = setTimeout(function(){
//				self._isFirstMessage = false;
//				self._initialLock = false;
//				self.hideInfo();
//			}, duration);
			this._lastPosition = lastPosition;
			//this.say(message, force);
		},
		bSay: function(msg){
			$("ta_tooltip_text").innerHTML = msg;
		},
		error: function(message, force){
			this._say(message, force, "errorMessage");
		},
		say: function(message, force){
			this._say(message, force, "");
		},
		_say: function(message, force, msgClass){
			if((this.currentMessage !== message && !this.locked) || force){
				var aMessage = $('ta_assistant_message');
				aMessage.innerHTML = "<span class=\"" + msgClass + "\">" + ch.exmachina.bravofly.pricesearch.utils.unescapeHTML(message) + "</span>";
				aMessage.hide();
				new Effect.Appear('ta_assistant_message', { duration: .5 });
				this.currentMessage = message;
			}
		},
		lock: function(/** number */ time){
			var self = this;
			this.locked = true;
			setInterval(function(){ self.locked = false}, time);
		},
		messages: {}
	},
	/**
	 * Si occupa di costruire il pricechooser per questa applicazione
	 */
	makePriceChooser: function(){
        var self = this;
		this.priceChooser = new ch.exmachina.bravofly.PriceChooser({
			data: this.cfg.pdata,
            onEnable: function(){
                $("ta_enable_pricechooser").style.display = "none";
            },
            onDisable: function(){
                $("ta_enable_pricechooser").style.display = "block";
            },
            onCreate: function(){
                // il nodo di abilitazione deve sovrastare il price chooser
/*
                console.log("shift");
                var n = $("ta_enable_pricechooser");
                n.parentNode.appendChild(n);
*/
            },
            onArrowClick: function(){
            	//self.assistant.hideInfo();
            },
            onChange: function(){
                self.enableStep(1);
                self.setDepartureData(this.getValue());
            },
			pNode: "ta_priceChooser"
		});
	},
	/**
	 * Crea i gruppi di campi per questa applicazione in base alla configurazione iniziale
	 */
	makeFieldGroups: function(){
        var self = this,
            defaultNation = "",
            nationReadOnly = false,
            continentCode = "",
            countryCode = "",
            departureAspect = "overlapped",
            depAreaDataKey = "",
            fieldType = "",
            onDepartureSelectionChange = function(){},
            onReturnSelectionChange = function(){},
            onFirstSelectionChange = function(){}
        ;
        // *************************************************** BLOCCO CIBAVISION
		if(this.cfg.type == "pricesearch_h"){
            defaultNation = "";
            nationReadOnly = false;
            depAreaDataKey = "availableDepartureGeoArea";
            continentCode = "EU";
            countryCode = "IT";
            departureAspect = "doubleSelect";//"standard";
            fieldType = "select";
            onFirstSelectionChange = function(){
                this.firstOption = false;
                this.listData.shift();
                this.selectedIndex--;
                this.createList();
            };
            onDepartureSelectionChange = function(){
                var params = { departureAirports: [ ] },
                    dag = self.departureAirportsGroup,
                    rag = self.returnAirGroup
                ;
                for(var i = 0; i < dag.fields.length; i++){
                    params.departureAirports.push(dag.fields[i].getKey());
                }
                rag.selectUrlParameters = params;
                if(dag.atLeastOneValid()){
                    //rag.loadData();
                    // spostare questa chiamata a livello app
                    // devo recuperare il dato e spedirlo nel gruppo corrispondente
                    self.loadCibaReturnData({
                        cback: function(){
                            // nr 05 feb 2009b
                            // disabilitazione del blocco con il priceChooser
                            self.priceChooser.disable();
                            // nr 05 feb 2009e
                            self.enableBlock('ta_arrival');
                            self.enableStep(2);
                        },
                        parameters: params
                    });
                }else{
                    self.disableBlock('ta_arrival');
//                    self.enableStep(1);
                }
            };
            onReturnSelectionChange = function(){
                var params = { destinationAirports: [ ] },
                    dag = self.departureAirportsGroup,
                    rag = self.returnAirGroup
                ;
                for(var i = 0; i < rag.fields.length; i++){
                    params.destinationAirports.push(rag.fields[i].getKey());
                }
                //rag.selectUrlParameters = params; // <--- sostituire con "blocco mesi"
                if(rag.atLeastOneValid()){

                    self.loadMonths({ cback: function(){
                        this.disableBlock('ta_partenza');
                        $('ta_modifica_partenza').setStyle({
                        	display: "block"
                        });
                        $('ta_step_one_circle').setStyle({
                            display: "none"
                        });
                    }});
                }
            };
        }
        this.departureAirportsGroup = new ch.exmachina.bravofly.GeographicGroup({
            maxFields: 3,
            autocompleteURL: self._geoCompleteUrl,
            nationCompleteUrl: self._nationCompleteUrl,
            domNode: "ta_departureAirGroup",
            addNode: "ta_add_departure_airport",
//            domNode: "ta_departure_geo_input",
            aspect: departureAspect,
            containerNode: "ta_departureAirGroup", // changed
//            addNode: "ta_add_departure_area",
            datasource: "static",
            areaDataKey: depAreaDataKey,
            asynchAreaLoad: (this.cfg.type != "pricesearch_h"),
            areaPrompt: ch.exmachina.bravofly.pricesearch.utils.unescapeHTML(this._areaPrompt),
            nationPrompt: ch.exmachina.bravofly.pricesearch.utils.unescapeHTML(this._nationPrompt),
            searchLanguage: this._currentLanguage,
            nationReadOnly: nationReadOnly,
            defaultNation: defaultNation,
            selectClass: ch.exmachina.bravofly.ComplexSelect,
            onAddChild: function(){
                if(this.fields.length === this.maxFields){
                    this.hideAddNode();
                }
	        	this.setCloserButtons();
				// validazioni strette, non è valido appena aggiunto un campo
	            self.returnAirGroup.disable && self.disableBlock("ta_arrival");
            },
            onChangeNation: function(){
                var enclosingObject = this.enclosingObject,
                    dag = enclosingObject.pGroup,
                    n = dag.nations,
                    areas = []
                ;
                areas.push({ key: "", value: n[this.selectedIndex].key ? "&lt;" + self._prompts.airport + "&gt;" : "---" });
                if(n[this.selectedIndex].key){
                    for(var i = 0; i < dag.groupData.length; i++){
                        if(dag.groupData[i].description == n[this.selectedIndex].key){
                            areas.push(dag.groupData[i]);
                        }
                    }
                }
	            if(areas.length == 2){
                    enclosingObject.areaField.onFirstChange = function(){};
                    this.firstOption = false;
					areas.shift();
					this.createList();
					if(!areas[0] || areas[0].key === ""){
						enclosingObject.areaField.fillInData([{ key: "", value: "" ? "" : "---" }]);
						this.enclosingObject.pGroup.disableAddNode();
					}else{
						enclosingObject.areaField.fillInData(areas);
					}
                    enclosingObject.onChangeArea.call(this);
                }else if(areas.length > 2){
                    enclosingObject.areaField.onFirstChange = function(){
                        this.firstOption = false;
                        this.listData.shift();
                        this.selectedIndex--;
                        this.createList();
                    };
                    enclosingObject.areaField.fillInData(areas);
		            enclosingObject.onChangeArea.call(this);
		            // 11-03-2009, disabilitare periodi quando non c'è una partenza
		            if(!this.enclosingObject.pGroup.atLeastOneValid()){
			            this.enclosingObject.pGroup.disableAddNode();
		            }
                }
            },
            onRemoveChild: function(){
                // mantenere la consistenza (...) dell'interfaccia,
                // eventuale rimozione di fields con dati non validi nel semicerchio della destinazione
                // AREE ************************************************************************************************
                if(self.cfg.type == "pricesearch_h"){
                    var params = { departureAirports: [ ] },
                        dag = self.departureAirportsGroup,
                        rag = self.returnAirGroup
                    ;
                    for(var i = 0; i < dag.fields.length; i++){
                        dag.fields[i].areaField.getKey() && params.departureAirports.push(dag.fields[i].areaField.getKey());
                    }
                    rag.selectUrlParameters = params;
                    if(dag.atLeastOneValid()){
                        //rag.loadData();
                        // spostare questa chiamata a livello app
                        // devo recuperare il dato e spedirlo nel gruppo corrispondente
                        self.loadCibaReturnData({
                            cback: function(){
                                self.enableBlock('ta_arrival');
                                self.enableStep(2);
                            },
                            parameters: params
                        });
                        this.addNode && this.enableAddNode();
                    }else{
                        this.addNode && this.disableAddNode();
                        self.disableBlock("ta_arrival");
                    }
                }
            },
            onChangeArea: function(){
                // controllare che sia valida la select
                // in caso positivo, eseguire i soliti controlli sulla validità di gruppo
                // AREE ************************************************************************************************
                if(this.enclosingObject.pGroup.allAreasValid()){
                    if(this.enclosingObject.pGroup.fields.length < this.enclosingObject.pGroup.maxFields){
                        this.enclosingObject.pGroup.enableAddNode();
                    }
//                    self.enableBlock("ta_arrival");
                    // nome del parametro: departureGeoAreas
                    var params = { departureAirports: [ ] },
                        dag = self.departureAirportsGroup,
                        rag = self.returnAirGroup
                    ;
                    for(var i = 0; i < dag.fields.length; i++){
                        dag.fields[i].areaField.getKey() && params.departureAirports.push(dag.fields[i].areaField.getKey());
                    }
                    rag.selectUrlParameters = params;
                    if(dag.atLeastOneValid()){
                        self.loadCibaReturnData({
                            cback: function(){
                                self.priceChooser.disable();
                                self.enableBlock('ta_arrival');
                                self.enableStep(2);
                            },
                            parameters: params
                        });
                    }else{
                        self.disableBlock('ta_arrival');
                        self.enableStep(1);
                    }
                }else{
                    self.disableBlock("ta_arrival");
                }
            },
            onFirstSelectionChange: onFirstSelectionChange,
            firstOption: (this.cfg.type == "pricesearch_h") ? { imposedClassName: "ta_deadItem", key: "-", value: this._prompts["filterList"] } : null,
            onComplete: function(){
            }
        });
        this.departureAirportsGroup.setCloserButtons();
        this.returnAirGroup = new ch.exmachina.bravofly.GeographicGroup({
            maxFields: 3,
            domNode: "ta_returnAirGroup",
            addNode: "ta_add_return_air",
            autocompleteURL: self._geoCompleteUrl,
            nationCompleteUrl: self._nationCompleteUrl,
            aspect: (this.cfg.type == "pricesearch_h") ? "doubleSelect" : "",
            continentCode: continentCode,
            containerNode: "ta_returnAirGroup",
            selectClass: ch.exmachina.bravofly.ComplexSelect,
            nationReadOnly: true,
            onAddChild: function(){
                if(this.fields.length === this.maxFields){
                    this.hideAddNode();
                }
	            self.disableBlock("ta_when");
            },
            onRemoveChild: function(){
                if(self.cfg.type == "pricesearch_h"){
                    if(this.atLeastOneValid()){
                        // reload months
                        self.loadMonths();
                    }else{
                        // disable the months block
                        self.disableBlock('ta_when');
                    }
                }
                if(this.addNode){
                    if(!this.atLeastOneValid()){
                        this.disableAddNode();
                    }else{
                        this.enableAddNode();
                    }
                }
            },
            onFirstSelectionChange: onFirstSelectionChange,
            firstOption: (this.cfg.type == "pricesearch_h") ? { imposedClassName: "ta_deadItem", key: "-", value: this._prompts["filterList"] } : null,
            onChangeNation: function(){
                var enclosingObject = this.enclosingObject,
                    rag = enclosingObject.pGroup,
                    n = rag.nations,
                    areas = []
                ;
                areas.push({ key: "", value: n[this.selectedIndex].key ? "&lt;" + self._prompts.airport + "&gt;" : "---" });
                if(n[this.selectedIndex].key){
                    for(var i = 0; i < rag.groupData.length; i++){
                        if(rag.groupData[i].description == n[this.selectedIndex].key){
                            areas.push(rag.groupData[i]);
                        }
                    }
                    // bloccare l'area di partenza
                    //self.disableBlock('ta_partenza');
                }
                if(areas.length == 2){
                    // 07-jan-2008
                    // areas.length == 2
                    // in questo caso la select delle aree geografiche deve avere subito
                    // selezionata l'unica zona disponibile
                    enclosingObject.areaField.onFirstChange = function(){};
                    this.firstOption = false;
                    areas.shift();
                    this.createList();
                    // a questo punto devo chiamare esplicitamente la funzione che scatta
                    // alla selezione dell'area
                    // FIXME: problema di validità
	                if(!areas[0] || areas[0].key === ""){
		                enclosingObject.areaField.fillInData([{ key: "", value: "" ? "" : "---" }]);
		                this.enclosingObject.pGroup.disableAddNode();
	                }else{
		                enclosingObject.areaField.fillInData(areas);
	                }
                    enclosingObject.onChangeArea.call(this);
                }else{
                    enclosingObject.areaField.onFirstChange = function(){
                        this.firstOption = false;
                        this.listData.shift();
                        this.selectedIndex--;
                        this.createList();
                    };
                    enclosingObject.areaField.fillInData(areas);
	                enclosingObject.onChangeArea.call(this);
	                // 11-03-2009, disabilitare periodi quando non c'è un arrivo valido
	                if(!this.enclosingObject.pGroup.atLeastOneValid()){
		                this.enclosingObject.pGroup.disableAddNode();
	                }
                }
            },
            areaPrompt: ch.exmachina.bravofly.pricesearch.utils.unescapeHTML(this._areaPrompt),
            nationPrompt: ch.exmachina.bravofly.pricesearch.utils.unescapeHTML(this._nationPrompt),
            onChangeArea: function(){
                if(this.enclosingObject.pGroup.allAreasValid()){
                    self.disableBlock("ta_partenza");
                    if(this.enclosingObject.pGroup.fields.length < this.enclosingObject.pGroup.maxFields){
                        this.enclosingObject.pGroup.enableAddNode();
                    }
                    self.loadMonths({ cback: function(){
                        this.disableBlock('ta_partenza');
                        $('ta_modifica_partenza').setStyle({
                            display: "block"
                        });
                        $('ta_step_one_circle').setStyle({
                            display: "none"
                        });
                    }});
                }else{
	               // disabilitare zona mesi
	                self.disableBlock('ta_when');
                }
            },
            onComplete: function(){
            }
        });
		this.departureAreaGroup = new ch.exmachina.bravofly.GeographicGroup({
			autocompleteURL: self._geoCompleteUrl,
            nationCompleteUrl: self._nationCompleteUrl,
			domNode: "ta_departure_geo_input",
            aspect: departureAspect,
			containerNode: "ta_departureAreaGroup",
			addNode: "ta_add_departure_area",
            datasource: "net",
            areaDataKey: depAreaDataKey,
            asynchAreaLoad: (this.cfg.type != "pricesearch_h"),
			areaPrompt: ch.exmachina.bravofly.pricesearch.utils.unescapeHTML(this._areaPrompt),
			nationPrompt: ch.exmachina.bravofly.pricesearch.utils.unescapeHTML(this._nationPrompt),
			searchLanguage: this._currentLanguage,
            nationReadOnly: nationReadOnly,
            selectClass: ch.exmachina.bravofly.ComplexSelect,
            defaultNation: defaultNation,
            selectUrl:  (self.cfg.type == "pricesearch_h") ? "pricedeparture.action" : self._geoCompleteUrl,//"suggest/GeographicalArea",
            onAddChild: function(){
	        	if(this.fields.length === this.maxFields){
	        		this.hideAddNode();
	        	}
	        	this.setCloserButtons();
	            self.returnAreaGroup.disable && self.disableBlock("ta_arrival");
			},
            onChangeNation: function(){
                var enclosingObject = this.enclosingObject,
                    rarg = enclosingObject.pGroup,
                    n = rarg.nations,
                    areas = []
                ;
                areas.push({ key: "", value: n[this.selectedIndex].key ? "&lt;" + self._prompts.geoArea + "&gt;" : "---" });
                if(n[this.selectedIndex].key){
                    for(var i = 0; i < rarg.groupData.length; i++){
                        if(rarg.groupData[i].description == n[this.selectedIndex].key){
                            areas.push(rarg.groupData[i]);
                        }
                    }
                    // bloccare l'area di partenza
                    //self.disableBlock('ta_partenza');
                }
                if(areas.length == 2){
                	// 07-jan-2008
                    // areas.length == 2
                	// in questo caso la select delle aree geografiche deve avere subito
                	// selezionata l'unica zona disponibile
                	enclosingObject.areaField.onFirstChange = function(){};
                    this.firstOption = false;
                    areas.shift();
                    this.createList();
                    // a questo punto devo chiamare esplicitamente la funzione che scatta
                    // alla selezione dell'area
                    // FIXME: problema di validità
	                if(!areas[0] || areas[0].key === ""){
		                enclosingObject.areaField.fillInData([{ key: "", value: "" ? "" : "---" }]);
		                this.enclosingObject.pGroup.disableAddNode();
	                }else{
		                enclosingObject.areaField.fillInData(areas);
	                }
                    enclosingObject.onChangeArea.call(this);
                }else{
                	enclosingObject.areaField.onFirstChange = function(){
                        this.firstOption = false;
                        this.listData.shift();
                        this.selectedIndex--;
                        this.createList();
                    };
                    enclosingObject.areaField.fillInData(areas);
	                enclosingObject.onChangeArea.call(this);
	                // 11-03-2009, disabilitare periodi quando non c'è una partenza
	                if(!this.enclosingObject.pGroup.atLeastOneValid()){
		                this.enclosingObject.pGroup.disableAddNode();
	                }
                }
            },
            onRemoveChild: function(){
				// mantenere la consistenza (...) dell'interfaccia,
				// eventuale rimozione di fields con dati non validi nel semicerchio della destinazione
                // AREE ************************************************************************************************
				if(self.cfg.type == "pricesearch_h"){
		            var params = { departureAirports: [ ] },
			            darg = self.departureAreaGroup,
			            rag = self.returnAirGroup
			        ;
			        for(var i = 0; i < darg.fields.length; i++){
			        	darg.fields[i].areaField.getKey() && params.departureAirports.push(darg.fields[i].areaField.getKey());
			        }
			        rag.selectUrlParameters = params;
			        if(darg.atLeastOneValid()){
			            //rag.loadData();
			            // spostare questa chiamata a livello app
			            // devo recuperare il dato e spedirlo nel gruppo corrispondente
			            self.loadCibaReturnData({
			                cback: function(){
			                    self.enableBlock('ta_arrival');
			                    self.enableStep(2);
			                },
			                parameters: params
			            });
			            this.addNode && this.enableAddNode();
			        }else{
			        	this.addNode && this.disableAddNode();
                        self.disableBlock("ta_arrival");
			        }
				}
			},
            onChangeArea: function(){
				// controllare che sia valida la select
				// in caso positivo, eseguire i soliti controlli sulla validità di gruppo
                // AREE ************************************************************************************************
                if(this.enclosingObject.pGroup.allAreasValid()){
                    if(this.enclosingObject.pGroup.fields.length < this.enclosingObject.pGroup.maxFields){
                    	// nicola, aggiungere qui anche con
                        this.enclosingObject.pGroup.enableAddNode();
                    }
//                    self.enableBlock("ta_arrival");
                    // nome del parametro: departureGeoAreas
                    var params = { departureAirports: [ ] },
	                    darg = self.departureAreaGroup,
	                    rag = self.returnAirGroup
	                ;
	                for(var i = 0; i < darg.fields.length; i++){
	                	darg.fields[i].areaField.getKey() && params.departureAirports.push(darg.fields[i].areaField.getKey());
	                }
	                rag.selectUrlParameters = params;
	                if(darg.atLeastOneValid()){
	                    //rag.loadData();
	                    // spostare questa chiamata a livello app
	                    // devo recuperare il dato e spedirlo nel gruppo corrispondente
	                    self.loadCibaReturnData({
	                        cback: function(){
                                self.priceChooser.disable();
	                            self.enableBlock('ta_arrival');
	                            self.enableStep(2);
	                        },
	                        parameters: params
	                    });
	                }else{
	                    self.disableBlock('ta_arrival');
	                    // la seguente potrebbe non servire, controllare
	                    self.enableStep(1);
	                }
                }else{
                    self.disableBlock("ta_arrival");
                }
			},
            onFirstSelectionChange: onFirstSelectionChange,
            firstOption: (this.cfg.type == "pricesearch_h") ? { imposedClassName: "ta_deadItem", key: "-", value: this._prompts["filterList"] } : null,
			onComplete: function(){
			}
		});
        this.departureAreaGroup.setCloserButtons();

		this.returnAreaGroup = new ch.exmachina.bravofly.GeographicGroup({
			autocompleteURL: self._geoCompleteUrl,
            nationCompleteUrl: self._nationCompleteUrl,
			domNode: "ta_return_geo_input",
            aspect: (this.cfg.type == "pricesearch_h") ? "doubleSelect" : "",
            continentCode: continentCode,
			containerNode: "ta_returnAreaGroup",
			addNode: "ta_add_return_area",
            selectClass: ch.exmachina.bravofly.ComplexSelect,
			nationReadOnly: true,
            onAddChild: function(){
	        	if(this.fields.length === this.maxFields){
	        		this.hideAddNode();
	        	}
	            self.disableBlock("ta_when");
			},
			onRemoveChild: function(){
				if(self.cfg.type == "pricesearch_h"){
					if(this.atLeastOneValid()){
						// reload months
	                    self.loadMonths();
					}else{
						// disable the months block
						self.disableBlock('ta_when');
					}
				}
				if(this.addNode){
					if(!this.atLeastOneValid()){
						this.disableAddNode();
					}else{
						this.enableAddNode();
					}
				}
			},
			onFirstSelectionChange: onFirstSelectionChange,
            firstOption: (this.cfg.type == "pricesearch_h") ? { imposedClassName: "ta_deadItem", key: "-", value: this._prompts["filterList"] } : null,
            onChangeNation: function(){
                var enclosingObject = this.enclosingObject,
                    rarg = enclosingObject.pGroup,
                    n = rarg.nations,
                    areas = []
                ;
                areas.push({ key: "", value: n[this.selectedIndex].key ? "&lt;" + self._prompts.geoArea + "&gt;" : "---" });
                if(n[this.selectedIndex].key){
                    for(var i = 0; i < rarg.groupData.length; i++){
                        if(rarg.groupData[i].description == n[this.selectedIndex].key){
                            areas.push(rarg.groupData[i]);
                        }
                    }
                    // bloccare l'area di partenza
                    //self.disableBlock('ta_partenza');
                }
                if(areas.length == 2){
                	// 07-jan-2008
                    // areas.length == 2
                	// in questo caso la select delle aree geografiche deve avere subito
                	// selezionata l'unica zona disponibile
                	enclosingObject.areaField.onFirstChange = function(){};
                    this.firstOption = false;
                    areas.shift();
                    this.createList();
                    // a questo punto devo chiamare esplicitamente la funzione che scatta
                    // alla selezione dell'area
                    // FIXME: problema di validità
	                if(!areas[0] || areas[0].key === ""){
		                enclosingObject.areaField.fillInData([{ key: "", value: "" ? "" : "---" }]);
		                this.enclosingObject.pGroup.disableAddNode();
	                }else{
		                enclosingObject.areaField.fillInData(areas);
	                }
                    enclosingObject.onChangeArea.call(this);
                }else{
                	enclosingObject.areaField.onFirstChange = function(){
                        this.firstOption = false;
                        this.listData.shift();
                        this.selectedIndex--;
                        this.createList();
                    };
                    enclosingObject.areaField.fillInData(areas);
	                enclosingObject.onChangeArea.call(this);
//	                // 11-03-2009, disabilitare periodi quando non c'è un arrivo valido
	                if(!this.enclosingObject.pGroup.atLeastOneValid()){
		                this.enclosingObject.pGroup.disableAddNode();
	                }
                }
            },
			areaPrompt: ch.exmachina.bravofly.pricesearch.utils.unescapeHTML(this._areaPrompt),
			nationPrompt: ch.exmachina.bravofly.pricesearch.utils.unescapeHTML(this._nationPrompt),
            onChangeArea: function(){
                if(this.enclosingObject.pGroup.allAreasValid()){
                	self.disableBlock("ta_partenza");
                    if(this.enclosingObject.pGroup.fields.length < this.enclosingObject.pGroup.maxFields){
                        this.enclosingObject.pGroup.enableAddNode();
                    }
                    self.loadMonths({ cback: function(){
                        this.disableBlock('ta_partenza');
                        $('ta_modifica_partenza').setStyle({
                        	display: "block"
                        });
                        $('ta_step_one_circle').setStyle({
                            display: "none"
                        });
                    }});
                }else{
	               // disabilitare zona mesi
	                self.disableBlock('ta_when');
                }
            },
			onComplete: function(){
//				var pGroup = this.pGroup;
//				if(this.fields.length < this.maxFields){
//					$("ta_add_departure_airport").className = "ta_new_airport";
//				}
			}
		});
	},
	/**
	 * Mostra, abilita e seleziona i mesi passati nell'argomento
	 * @param {Array} months
	 */
    displayMonths: function(/** Array */ months){
        // abilito il blocco dei mesi
		var self = this;
        self.enableBlock('ta_when');
        this.enableStep(3);
        var cmonth,
            months_on = 0
        ;
        this.calendar
            .disableAllMonths()
            .enableMonths(months)
            .selectAllMonths(self.initSelectedMonths)
        ;
//        self.selectedMonths = months_on;
    },
	/**
	 * Carica i mesi
	 * @param {Object} args
	 */
    loadMonths: function(/** Object */ args){
        // costruire i parametri per la chiamata in base
        // alla configurazione dei gruppi
        var
            tg = this.tabGroups,
            dag = this.departureAirportsGroup,
            rag = this.returnAirGroup,
            darg = this.departureAreaGroup,
            rarg = this.returnAreaGroup,
            depList = [],
            arrList = [],
            depKey = "",
            arrKey = "",
            depTempKey = "",
            arrTempKey = "",
            params = {},
            departureSelection = args && args.forcedDeparture ?  args.forcedDeparture : tg.partenzaGroup.selected,
            arrivalSelection = args && args.forcedReturn ? args.forcedReturn : tg.ritornoGroup.selected
        ;
        if(departureSelection === "ta_partenzaTab0"){
            depKey = "departureAirports";
            for(var i = 0; i < dag.fields.length; i++){
                (depTempKey = dag.fields[i].areaField.getKey()) && depList.push(depTempKey);
            }
        }else{
            // areas
            depKey = "departureAirports";
            for(i = 0; i < darg.fields.length; i++){
                (arrTempKey = darg.fields[i].areaField.getKey()) && depList.push(arrTempKey);
            }
        }
        params[depKey] = depList;
        if(arrivalSelection === "ta_ritornoTab0"){
            arrKey = "arrivalAirports";
            for(i = 0; i < rag.fields.length; i++){
                (depTempKey = rag.fields[i].areaField.getKey()) && arrList.push(depTempKey);
            }
        }else{
            // areas
            arrKey = "arrivalAirports";
            for(i = 0; i < rarg.fields.length; i++){
                (arrTempKey = rarg.fields[i].areaField.getKey()) && arrList.push(arrTempKey);
            }
        }
        params[arrKey] = arrList;
        params["asynch"] = args ? args["asynch"] : null;
        this._loadMonthsData(params, args && args.cback ? args.cback : null);
    },
    _loadMonthsData: function(/** Object */ params, cback){
    	var self = this,
        asynch = params.asynch === false ? false : true
        ;
        params["price"] = this.priceChooser.getValue();
	    $("ta_loading_msg").setStyle({
			display: "block"
		});
        new Ajax.Request("priceperiods.action", {
            asynchronous: asynch,
            method: 'POST',
            evalJSON: true,
            parameters: params,
            onSuccess: function(transport){
                if(!self.isValidData(transport)){ return; }
        		var cm = self._cachedMonths = transport.responseJSON["availableMonth"];
                self.displayMonths(cm);
                cback && cback.call(self);
	            $("ta_loading_msg").setStyle({
			        display: "none"
		        });
            },
            onFailure: function(){
                window.alert("load months failure");
	            $("ta_loading_msg").setStyle({
			        display: "none"
		        });
            },
            onException: function(req, exc){
                window.alert(this + " " + exc);
	            $("ta_loading_msg").setStyle({
			        display: "none"
		        });
            }
        });

    },
    enableBlock: function(/** String */ blockId){
        var trg = $(blockId);
        trg.hasClassName("ta_disabledBlock") && trg.removeClassName("ta_disabledBlock");
        switch(blockId){
            case "ta_partenza":
            	this.departureAirportsGroup.enable();
            	this.departureAreaGroup.enable();
            	this.tabGroups.partenzaGroup.disabled = false;
            break;
            case "ta_arrival":
            	this.returnAirGroup.enable();
            	this.returnAreaGroup.enable();
            	this.tabGroups.ritornoGroup.disabled = false;
            break;
            case "ta_when":
                this.calendar.enable();
//            	this.tabGroups.partenzaGroup.disabled = false;
                var btn = $("trovaVoli").firstChild;
                btn.style.cursor = "pointer";
            	$("trovaVoli").firstChild.src = this.enabledButton;
            	this._monthsDisabled = false;
            break;
            default:
            break;
        }
    },
    disableBlock: function(/** String */ blockId){
        var trg = $(blockId);
        !trg.hasClassName("ta_disabledBlock") && trg.addClassName("ta_disabledBlock");
        switch(blockId){
            case "ta_partenza":
            	this.departureAirportsGroup.disable();
            	this.departureAreaGroup.disable();
            	this.tabGroups.partenzaGroup.disabled = true;
            	// disabilito singolarmente gli oggetti del primo blocco
                var dag = this.departureAirportsGroup,
                	darg = this.departureAreaGroup
                ;

//            	$('ta_step_one_circle').hide();
                for(var i = 0; i < dag.fields.length; i++){
                    dag.fields[i].nationField.disable({
                        keepData: true
                    });
                    dag.fields[i].areaField.disable({
                        keepData: true
                    });
                }
                for(i = 0; i < darg.fields.length; i++){
                    darg.fields[i].nationField.disable({
                        keepData: true
                    });
                    darg.fields[i].areaField.disable({
                        keepData: true
                    });
                }
            break;
            case "ta_arrival":
            	this.returnAirGroup.disable();
            	this.returnAreaGroup.disable();
            	this.tabGroups.ritornoGroup.disabled = true;
//                $("ta_stepTwo").removeClassName("ta_step_current");
            	// disabilito singolarmente gli oggetti del secondo blocco
                var rag = this.returnAirGroup,
                	rarg = this.returnAreaGroup
                ;

//            	$('ta_step_two_circle').hide();
                for(i = 0; i < rag.fields.length; i++){
                    rag.fields[i].disable({
                        keepData: true
                    });
                }
                for(i = 0; i < rarg.fields.length; i++){
                    rarg.fields[i].nationField.disable({
                        keepData: true
                    });
                    rarg.fields[i].areaField.disable({
                        keepData: true
                    });
                }
            break;
            case "ta_when":
                this.calendar.disable();
                var btn = $("trovaVoli").firstChild;
                btn.style.cursor = "";
            	btn.src = this.disabledButton;
            	this._monthsDisabled = true;
            break;
            default:
            break;
        }
    },
    setupPricesearchCallbacks: function(){
    	// questo metodo genererà delle callback aggiuntive da eseguire in caso di pagina
    	// d'errore o di ritorno da ricerca per modificare i criteri
    	if(this.cfg.type != "pricesearch_h"){
    		return;
    	}
    },
    makeCibavisionReturnFieldGroups: function(){
    	if(this.cfg.type != "pricesearch_h"){
    		return;
    	}
    },
    setupCibavisionReturn: function(){
    	if($F("errorPage") != "true" && $F("ta_searchAgain") != "true"){
    		return;
    	}
    	if(this.cfg.type != "pricesearch_h"){
    		return;
    	}
    	// costruzione dei campi in caso di errore / riesecuzione ricerca
    	var depAirsCounter = 0,
    		depAreasCounter = 0,
    		retAirsCounter = 0,
    		retAreasCounter = 0,
	    	airKeys = [],
	    	areaKeys = [],
	    	self = this,
			dag = this.departureAirportsGroup,
			darg = this.departureAreaGroup,
			rarg = this.returnAreaGroup,
			rag = this.returnAirGroup,
            forcedDeparture = "",
            forcedReturn = ""
    	;
        var getNationFromArea = function(args){
            var a = args.area,
                grp  = args.grp,
                gd = grp.groupData
            ;
            for(var i in gd){
                if(gd[i].key == a){
                    return gd[i].description;
                }
            }
            return null;
        };
    	// DEPARTURE AIRPORTS___________________________________________________
    	for(var i = 0; i < 3; i++){
			var val = $("departureAirports" + i).value;
			if(val){
				airKeys.push(val);
				depAirsCounter++;
			}
		}
        // fin qui ok
    	for(i = 0; i < depAirsCounter - 1; i++){
			dag.createField();
    	}
    	for(i = 0; i < depAreasCounter - 1; i++){
			darg.createField();
    	}
        this.setDepartureData();
        // riempimento dei campi
        for(i = 0; i < airKeys.length; i++){
            dag.fields[i].nationField.setIndex(dag.fields[i].nationField.getKeyIndex(getNationFromArea({ area: airKeys[i], grp: dag })));
        }
        for(var k = 0; k < airKeys.length; k++){
            var areas = [];
            for(i = 0; i < dag.groupData.length; i++){
                if(dag.groupData[i].description == getNationFromArea({ area: $F("departureAirports" + k), grp: dag })){
                    areas.push(dag.groupData[i]);
                }
            }
            dag.fields[k].areaField.fillInData(areas);
            dag.fields[k].areaField.setKey($F("departureAirports" + k));
            dag.fields[k].areaField.onFirstChange = function(){};
        }

    	// DEPARTURE AREAS______________________________________________________
    	for(i = 0; i < 2; i++){
			val = $("departureGeographicalArea" + i).value;
			if(val){
				areaKeys.push(val);
				depAreasCounter++;
			}
		}
    	// rimpiazzare solo con il riempimento delle select con i dati nella cache di gruppo
//        this.setDepartureData();
    	// riempimento dei campi
        for(i = 0; i < areaKeys.length; i++){
            darg.fields[i].nationField.setIndex(darg.fields[i].nationField.getKeyIndex(getNationFromArea({ area: areaKeys[i], grp: darg })));
        }
        for(k = 0; k < areaKeys.length; k++){
            var areas = [];
            for(i = 0; i < darg.groupData.length; i++){
                if(darg.groupData[i].description == getNationFromArea({ area: $F("departureGeographicalArea" + k), grp: darg })){
                    areas.push(darg.groupData[i]);
                }
            }
            darg.fields[k].areaField.fillInData(areas);
            darg.fields[k].areaField.setKey($F("departureGeographicalArea" + k));
            darg.fields[k].areaField.onFirstChange = function(){};
        }

    	// RETURN ZONE__________________________________________________________
    	// caricamento *sincrono* dei dati
    	var params;
    	if(depAirsCounter){
        	params = { departureAirports: [ ] };
    	}
        if(depAreasCounter){
        	params = { departureAirports: [ ] };
        }
	    for(i = 0; i < depAirsCounter; i++){
	        params.departureAirports && params.departureAirports.push(dag.fields[i].areaField.getKey());
	    }
        //
        for(i = 0; i < depAreasCounter; i++){
	        params.departureAirports && params.departureAirports.push(darg.fields[i].areaField.getKey());
	    }
        //
	    rag.selectUrlParameters = params;
        // creazione campi per il ritorno
        airKeys = [];
    	for(i = 0; i < 3; i++){
			val = $("arrivalAirports" + i).value;
			if(val){
				airKeys.push(val);
				retAirsCounter++;
			}
		}
    	for(i = 0; i < retAirsCounter - 1; i++){
			rag.createField();
    	}

    	// RETURN AREAS_________________________________________________________
    	areaKeys = [];
    	for(i = 0; i < 2; i++){
			val = $F("arrivalGeographicalArea" + i);
			if(val){
				areaKeys.push(val);
				retAreasCounter++;
			}
		}
    	for(i = 0; i < retAreasCounter - 1; i++){
			rarg.createField();
    	}
        forcedDeparture = depAirsCounter ? "ta_partenzaTab0" : "ta_partenzaTab1";
        forcedReturn = retAirsCounter ? "ta_ritornoTab0" : "ta_ritornoTab1";
        if(depAirsCounter || depAreasCounter){
			this.loadCibaReturnData({
	            cback: function(){
	                self.enableBlock('ta_arrival');
	                self.enableStep(2);
	            },
	            asynch: false,
	            parameters: params
	        });
		}else{
			// SVUOTARE il target. In questo caso è corretta?
			this._emptyPanel(rag);
		}
        // return airports
        for(i = 0; i < airKeys.length; i++){
            rag.fields[i].nationField.setIndex(rag.fields[i].nationField.getKeyIndex(getNationFromArea({ area: airKeys[i], grp: rag })));
        }
        for(var k = 0; k < airKeys.length; k++){
            var areas = [];
            for(i = 0; i < rag.groupData.length; i++){
                if(rag.groupData[i].description == getNationFromArea({ area: $F("arrivalAirports" + k), grp: rag })){
                    areas.push(rag.groupData[i]);
                }
            }
            rag.fields[k].areaField.fillInData(areas);
            rag.fields[k].areaField.setKey($F("arrivalAirports" + k));
            rag.fields[k].areaField.onFirstChange = function(){};
        }

    	// RETURN AIRPORTS______________________________________________________
        // riempimento dei campi
    	for(i = 0; i < areaKeys.length; i++){
    		rarg.fields[i].nationField.setIndex(rarg.fields[i].nationField.getKeyIndex(getNationFromArea({ area: areaKeys[i], grp: rarg })));
    	}
        for(k = 0; k < areaKeys.length; k++){
            var areas = [];
            for(i = 0; i < rarg.groupData.length; i++){
                if(rarg.groupData[i].description == getNationFromArea({ area: $F("arrivalGeographicalArea" + k), grp: rarg })){
                    areas.push(rarg.groupData[i]);
                }
            }
            rarg.fields[k].areaField.fillInData(areas);
            rarg.fields[k].areaField.setKey($F("arrivalGeographicalArea" + k));
            rarg.fields[k].areaField.onFirstChange = function(){};
        }
        retAreasCounter && self.loadMonths({
            forcedDeparture: forcedDeparture,
            forcedReturn: forcedReturn,
            asynch: false,
            cback: function(){
                this.disableBlock('ta_partenza');
                $('ta_modifica_partenza').setStyle({
                    display: "block"
                });
                $('ta_step_one_circle').setStyle({
                    display: "none"
                });
            }
        });
        this.priceChooser.disable();
        // *************************************************************************
        // ricostruzione della situazione corretta dei link di aggiunta nodi
        // *************************************************************************
        depAirsCounter && (dag.fields.length < dag.maxFields) && dag.enableAddNode();
        depAreasCounter && (darg.fields.length < darg.maxFields) && darg.enableAddNode();
        retAirsCounter && (rag.fields.length < rag.maxFields) && rag.enableAddNode();
        retAreasCounter && (rarg.fields.length < rarg.maxFields) && rarg.enableAddNode();
    },
    isValidData: function(/**/ transport){
        var validData = transport.responseJSON.validData;
        (validData === false) && this.assistant.showInfo({
            msg: transport.responseJSON.errormessage,
            top: "2px",
            left: "600px",
            position: "initial",
            force: false,
            dir: "",
            duration: 10000,
            type: "error"
        });
	    $("ta_loading_msg").setStyle({
		    display: "none"
	    });
        return !!validData;
    },
    setupConnections: function(){
		var self = this;
		Ajax.Responders.register({
			onCreate: function(requesterObj, xhr) {
                // timeout handling here
//		    	clearTimeout(self._currentTimeout);
//		    	self._currentTimeout = null;
//		    	self.notifier.info.call(self.notifier, "loading...");
//                $("ta_loading_overlay").show();
//
//		    	self._currentTimeout = setTimeout(function(){ self.timeoutHandler.call(self, requesterObj, xhr) }, self.connectionTimeout);
			},
			onComplete: function(request, transport, json){
				var status = request.getStatus();
//		    	clearTimeout(self._currentTimeout);
				// client error codes
				// 400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,422,423,424,425,426,449
				// server error codes
				// 500,501,502,503,504,505,506,507,509,510
				switch (status) {
					case 404:
						// client error
						break;
					case 500:
						// server error
						break;
					case 200:
						// success
						break;
					default:
						break;
				}
//                $("ta_loading_overlay").hide();

			}
		});
	},
    setDepartureData: function(/** Number */ currentPrice){
        var self = this,
            params = {
                price: self.priceChooser.getValue()
            },
            cback = function(){},
            dag = this.departureAirportsGroup,
            darg = this.departureAreaGroup//,
//            asynch = args.asynch === false ? false : true
        ;
	    $("ta_loading_msg").setStyle({
			display: "block"
		});
		new Ajax.Request("pricedeparture.action", {
//			asynchronous: true,
            asynchronous: false, // condizionare al fatto che si sia nella pag di ritorno
	  		method: 'POST',
			evalJSON: true,
			parameters: params,
			onSuccess: function(transport){
                if(!self.isValidData(transport)){
                	self.disableBlock('ta_partenza');
                	return;
                }
                self.enableBlock('ta_partenza');
                var aAirports = transport.responseJSON["availableAirports"],
                    aAreas = transport.responseJSON["availableDepartureGeoArea"]
                ;
                self._setDepartureData({
                	aAirports: aAirports,
                	aAreas: aAreas
                });
				cback.call(self);
				$("ta_loading_msg").setStyle({
					display: "none"
				});
			},
			onFailure: function(){
				window.alert("loadCibaReturnData failure");
				$("ta_loading_msg").setStyle({
					display: "none"
				});
			},
			onException: function(req, exc){
				window.alert(this + " " + exc);
				$("ta_loading_msg").setStyle({
					display: "none"
				});
			}
		});
    },
    _setDepartureData: function(args){
    	var self = this, // this method needs only "this", rename
	    	aAirports = args.aAirports,
	    	aAreas = args.aAreas,
            dag = this.departureAirportsGroup,
            darg = this.departureAreaGroup
        ;

    	dag.setGroupData(aAirports);
        darg.setGroupData(aAreas);

        var n = [],
            k = "",
            prev = ""
        ;
        // rifacimento degli aeroporti, uso un GeographicGroup: rifattorizzare il nome di questa classe,
        // adesso il nome ha perso di senso
        for(var i = 0; i < dag.groupData.length; i++){
            k = dag.groupData[i].description;
            if(k != prev || k == ""){
	            n.push({ _delimiter: dag.groupData[i].key == "", _key: dag.groupData[i].key, key: dag.groupData[i].description, value: dag.groupData[i].description });
            }
            prev = k;
        }
        var areas = [];
        if(!dag.firstOption && !n[0]._delimiter){
            for(i = 0; i < dag.fields.length; i++){
                if(dag.groupData[i].description == n[0].key){
                    areas.push(dag.groupData[i]);
                }
            }
        }else{
            areas = [{ key: "", value: "---" }];
        }
        dag.nations = n;
        // coppia di select (nazione, area)
        for(i = 0; i < dag.fields.length; i++){
        	dag.fields[i].nationField.firstOption = dag.fields[i]._firstOption;
        	dag.fields[i].nationField.onFirstChange = function(){
                this.firstOption = false;
                this.listData.shift();
                this.selectedIndex--;
                this.createList();
        	};
        	dag.fields[i].nationField.trimList();
            dag.fields[i].nationField.fillInData(n);
            dag.fields[i].nationField.enable();
            dag.fields[i].areaField.fillInData(areas);
            dag.fields[i].areaField.enable();
        }
        // fine rifacimento_____________________________________________________________________________________
        n = [];
        k = "";
        prev = "";
        for(i = 0; i < darg.groupData.length; i++){
            k = darg.groupData[i].description;
            if(k != prev || k == ""){
	            n.push({ _delimiter: darg.groupData[i].key == "", _key: darg.groupData[i].key, key: darg.groupData[i].description, value: darg.groupData[i].description });
            }
            prev = k;
        }
        var areas = [];
        if(!darg.firstOption && !n[0]._delimiter){
            for(i = 0; i < darg.fields.length; i++){
                if(darg.groupData[i].description == n[0].key){
                    areas.push(darg.groupData[i]);
                }
            }
        }else{
            areas = [{ key: "", value: "---" }];
        }
        darg.nations = n;
        // coppia di select (nazione, area)
        for(i = 0; i < darg.fields.length; i++){
//        	darg.fields[i].nationField.firstOption = darg.fields[i]._firstOption;
//        	darg.fields[i].nationField.onFirstChange = function(){
//                this.firstOption = false;
//                this.listData.shift();
//                this.selectedIndex--;
//                this.createList();
//        	};
//        	darg.fields[i].nationField.trimList();
            darg.fields[i].nationField.fillInData(n);
            darg.fields[i].nationField.enable();
            darg.fields[i].areaField.fillInData(areas);
            darg.fields[i].areaField.enable();
        }
    },
    _comparator: function(a, b){
        var ret = 0,
            da = a.description,
            db = b.description
        ;
        if(da < db){
            ret = -1;
        }else if(da > db){
            ret = 1;
        }
        return ret;
    },
	startup: function(){
		var self = this;
		this.setupConnections();
		this._setCfg();
		// definizione classe calendario proprio per questa applicazione
		var Calendar = function(){};
		ch.exmachina.bravofly.inherits(Calendar, ch.exmachina.bravofly.Calendar);
		Calendar.prototype.onClickHandler = function(/* Event */ evt){
			if(this.disabled){
				return;
			}
			var trg = evt.target,
				self = ch.exmachina.bravofly.pricesearch, // use a parameter instead,
				msgs = self.assistant.messages
			;
			if(trg.tagName.toLowerCase() === "td" && trg.hasClassName("available")){
                var sm = this.getSelectedMonths();
                self.assistant.hideInfo();
                if(!trg.hasClassName("selected")){
                    if(sm.length == self.maxSelectableMonths) {
                        self.assistant.showInfo({
                            msg:msgs.MAX_MONTHS,
                            top: "205px",
                            left: "0px",
                            position: "when",
                            force: true,
                            dir: "bottom",
                            duration: 5000,
                            type: "error"
                        });
                    }else{
                        this.selectMonth({ elem: trg });
                    }
                }else{
					if(sm.length > 1){
						this.unselectMonth({ elem: trg });
						if(self.cfg.type == "pricesearch_h"){
							self.disableBlock("ta_arrival");
							$("ta_modifica_destinazione").setStyle({
								display:"block"
							});
							$('ta_step_two_circle').setStyle({
								display: "none"
							});
						}
					}else{
						self.assistant.showInfo({
							msg:msgs.AT_LEAST_A_MONTH,
							top: "205px",
							left: "0px",
							position: "when",
							force: true,
							dir: "bottom",
							duration: 5000,
							type: "error"
						});
				    }
				}
			}
		};
		// fine definizione calendario
		this.calendar = new Calendar();
		this.calendar.setMessages(this._calMessages);
        this.calendar.init({
            node: "ta_quandoMesi",
            monthMap: this._monthMap
        });
		this.setupPricesearchCallbacks();
		this.makeFieldGroups();
        this.makePriceChooser();
        if(this.cfg.type == "pricesearch_h" && ($F("errorPage") == "true" || $F("ta_searchAgain") == "true")){
            this.priceChooser.selectValue($("ta_maxPrice").value + "&euro;");
        }else{
        	 if(ch.exmachina.bravofly.pricesearch.cfg.pdata.selectedValue){
                 this.priceChooser.selectValue(ch.exmachina.bravofly.pricesearch.cfg.pdata.selectedValue + "&euro;")
         }else{
                 this.setDepartureData(this.priceChooser.getValue());
         }
        }
		this.setupCibavisionReturn();

		// visualizzo il messaggio iniziale, benvenuto o errore.
		var type = "info";
		if($("errorPage").value == "true"){
			this.assistant.lock(15000);
			type = "error";
		}
		var msg = $("ta_assistant_message").innerHTML;
		if(msg.replace(/ |\n|\r|\t/g, "") !== ""){
            var msgType = $("ta_noresult") && $F("ta_noresult") === "true" ? "error" : "info";
			this.assistant.showInfo({
				msg: msg,
				top: "2px",
                left: "600px",
				position: "initial",
				force: false,
				dir: "",
				duration: 10000,
				type: msgType
			});
		}

		// EVENTS

		// airports text fields behaviour
		$("ta_close_tooltip").observe("click", function(){
			self.assistant._initialLock = false;
			self.assistant._isFirstMessage = false;
			clearTimeout(self._assistantTimeout);
			self.assistant.hideInfo();
		});
		// document
        //
		// assistant
		var msgs = this.assistant.messages;
		if(this.cfg.type == "pricesearch"){
			this.makePriceChooser();
			$('ta_pricechooser_helper').observe('click', (function(evt){
				self.assistant.showInfo({
					msg: msgs.CHOOSER,
					top: "15px",
					left: "580px",
					position: "when",
					force: false,
					dir: "bottom",
					duration: 4000
				});
			}).bindAsEventListener(self));
		}
        var showWhenHelp = function(evt){
			self.assistant.showInfo({
				msg: msgs.WHEN,
				top: "185px",
				left: "0px",
				position: "when",
				force: false,
				dir: "bottom",
				duration: 4000
			});
		};
		$('ta_when_helper').observe('click', (showWhenHelp).bindAsEventListener(self));

        $('ta_when_title').observe('click', (showWhenHelp).bindAsEventListener(self));

		// request start
		$('trovaVoli').observe('click', this.startRequest.bindAsEventListener(self, this));

		// tab actions (refactor)
		var radioNode = $('aeroportiZonaRadio');
		radioNode.observe('click', this.showTab.bindAsEventListener(self, this));
		$(radioNode.readAttribute("labelNode")).observe('click', (function(){ self.showTab.call(self, {target: $('aeroportiZonaRadio')}) }).bindAsEventListener());

		radioNode = $('aeroportiManualeRadio');
		radioNode.observe('click', this.showTab.bindAsEventListener(self, this));
		$(radioNode.readAttribute("labelNode")).observe('click', (function(){ self.showTab.call(self, {target: $('aeroportiManualeRadio')}) }).bindAsEventListener());

		radioNode = $('ta_aeroportoRitornoRadio');
		radioNode.observe('click', this.showTab.bindAsEventListener(self, this));
		$(radioNode.readAttribute("labelNode")).observe('click', (function(){ self.showTab.call(self, {target: $('ta_aeroportoRitornoRadio')}) }).bindAsEventListener());

		radioNode = $('ta_areaRitornoRadio');
		radioNode.observe('click', this.showTab.bindAsEventListener(self, this));
		$(radioNode.readAttribute("labelNode")).observe('click', (function(){ self.showTab.call(self, {target: $('ta_areaRitornoRadio')}) }).bindAsEventListener());


		// radio related messages
		var al = $("ta_alert"), si = self.assistant.showInfo, as = self.assistant;
        var showDepartureHelp = function(){
			if(this.tabGroups.partenzaGroup.selected === "ta_partenzaTab0"){
				si.call(as, {
					msg: msgs.START_AIRPORT_ZONE,
					top: "10px",
					left: "570px",
					position: "start",
					force: false,
					dir: "left",
					duration: 4000
				});
			}else{
				si.call(as, {
					msg: msgs.START_AIRPORT_MANUAL,
					position: "start_man",
					top: "220px",
					left: "270px",
					dir: "top",
					force: false,
					duration: 4000
				});
			}
		};
		$('ta_departure_helper').observe('click', showDepartureHelp.bindAsEventListener(self));

		$$('#ta_departure_title > span')[0].observe('click', (showDepartureHelp).bindAsEventListener(self));

        var showPriceHelp = function(){
			si.call(as, {
				msg: msgs.CHOOSER,
				top: "60px",
				left: "170px",
				position: "price_zone",
				force: false,
				dir: "left",
				duration: 4000
			});
		};
		$('ta_price_helper').observe('click', showPriceHelp.bindAsEventListener(self));

//		$$('#ta_price_title > span')[0].observe('click', (showDepartureHelp).bindAsEventListener(self));


        var showDestinationHelp = function(){
			if(this.tabGroups.ritornoGroup.selected === "ta_ritornoTab0"){
				si.call(as, {
					msg: msgs.ARRIVAL_AIRPORT_ZONE,
					position: "arrival_airport",
					top: "175px",
					left: "290px",
					force: false,
					dir: "bottom",
					duration: 4000
				});
			}else{
				si.call(as,{
					msg: msgs.ARRIVAL_GEOGRAPHIC_AREA,
					top: "175px",
					left: "290px",
					position: "arrival_airport_zone",
					force: false,
					dir: "bottom",
					duration: 4000
				});
			}
		};
        $('ta_destination_helper').observe('click', showDestinationHelp.bindAsEventListener(self));

        $$('#ta_return_title > span')[0].observe('click', (showDestinationHelp).bindAsEventListener(self));


		this.resetForm();

		var monthCheckPressed = function(){
            if(this.readAttribute("checkDisabled") == "true"){
                return;
            }
			if(self.selectedMonths == 1 && (this.readAttribute("class") === "ta_check_on")){
				var al = $("ta_alert");
				al.style.top = "348px";
				al.style.left = "150px";
				self.assistant.showInfo({
					msg:msgs.AT_LEAST_A_MONTH,
					top: "205px",
					left: "0px",
					position: "when",
					force: true,
					dir: "bottom",
					duration: 5000,
					type: type
				});
			}else{
				self.selectedMonths += (this.readAttribute("class") === "ta_check_on") ? -1 : 1;
				if(self.cfg.type == "pricesearch_h"){
					self.disableBlock("ta_arrival");
//					$("ta_modifica_partenza").hide();
					$("ta_modifica_destinazione").setStyle({
						display:"block"
					});
                    $('ta_step_two_circle').setStyle({
                        display: "none"
                    });
				}
				self.toggleCheck.call(this);
			}
		};
		// Autocompleters
		var airportSearchBox_language = this._currentLanguage;

		//document.observe("onkey");

		$("ta_show_airports").observe("click", function(){
			self.hideKnobPanel.call(self);
		});
		$("ta_show_distance").observe("click", function(){
			self.showKnobPanel.call(self);
		});
        this.bindCibavisionEvents();
	},
    loadCibaReturnData: function(/** Object */ args){
        if(this.cfg.type != "pricesearch_h"){ return }
        var cback = args.cback || function(){},
            self = this,
            rag = this.returnAirGroup,
            rarg = this.returnAreaGroup,
            parameters = args.parameters,
            asynch = args.asynch === false ? false : true
        ;
        parameters["price"] = this.priceChooser.getValue();

	    $("ta_loading_msg").setStyle({
			display: "block"
		});
		new Ajax.Request("pricedestination.action", {
			asynchronous: asynch,
	  		method: 'POST',
			evalJSON: true,
			parameters: parameters,
			onSuccess: function(transport){
                if(!self.isValidData(transport)){ return; }
                var aAirports = transport.responseJSON["availableDestinations"],
                    aAreas = transport.responseJSON["availableDestinationGeoArea"]
                ;
                rag.setGroupData(aAirports/*.sort(self._comparator)*/);
                rarg.setGroupData(aAreas/*.sort(self._comparator)*/);
                var n = [],
                    k = "",
                    prev = ""
                ;

                // aeroporti ritorno ___________________________________________________________________________________
                for(var i = 0; i < rag.groupData.length; i++){
                    k = rag.groupData[i].description;
                    (k != prev || k == "") && n.push({ _delimiter: rag.groupData[i].key == "", _key: rag.groupData[i].key, key: rag.groupData[i].description, value: rag.groupData[i].description });
                    prev = k;
                }
                var areas = [];
                if(!rag.firstOption){
                    for(i = 0; i < rag.fields.length; i++){
                        if(rag.groupData[i].description == n[0].key){
                            areas.push(rag.groupData[i]);
                        }
                    }
                }else{
                    areas = [{ key: "", value: "---" }];
                }
                rag.nations = n;
                for(i = 0; i < rag.fields.length; i++){
                	rag.fields[i].nationField.firstOption = rag.fields[i]._firstOption;
                	rag.fields[i].nationField.onFirstChange = function(){
                        this.firstOption = false;
                        this.listData.shift();
                        this.selectedIndex--;
                        this.createList();
                	};
                	rag.fields[i].nationField.trimList();
                    rag.fields[i].nationField.fillInData(n);
                    rag.fields[i].nationField.enable();

                    rag.fields[i].areaField.fillInData(areas);
                    rag.fields[i].areaField.enable();
                }
                // aeroporti ritorno end________________________________________________________________________________

                n = [];
                k = "";
                prev = "";
                for(var i = 0; i < rarg.groupData.length; i++){
                    k = rarg.groupData[i].description;
                    (k != prev || k == "") && n.push({ _delimiter: rarg.groupData[i].key == "", _key: rarg.groupData[i].key, key: rarg.groupData[i].description, value: rarg.groupData[i].description });
                    prev = k;
                }
                var areas = [];
                if(!rarg.firstOption){
                    for(i = 0; i < rarg.fields.length; i++){
                        if(rarg.groupData[i].description == n[0].key){
                            areas.push(rarg.groupData[i]);
                        }
                    }
                }else{
                    areas = [{ key: "", value: "---" }];
                }
                rarg.nations = n;
                // coppia di select (nazione, area)
                for(i = 0; i < rarg.fields.length; i++){
                	rarg.fields[i].nationField.firstOption = rarg.fields[i]._firstOption;
                	rarg.fields[i].nationField.onFirstChange = function(){
                        this.firstOption = false;
                        this.listData.shift();
                        this.selectedIndex--;
                        this.createList();
                	};
                	rarg.fields[i].nationField.trimList();
                    rarg.fields[i].nationField.fillInData(n);
                    rarg.fields[i].nationField.enable();
                    rarg.fields[i].areaField.fillInData(areas);
                    rarg.fields[i].areaField.enable();
                }
                self.enableStep(2);
				cback.call(self);
				$("ta_loading_msg").setStyle({
					display: "none"
				});
			},
			onFailure: function(){
				window.alert("loadCibaReturnData failure");
				$("ta_loading_msg").setStyle({
					display: "none"
				});
			},
			onException: function(req, exc){
				window.alert(this + " " + exc);
				$("ta_loading_msg").setStyle({
					display: "none"
				});
			}
		});
    },
    enableStep: function(/** Integer */ stepNo){
    	var map = [, "One", "Two", "Three"];
    	for(var i = 1; i < map.length; i++){
        	$("ta_step" + map[i]).removeClassName("ta_step_current");
    	}
        $("ta_step" + map[stepNo]).addClassName("ta_step_current");
    },
   _emptyPanel: function(/** Group */ grp){
    	var len = grp.fields.length;
        for(var i = len - 1; i > 0; i--){
        	grp.removeField(i);
        }
        grp.setCloserButtons();
        grp.disableAddNode();
    },
    bindCibavisionEvents: function(){
        if(this.cfg.type != "pricesearch_h") { return; }
        var self = this;
        $('ta_modifica_prezzo').observe('click', function(){
            self.enableStep(1);
            self.priceChooser.enable();
            $('ta_modifica_prezzo').parentNode.style.display = "none";
            $('ta_modifica_partenza').style.display = "none";
            $('ta_modifica_destinazione').style.display = "none";

            // TODO: disabilitare tutti i settori tranne quello di partenza
            $('ta_step_one_circle').setStyle({
                display: "block"
            });
            $('ta_step_two_circle').setStyle({
                display: "block"
            });
            var cLen = self.returnAirGroup.fields.length;
            for(var i = 0; i < cLen; i++){
                self.returnAirGroup.removeField(0);
            }
            self.returnAirGroup.createField();
            // aree geografiche
            cLen = self.returnAreaGroup.fields.length;
            for(i = 0; i < cLen; i++){
                self.returnAreaGroup.removeField(0);
            }
            self.returnAreaGroup.createField();

            self.disableBlock('ta_arrival');
            self.disableBlock('ta_when');
            // distruggo tutti i campi dei due gruppi di partenza
            cLen = self.departureAirportsGroup.fields.length;
            for(i = 0; i < cLen; i++){
                self.departureAirportsGroup.removeField(0);
            }
            self.departureAirportsGroup.createField();

            cLen = self.departureAreaGroup.fields.length;
            for(i = 0; i < cLen; i++){
                self.departureAreaGroup.removeField(0);
            }
            self.departureAreaGroup.createField();

            self.setDepartureData(self.priceChooser.getValue());
            self.enableBlock('ta_partenza');
        });
        $("ta_ricomincia").observe('click', function(){
        	window.location.href = "pricesearchindex.action";
        });
        // MODIFICA PARTENZA
        $('ta_modifica_partenza').observe('click', (function(){
            var dag = this.departureAirportsGroup,
                rag = this.returnAirGroup,
                darg = this.departureAreaGroup,
                rarg = this.returnAreaGroup
            ;
            this.enableBlock('ta_partenza');
            this.enableStep(2);

            //this.disableBlock('ta_arrival');
            this.disableBlock('ta_when');
            $('ta_modifica_partenza').setStyle({
            	display: "none"
            });
            $('ta_modifica_destinazione').setStyle({
            	display: "none"
            });
            $('ta_step_one_circle').setStyle({
                display: "block"
            });
            $('ta_step_two_circle').setStyle({
                display: "block"
            });
            for(var i = 0; i < dag.fields.length; i++){
                dag.fields[i].nationField.enable();
                dag.fields[i].areaField.enable();
            }
            for(i = 0; i < darg.fields.length; i++){
                darg.fields[i].nationField.enable();
                darg.fields[i].areaField.enable();
            }
            $('ta_step_three_circle').setStyle({
            	display: "block"
            });
            this._emptyPanel(rag);
            this._emptyPanel(rarg);
			while(rarg.fields[0]["nationField"].listData[0] && !rarg.fields[0]["nationField"].listData[0].key){
				rarg.fields[0]["nationField"].listData.shift();
			}
    		rarg.fields[0]["nationField"].addFirstOption({ imposedClassName: "ta_deadItem", key: "-", value: this._prompts["filterList"] });
        	rarg.fields[0]["nationField"].onFirstChange = function(){
                this.firstOption = false;
                this.listData.shift();
                this.selectedIndex--;
                this.createList();
        	};
            rarg.fields[0]["nationField"].setIndex(0);

            rarg.fields[0]["areaField"].listData = [];
    		rarg.fields[0]["areaField"].addFirstOption({ key: "", value: "---" });

//            rarg.fields[0]["areaField"].firstOption = true;

            rarg.fields[0]["areaField"].onFirstChange = function(){
                this.firstOption = false;
                this.listData.shift();
                this.selectedIndex--;
                this.createList();
        	};
        	rarg.fields[0]["areaField"].setIndex(0);
        }).bindAsEventListener(this));
        $('ta_modifica_destinazione').observe('click', (function(){
            var dag = this.departureAirportsGroup,
                rag = this.returnAirGroup,
                rarg = this.returnAreaGroup
            ;
            this.enableBlock('ta_arrival');
            this.displayMonths(this._cachedMonths);
            this.enableStep(3);
            $('ta_modifica_destinazione').setStyle({
            	display: "none"
            });
            $('ta_step_two_circle').setStyle({
            	display: "block"
            });
            for(var i = 0; i < rag.fields.length; i++){
                rag.fields[i].nationField.enable();
                rag.fields[i].areaField.enable();
            }
            for(i = 0; i < rarg.fields.length; i++){
                rarg.fields[i].nationField.enable();
                rarg.fields[i].areaField.enable();
            }
            //this.disableBlock('ta_arrival');
        }).bindAsEventListener(this));
    },
	showKnobPanel: function(){
		var self = this;
		this._isKnobVisible = true;
		$("ta_show_distance_container").style.display = "none";
		$("ta_knob_message").style.display = "block";
		$("ta_knob_container").style.display = "block";
		$("ta_knobGroup").style.display = "block";
		$("ta_departureAirGroupContainer").style.display = "none";
		$("ta_add_airport_container").style.display = "block";
		ch.exmachina.bravofly.FieldGroup.copy({
			dest: self.departureKnobGroup.fields[0],
			src: self.departureAirportsGroup.fields[0]
		});
		if(self.departureKnobGroup.fields[0].disabled){
			this.findKnobInfo();
		}else{
			this.knob.disable();
		}
	},
	hideKnobPanel: function(args){
		var self = this;
		this._isKnobVisible = false;
		$("ta_add_airport_container").style.display = "none";
		$("ta_knob_message").style.display = "none";
		$("ta_knob_container").style.display = "none";
		$("ta_knobGroup").style.display = "none";
		$("ta_departureAirGroupContainer").style.display = "block";
		$("ta_show_distance_container").style.display = "block";
		if(!args || (args && !args.noCopy)){
			ch.exmachina.bravofly.FieldGroup.copy({
				src: self.departureKnobGroup.fields[0],
				dest: self.departureAirportsGroup.fields[0]
			});
			this.departureAirportsGroup.collapse();
			if(this.departureAirportsGroup.allFreezed() &&
				this.departureAirportsGroup.fields.length < this.departureAirportsGroup.maxFields){
				this.departureAirportsGroup.enableAddNode();
			}
		}
		this.knob.setStatus(0.0);
		//this.unfreezeField($('fld_departureAirports0')); --> deve finire nell'oggetto interessato
	},
	freezeField: function(/** input */ elem){
		elem.className = "fixed";
		elem.disabled = true;
	},
	unfreezeField: function(/** input */ elem){
		this.knob.disable();
		elem.className = "";
		elem.disabled = false;
	},
	toggleCheck: function(){
		var ref = this.readAttribute("labelRef"), fieldRef = this.readAttribute("fieldRef"), refElem;
		if(ref){
			refElem = $(ref);
			refElem.className = refElem.className == "ta_labelOff" ? "ta_labelOn" : "ta_labelOff";
		}
		this.className = this.className == "ta_check_off" ? "ta_check_on" : "ta_check_off";
	},
	_showTab: function(trg, grp, noConnections, force){
		// se gruppo corrente disabilitato non fare niente, solo per cibavision
		if(this.cfg.type === "pricesearch_h"){
			switch(trg.id){
				case "aeroportiZonaRadio":
				case "aeroportiManualeRadio":
					if(this.tabGroups.partenzaGroup.disabled && !force){
						return;
					}
				break;
				case "ta_aeroportoRitornoRadio":
				case "ta_areaRitornoRadio":
					if(this.tabGroups.ritornoGroup.disabled && !force){
						return;
					}
				break;
				default:
				break;
			}
		}
		for(var i in grp){
			$(grp[i].panel).removeClassName("enabledTabContainer").addClassName("disabledTabContainer");
			$(i).removeClassName("ta_radio_on").addClassName("ta_radio_off");
		}
		var toShowTab = $(trg.id), toShowPanel = $(grp[trg.id].panel);
		toShowTab.addClassName("ta_radio_on").removeClassName("ta_radio_off");
		toShowPanel.addClassName("enabledTabContainer").removeClassName("disabledTabContainer");
		this.tabGroups[trg.readAttribute("tabGroup")].selected = grp[trg.id].panel;

		// azioni da intraprendere in cibavision al cambio di tab
		if(this.cfg.type === "pricesearch_h"){
			var self = this;
			switch(trg.id){
				case "aeroportiZonaRadio":
					var dag = this.departureAirportsGroup;
					switch(this.tabGroups.ritornoGroup.selected){
						case "ta_ritornoTab0":
			                var params = { departureAirports: [ ] },
			                    rag = this.returnAirGroup
			                ;
			                for(var i = 0; i < dag.fields.length; i++){
			                    params.departureAirports.push(dag.fields[i].getKey());
			                }
			                rag.selectUrlParameters = params;
							if(dag.atLeastOneValid()){
								this.loadCibaReturnData({
			                        cback: function(){
			                            self.enableBlock('ta_arrival');
			                            self.enableStep(2);
			                        },
			                        parameters: params
			                    });
							}else{
								// SVUOTARE il target
								this._emptyPanel(rag);
							}
						break;
						case "ta_ritornoTab1":
                            if(noConnections){ break; }
			                var params = { departureAirports: [ ] },
			                    rarg = this.returnAreaGroup
			                ;
			                for(i = 0; i < dag.fields.length; i++){
			                    params.departureAirports.push(dag.fields[i].areaField.getKey());
			                }
			                rarg.selectUrlParameters = params;
							if(dag.atLeastOneValid()){
								this.loadCibaReturnData({
			                        cback: function(){
			                            self.enableBlock('ta_arrival');
			                            self.enableStep(2);
			                        },
			                        parameters: params
			                    });
							}else{
								// SVUOTARE il target
								this._emptyPanel(rarg);
							}
						break;
					}
				break;
				case "aeroportiManualeRadio":
					var darg = this.departureAreaGroup;
					switch(this.tabGroups.ritornoGroup.selected){
						case "ta_ritornoTab0":
			                var params = { departureAirports: [ ] },
			                    rag = this.returnAirGroup
			                ;
			                for(i = 0; i < darg.fields.length; i++){
			                    params.departureAirports.push(darg.fields[i].areaField.getKey());
			                }
			                rag.selectUrlParameters = params;
							if(darg.atLeastOneValid()){
								this.loadCibaReturnData({
			                        cback: function(){
			                            self.enableBlock('ta_arrival');
			                            self.enableStep(2);
			                        },
			                        parameters: params
			                    });
							}else{
								// SVUOTARE il target
//								this._emptyPanel(rag);
								this.disableBlock("ta_arrival")
							}
						break;
						case "ta_ritornoTab1":
                            if(noConnections){ break; }
			                var params = { departureAirports: [ ] },
			                    rarg = this.returnAreaGroup
			                ;
			                for(i = 0; i < darg.fields.length; i++){
			                    params.departureAirports.push(darg.fields[i].areaField.getKey());
			                }
			                rarg.selectUrlParameters = params;
							if(darg.atLeastOneValid()){
								this.loadCibaReturnData({
			                        cback: function(){
			                            self.enableBlock('ta_arrival');
			                            self.enableStep(2);
			                        },
			                        parameters: params
			                    });
							}else{
								// SVUOTARE il target
								//this._emptyPanel(rarg);
								this.disableBlock("ta_arrival")
							}
						break;
					}
				break;
				case "ta_aeroportoRitornoRadio":
	                var params = { destinationAirports: [ ] },
	                    dag = self.departureAirportsGroup,
	                    rag = self.returnAirGroup
	                ;
	                for(i = 0; i < rag.fields.length; i++){
	                    params.destinationAirports.push(rag.fields[i].areaField.getKey());
	                }
	                //rag.selectUrlParameters = params; // <--- sostituire con "blocco mesi"
	                if(rag.atLeastOneValid()){

	                    self.loadMonths({ cback: function(){
	                        this.disableBlock('ta_partenza');
	                        $('ta_modifica_partenza').setStyle({
	                        	display: "block"
	                        });
                            $('ta_step_one_circle').setStyle({
                                display: "none"
                            });
	                    }});
	                }else{
	                	// disabilito sezione mesi
	                	this.disableBlock("ta_when");
	                }
				break;
				case "ta_areaRitornoRadio":
	                var params = { destinationAirports: [ ] },
	                    dag = self.departureAirportsGroup,
	                    rarg = self.returnAreaGroup
	                ;
	                for(i = 0; i < rarg.fields.length; i++){
	                    params.destinationAirports.push(rarg.fields[i].areaField.getKey());
	                }
	                //rag.selectUrlParameters = params; // <--- sostituire con "blocco mesi"
	                if(rarg.atLeastOneValid()){
	                    self.loadMonths({ cback: function(){
	                        this.disableBlock('ta_partenza');
	                        $('ta_modifica_partenza').setStyle({
	                        	display: "block"
	                        });
                            $('ta_step_one_circle').setStyle({
                                display: "none"
                            });
	                    }});
	                }else{
	                	// disabilito sezione mesi
	                	this.disableBlock("ta_when");
	                }
				break;

				default:
				break;
			}
		}
	},
	showTab: function(/** DOM node */evt){
		var trg = evt.target, grp = this.tabGroups[trg.readAttribute("tabGroup")].tabs;
		this._showTab(trg, grp);
	},
	resetHiddenForm: function(){
		var flds = document.searchForm.getElementsByTagName("input");
		for(var i = 0; i < flds.length; i++){
			flds[i].value = "";
		}
		$("hourTolerance").value = "0";
		$("numberOfRowsToDisplay").value = "50";
	},
	startRequest: function(){
		if(this.cfg.type === "pricesearch_h" && this._monthsDisabled){
			return;
		}
//		return;
		this.resetHiddenForm();
		var uncompleteFields = false;
		if(this.tabGroups.partenzaGroup.selected === "ta_partenzaTab0"){
			if((this.cfg.type != "pricesearch_h" && this._isKnobVisible && !this.departureKnobGroup.allValid())
				|| (!this._isKnobVisible && !this.departureAirportsGroup.allValid())){
				uncompleteFields = true;
			}
		}
        if(this.cfg.type != "pricesearch_h"){
            if(this.tabGroups.partenzaGroup.selected === "ta_partenzaTab1" && !this.departureAreaGroup.allValid()){
                uncompleteFields = true;
            }
            if(this.tabGroups.ritornoGroup.selected === "ta_ritornoTab0" && !this.returnAirGroup.allValid()){
                uncompleteFields = true;
            }
            if(this.tabGroups.ritornoGroup.selected === "ta_ritornoTab1" && !this.returnAreaGroup.allValid()){
                uncompleteFields = true;
            }
        }
		var msgs = this.assistant.messages;
		if(uncompleteFields){
			this.assistant.lock(8000);
			this.assistant.showInfo({
				msg: msgs.FIELD_NOT_FIXED,
				top: "0px",
				left: "0px",
				position: "not fixed",
				force: false,
				dir: "",
				duration: 5000,
				type: "dep"
			});
			return;
		}
		// priceChooser value
		if(this.cfg.type == "pricesearch_h" || this.cfg.type == "pricesearch"){
			$("ta_maxPrice").value = this.priceChooser.getValue();
		}

		// departure airports or distance
		if(this.cfg.type != "pricesearch_h" && this._isKnobVisible){
			$("departureAirports0").value = this.departureKnobGroup.getField(0).isFreezed() ?
				this.departureKnobGroup.getField(0).getValue() : "";
		}else{
            if(this.cfg.type != "pricesearch_h"){
                for(var i = 0; i < this.departureAirportsGroup.fields.length; i++){
                    $("departureAirports" + i).value = this.departureAirportsGroup.getField(i).isFreezed() ?
                        this.departureAirportsGroup.getField(i).getValue() : "";
                }
            }else{
                // valori di aeroporti per ciba, qui
                for(var i = 0; i < this.departureAirportsGroup.fields.length; i++){
                    var isValid = this.departureAirportsGroup.getField(i).areaField.isValid();
                    $("departureAirports" + i).value = isValid?
                        this.departureAirportsGroup.getField(i).areaField.getKey() : "";
                }
            }
		}
        // HERE FOR PRICESEARCH SEARCH
        for(i = 0; i < this.departureAreaGroup.fields.length; i++){
            var isValid = this.departureAreaGroup.getField(i).areaField.isValid();
            $("ta_depCountry" + i).value = 'ITA';
            $("departureGeographicalArea" + i).value = isValid ?
                this.departureAreaGroup.getField(i).areaField.getKey() : "";
        }
        // return airports
        for(i = 0; i < this.returnAirGroup.fields.length; i++){
            var isValid = this.returnAirGroup.getField(i).areaField.isValid();
            $("arrivalAirports" + i).value = isValid ?
                this.returnAirGroup.getField(i).areaField.getKey() : "";
        }
        // return areas
        for(i = 0; i < this.returnAreaGroup.fields.length; i++){
            isValid = this.returnAreaGroup.getField(i).areaField.isValid();
            $("ta_arrCountry" + i).value = isValid ?
                this.returnAreaGroup.getField(i).nationField.get_Key() : "";
            $("arrivalGeographicalArea" + i).value = isValid ?
                this.returnAreaGroup.getField(i).areaField.getKey() : "";
        }
        $("hourTolerance").value = "0";

		// month start
        var cal = this.calendar;
        for(i = 0; i < 12; i++){
			var md = cal.monthsNodes[i],
                mField = $(md.readAttribute("fieldRef"))
            ;
			mField.value = md.hasClassName("selected") ? md.readAttribute("valueon") || "" : md.readAttribute("valueoff") || "";
		}
		// month end

		// radio buttons start
		var tGroups = this.tabGroups;
		var selectedTabId;
		for(var j in tGroups){
			selectedTabId = tGroups[j].selected;
			for(i in tGroups[j]["tabs"]){
				var currentTab = $(i);
				if(currentTab.readAttribute("fieldRef")){
					if(selectedTabId != tGroups[j]["tabs"][i]["panel"]){
						$(currentTab.readAttribute("fieldRef")).value = currentTab.readAttribute("valueOff");
					}else{
						$(currentTab.readAttribute("fieldRef")).value = currentTab.readAttribute("valueOn");
					}
				}
			}
		}
		// radio buttons end

		// svuoto i campi relativi ai tab non attivi
		var flds, grp, tab;
		for(j in tGroups){
			grp = tGroups[j];
			tab = grp["tabs"];
			for(i in tab){
				flds = tab[i]["fields"];
				if(grp.selected != tab[i]["panel"]){
					for(var k = 0; k < flds.length; k++){
						$(flds[k]).value = "";
					}
				}
			}
		}
		// svuoto i campi relativi ai tab non attivi [fine]
 		// Distance in days
        var did = $$("[name=distanceInDays]");
		for(i = 0, l = did.length; i < l; i++){
			if(did[i].checked){
				var val = this._distanceHash[did[i].value];
				document.searchForm["minDistanceInDays"].value = val.start;
				document.searchForm["maxDistanceInDays"].value = val.end;
			}
		}  
        document.searchForm.submit();
	},
	resetForm: function(){
		var self = this;
		if($F("errorPage") != "true" && $F("ta_searchAgain") != "true"){
			for(var i = 0; i < 2; i++){
				$("departureGeographicalArea" + i).value = "";
				$("arrivalGeographicalArea" + i).value = "";
			}
            this.calendar.disableAllMonths();
			var airP, aP;

			/* months initialization */
			this.selectedMonths = 3;

			var uH = ch.exmachina.bravofly.pricesearch.utils.unescapeHTML;

		}else{
			// error or searchAgain page
			// RichFields
			if(this.cfg.type != "pricesearch_h"){
				var val = "",
					hourTolerance = $F("hourTolerance"),
					lastField,
					trgField,
					showKnob = false,
					counter = 0,
					depAreaCounter = 0,
					fHourTolerance = 0
				;
				fHourTolerance = parseFloat(hourTolerance);

				for(i = 0; i < 3; i++){
					counter += val = $("departureAirports" + i).value ? 1 : 0;
				}
				for(i = 0; i < 2; i++){
					depAreaCounter += $("departureGeographicalArea" + i).value ? 1 : 0;
				}
				if(fHourTolerance > 0 || (fHourTolerance == 0 && counter < 2 && !depAreaCounter)){
					lastField = this.departureKnobGroup.getLastField();
					lastField.setValue($("departureAirports0").value);
					lastField.freeze();
				}else{
					this.hideKnobPanel({
						noCopy: true
					});
					for(i = 0; i < 3; i++){
						val = $("departureAirports" + i).value;
						if(val){
							lastField = this.departureAirportsGroup.getLastField();
							if(lastField.isFreezed()){
								trgField = this.departureAirportsGroup.createField();
							}else{
								trgField = lastField;
							}
							trgField.setValue(val);
							trgField.freeze();
						}
					}
				}
				for(i = 0; i < 3; i++){
					val = $("arrivalAirports" + i).value;
					if(val){
						lastField = this.returnAirGroup.getLastField();
						if(lastField.isFreezed()){
							trgField = this.returnAirGroup.createField();
						}else{
							trgField = lastField;
						}
						trgField.setValue(val);
						trgField.freeze();
					}
				}
				for(i = 0; i < 2; i++){
					val = $("ta_depCountry" + i).value;
					if(val){
						lastField = this.departureAreaGroup.getLastField();
						if(lastField.isFreezed() && this.cfg.type != "pricesearch_h"){
							trgField = this.departureAreaGroup.createField();
						}else{
							trgField = lastField;
						}
						var values = val.split(":");
						trgField.areaField.onLoadOnce = function(x){
							return function(){
								this.setValue($("departureGeographicalArea" + x).value);
							}
						}(i);
						trgField.nationField.storedId = values[1];
						trgField.nationField.setValue(values[0]);
						trgField.nationField.freeze();
					}
					val = $("ta_arrCountry" + i).value;
					if(val){
						lastField = this.returnAreaGroup.getLastField();
						if(lastField.isFreezed()){
							trgField = this.returnAreaGroup.createField();
						}else{
							trgField = lastField;
						}
						values = val.split(":");
						trgField.areaField.onLoadOnce = function(x){
							return function(){
								this.setValue($("arrivalGeographicalArea" + x).value);
							}
						}(i);
						trgField.nationField.storedId = values[1];
						trgField.nationField.setValue(values[0]);
						trgField.nationField.freeze();
					}
				}

				// PriceChooser
				if(this.cfg.type == "pricesearch_h" || this.cfg.type == "pricesearch"){
					this.priceChooser.selectValue($("ta_maxPrice").value);
				}
				// "addNode" validation // parametrize this!
				if(this.departureAirportsGroup.allFreezed() &&
						this.departureAirportsGroup.fields.length < this.departureAirportsGroup.maxFields){
						this.departureAirportsGroup.enableAddNode();
					}
				if(this.returnAirGroup.allFreezed() &&
					this.returnAirGroup.fields.length < this.returnAirGroup.maxFields){
					this.returnAirGroup.enableAddNode();
				}
				if(this.departureAreaGroup.allFreezed() &&
					this.departureAreaGroup.fields.length < this.departureAreaGroup.maxFields){
					this.departureAreaGroup.enableAddNode();
				}
				if(this.returnAreaGroup.allFreezed() &&
						this.returnAreaGroup.fields.length < this.returnAreaGroup.maxFields){
						this.returnAreaGroup.enableAddNode();
				}
				// text fields

				// tab selezionati

				if($("departureGeographicalArea0").value != ""){
					var trg = $("aeroportiManualeRadio"), grp = this.tabGroups[trg.readAttribute("tabGroup")].tabs;
					this._showTab(trg, grp);
				}else{
				}
				if($("arrivalGeographicalArea0").value != ""){
					trg = $("ta_areaRitornoRadio"), grp = this.tabGroups[trg.readAttribute("tabGroup")].tabs;
					this._showTab(trg, grp);
				}
				var errorFields = document.getElementsByName("errorFields"), currentError;

				// knob
				// altra situazione d'errore per lo knob
				if($F("departureGeographicalArea0") == ""){ // first tab selected
					if($F("departureAirports1")){ // hidden knob
						// hide knob panel here
						this.hideKnobPanel({
							noCopy: true
						});
					}else{ // the knob is visible
						var	cback = function(){
								self.knob.setStatus(hourTolerance);
							}
						;
						self.findKnobInfo({
							cback: cback
						});
					}
				}
			}else{
				// pricesearch block here_________________________________________________________
				// ricostruzione selezione dei tab______________________________
                var returnPage = ($F("errorPage") == "true" || ($F("ta_searchAgain") == "true"));
                if($("departureGeographicalArea0").value != ""){
					var trg = $("aeroportiManualeRadio"), grp = this.tabGroups[trg.readAttribute("tabGroup")].tabs;
					this._showTab(trg, grp, returnPage, true);
				}else{
				}
				if($("arrivalAirports0").value != ""){
					trg = $("ta_aeroportoRitornoRadio"), grp = this.tabGroups[trg.readAttribute("tabGroup")].tabs;
					this._showTab(trg, grp, returnPage, true);
				}
				// ricostruzione selezione tab, end_____________________________
				var errorFields = document.getElementsByName("errorFields"), currentError;
				// departure months
                var Cal = this.calendar, md, mField;
                Cal.unselectAllMonths();
				for(i = 0, l = Cal.monthsNodes.length; i < l; i++){
					md = Cal.monthsNodes[i], mField = $(md.readAttribute("fieldRef"));
                    mField.value != "" && Cal.selectMonth({ index: i });
				}
			}
		} // ERROR end
	},
	findKnobInfo: function(/** Object*/ args){
		var self = this;
		var cback = args ? args.cback || function(){} : function(){};
		$("ta_loading_msg").setStyle({
			display: "block"
		});
		new Ajax.Request(this._airportReachabilityUrl, {
	  		method: 'POST',
	  		parameters: {
	  			airport: encodeURIComponent(self.departureKnobGroup.getField(0).getValue()),/*encodeURIComponent($F('fld_departureAirports0')),*/
	  			max_hour: "5.00" // usa una variabile per questo
	  		},
			evalJSON: true,
			onSuccess: function(transport){
                if(!self.isValidData(transport)){ return; }
				var d = transport.responseJSON;
				var rSet = d["availableHours"];
				if(rSet.length > 1){
					self.knob.enable();
					self.knob.setReachabilitySet(rSet);
					cback();
				}else{
					self.knob.disable();
				}
				$("ta_loading_msg").setStyle({
					display: "none"
				});
			},
			onFailure: function(){
				//window.alert("Failure loading the airport distance info");
				$("ta_loading_msg").setStyle({
					display: "none"
				});
			},
			onException: function(req, exc){
				//window.alert("[pricefinder] Error loading airport distance info: " + exc);
				$("ta_loading_msg").setStyle({
					display: "none"
				});
			}
		});
	}
};

Event.observe(document, 'dom:loaded',
	ch.exmachina.bravofly.pricesearch.startup.bindAsEventListener(ch.exmachina.bravofly.pricesearch)
);
Event.observe(window, 'unload', function(){});
