if(!ch){
	var ch = {};
}
if(!ch.exmachina){
	ch.exmachina = {};
}
if(!ch.exmachina.bravofly){
	ch.exmachina.bravofly = {};
}
ch.exmachina.bravofly.FieldGroup = function(/* object */ctorArgs){
	var _timestamp = (new Date()).getTime()
	;
	this.domNode = $(ctorArgs.domNode);
	this.addNode = $(ctorArgs.addNode);
	this.minFields = ctorArgs.minFields || this.minFields;
	this.maxFields = ctorArgs.maxFields || this.maxFields;
	this.symbols.SEARCHING = ctorArgs.searching || this.symbols.SEARCHING;
	this.searchLanguage = ctorArgs.searchLanguage || this.searchLanguage;
	this.promptText = ctorArgs.firstOption && ctorArgs.fieldType === "select" ? ctorArgs.firstOption.value : ctorArgs.promptText || "";
	this.autocompleteURL = ctorArgs.autocompleteURL || this.type;
	this.type = ctorArgs.type || this.type;
	this.onClean = ctorArgs.onClean || this.onClean;
    this.countryCode = ctorArgs.countryCode || "";
    this.continentCode = ctorArgs.continentCode || "";
    this._firstOption = ctorArgs.firstOption;
    this.onAddChild = ctorArgs.onAddChild || this.onAddChild;
    this.fieldType = ctorArgs.fieldType || "";
	this.dataKey = ctorArgs.dataKey || "";
    this.selectUrl = ctorArgs.selectUrl || "";
    this.selectUrlParameters = ctorArgs.selectUrlParameters || "";
    this.disabled = !!ctorArgs.disabled;
    this.onRemoveChild = ctorArgs.onRemoveChild || function(){};
    this.onFirstSelectionChange = ctorArgs.onFirstSelectionChange || this.onFirstSelectionChange;
	this.selectClass = ctorArgs.selectClass || ch.exmachina.bravofly.Select;

    // *************************************************************************
    this.datasource = ctorArgs.datasource || this.datasource;

	this.fields = [];
	this.onChildComplete = ctorArgs.onComplete || this.onChildComplete;
    this.onSelectionChange = ctorArgs.onSelectionChange || this.onSelectionChange;
	for(var i = 0; i < this.minFields; i++){
		//this.fieldsCount++;
		this.createField();
	}
	this.bindEvents();
};

ch.exmachina.bravofly.FieldGroup.prototype = {
	// ****************************************************************************************************
	// members
    groupData: null,
    datasource: "net",

	fields: [],
	minFields: 1,
	maxFields: 3,
	searchLanguage: "EN",
	selectClass: ch.exmachina.bravofly.Select,
	autocompleteURL: "",
	type: "",
	promptText: "",
    countryCode: "",
    continentCode: "",
    fieldType: "",
    dataKey: "",
    selectUrl: "",
    selectUrlParameters: {},
    _firstOption: null,
    // hooks
    onFirstSelectionChange: function(){},
    onAddChild: function(){},
	onClean: function(){},
	// domNodes
	domNode: null,
	addNode: null,
	// status
	disabled: false,
	// const
	symbols:{
		SEARCHING: "Searching..."
	},
	// ****************************************************************************************************
	// methods
    setGroupData: function(/** Object */ gd){
        this.groupData = gd;
    },
	getField: function(index){
		return this.fields[index];
	},
	getLastField: function(){
		return this.fields[this.fields.length - 1];
	},
	// hooks
    onSelectionChange:function(){},
	onChildComplete: function(){},
	// evt handlers
	clickHandler: function(){
		if(this.disabled){ return; }
        var freezed = this.fieldType != "select" ? this.allFreezed() : true;
        if(this.fieldType != "select"){
    		if(this.fields.length < this.maxFields && freezed){
    			this.createField();
    		}
        }else{
    		if(this.fields.length < this.maxFields && this.allValid()){
    			this.createField();
    		}
        }
	},
	enableAddNode: function(){
		this.addNode.className = "ta_new_airport";
	},
	disableAddNode: function(){
		this.addNode.className = "ta_new_airport_disabled";
	},
	hideAddNode: function(){
		this.addNode.className = "ta_new_airport_hidden";
	},
	createField: function(){
		if(this.addNode){
			this.disableAddNode();
		}
        if(this.fieldType == ""){
            return this.fields[this.fields.push(new ch.exmachina.bravofly.RichField({
                pNode: this.domNode,
                searchLanguage: this.searchLanguage,
                autocompleteURL: this.autocompleteURL,
                countryCode: this.countryCode,
                continentCode: this.continentCode,
                type: this.type,
                onComplete: this.onComplete,
                onClose: this.closeChild,
                onClean: this.onClean,
                promptText: this.promptText,
                pGroup: this
            })) - 1];
            this.onAddChild();
        }else if(this.fieldType == "select"){
            var targetNode = document.createElement("div");
	        targetNode.style.position = "absolute";
	        targetNode.style.width = "100%";
	        this.domNode.appendChild(targetNode);
            var newSel = new this.selectClass({
                nodeId: targetNode,
                searchLanguage: this.searchLanguage,
                width: "310px",
                dataKey: this.dataKey,
                pGroup: this,
                promptText: this.promptText,
                firstOption: this._firstOption,
                onLoad: function(){ this.enable(); },
                onChange: this.onSelectionChange,
                asynchLoad: false,
                onFirstChange: this.onFirstSelectionChange,
                onComplete: function(){
                	if(this.pGroup.allValid() && this.pGroup.fields.length < this.pGroup.maxFields){
                		this.pGroup.enableAddNode();
                	}
                },
                onClean: function(){
                    var pGroup = this.pGroup,
                        fields = pGroup.fields
                    ;
                    if(pGroup.disabled){
                        return;
                    }
                    if(pGroup.fields.length > pGroup.minFields){
                        var idx = fields.indexOf(this),
                        	pNode = this.domNode.parentNode;
                        pGroup.removeField(idx);
                        pNode.parentNode && pNode.parentNode.removeChild(pNode);
	                    pGroup.setChildrenPosition();
                        pGroup.onRemoveChild();
                        pGroup.setCloserButtons();
                    }
                    if(fields.length < pGroup.maxFields && pGroup.allValid()){
                        pGroup.enableAddNode();
    				}else{
    					pGroup.disableAddNode();
        			}
               },
                url: this.selectUrl //"/pricefinder/jsp/pricefinder/cfg/airports_stub.jsp"//ctorArgs.geoCompleteURL
            });
            // sincrona la prima volta, quando potrebbero esserci operazioni che devono essere
            // sincrone, come la scelta dell'indice selezionato di ritorno dalla pagina dei risultati
            newSel.aynchLoad = true;

            newSel.listNode.style.width = "370px";
            // i dati del gruppo hanno precedenza su quelli reperibili dalla url
            if(!this.disabled && this.datasource == "net"){
                newSel.loadData.call(newSel,
                    Object.toQueryString(self.selectUrlParameters)
                );
            }
            if(this.fields.length < this.maxFields - 1 && this.atLeastOneValid()){
                this.enableAddNode();
            }else{
                this.disableAddNode();
            }
            this.fields.push(newSel);
	        this.setChildrenPosition();
            this.setCloserButtons();
            this.onAddChild();
            return newSel;
        }
	},
	setChildrenPosition: function(){
		var f = this.fields;
		for(var i = 0, zi = 100, l = f.length; i < l; i++){
			Element.absolutize(f[i].domNode.parentNode);
			f[i].domNode.parentNode.style.width = "100%";
			f[i].domNode.parentNode.style.top = i * 22 + "px";
			f[i].domNode.parentNode.style.left = "0";
			f[i].domNode.parentNode.style.zIndex = zi--;
		}
		this.addNode.style.top = 110 + (f.length) * 22 + "px";
	},
    setCloserButtons: function(){
        var len = this.fields.length,
            displayProp = len == 1 ? "none": "block"
        ;
        for(var i = 0; i < len; i++){
            this.fields[i].clearButton.style.display = displayProp;
        }
    },
	onComplete: function(){
		var pGroup = this.pGroup;
		if(pGroup.addNode && pGroup.fields.length < pGroup.maxFields){
			pGroup.enableAddNode();
		}
		pGroup.onChildComplete.call(this);
	},
	bindEvents: function(){
		if(this.addNode){
			Event.observe($(this.addNode), 'click', this.clickHandler.bindAsEventListener(this));
		}
	},
	disable: function(){
		this.disabled = true;
	},
	enable: function(){
		this.disabled = false;
	},
	closeChild: function(){
		var pGroup = this.pGroup,
			fields = pGroup.fields
		;
		if(pGroup.fields.length > pGroup.minFields){
			var idx = fields.indexOf(this);
			pGroup.removeField(idx);
			this.setChildrenPosition();
            pGroup.onRemoveChild();
		}else{
			this.clean();
		}
		if(this.fieldType != "select"){
			if(pGroup.addNode){
				if(!pGroup.allFreezed()){
					pGroup.disableAddNode();
				}else{
					pGroup.enableAddNode();
				}
			}
		}else{
			if(pGroup.addNode){
				if(!pGroup.allValid()){
					pGroup.disableAddNode();
				}else{
					pGroup.enableAddNode();
				}
			}
		}
	},
    loadData: function(){
        if(this.fieldType === "select"){
            // evitare questa soluzione, i dati possono essere recuperati
            // una volta sola e iniettati in tutte le select
            for(var i = 0; i < this.fields.length; i++){
                this.fields[i].loadData(this.selectUrlParameters);
            }
        }
    },
	collapse: function(){
		if(this.fields.length > 1 && !this.fields[0].disabled){
			this.removeField(0);
			this.setChildrenPosition();
            this.onRemoveChild();
		}
	},
	removeField: function(index){
		this.fields[index].destroy();
		this.fields.splice(index, 1);
	},
	allValid: function(){
		var invalidFields = 0,
			freezedFields = 0,
			completedFields = 0
		;
		if(this.fieldType != "select"){
			for(var i = 0; i < this.fields.length; i++){
				if(this.fields[i].disabled === false && this.fields[i].dirty === true){
					invalidFields++;
				}
				if(this.fields[i].isFreezed()){
					freezedFields++;
				}
			}
			return !invalidFields && !!freezedFields;
		}else{
			for(i = 0; i < this.fields.length; i++){
				if(this.fields[i].getKey()){
					completedFields++;
				}
			}
			return completedFields === this.fields.length;
		}
	},
	allFreezed: function(){
		var unfreezedFields = 0;
		for(var i = 0; i < this.fields.length; i++){
			if(this.fields[i].disabled === false){
				unfreezedFields++;
			}
		}
		return !unfreezedFields;
	},
    atLeastOneValid: function(){
        var validFields = 0;
		for(var i = 0; i < this.fields.length; i++){
			if(this.fields[i].isValid()){
				validFields++;
			}
		}
        return validFields;
    },
    onRemoveChild: function(){},
	toString: function(){
		return "[ch.exmachina.bravofly.FieldGroup]";
	}
};

// static methods
ch.exmachina.bravofly.FieldGroup.copy = function(cpyArgs){
	var src = cpyArgs.src,
		dest = cpyArgs.dest
	;
	dest.fieldNode.className = src.fieldNode.className;
	dest.closerNode.className = src.closerNode.className;
	dest.fieldNode.value = src.fieldNode.value;
	if(src.disabled){
		dest.disable();
	}else{
		dest.enable();
	}
};