// warning: actual implementation can't handle getKey when there are
// identical values (the first key is returned)
if(!ch){
	var ch = {};
}
if(!ch.exmachina){
	ch.exmachina = {};
}
if(!ch.exmachina.bravofly){
	ch.exmachina.bravofly = {};
}

ch.exmachina.bravofly.Select = function(/* object */ctorArgs){
	var nodeId = ctorArgs.nodeId,
		_timestamp = (new Date()).getTime(),
        node = $(nodeId)
	;
	this.url = ctorArgs.url;
	node.innerHTML = this.template.replace(/\${SelectId}/g, _timestamp).
        replace(/\${width}/g, ctorArgs.width || "180");
	this.domNode = $("DomNode_" + _timestamp);
	this.domNode.style.textAlign = "center";
	this.domNode.writeAttribute("id", null);

    this.pNode = node.parentNode.parentNode;
	
	this.listButton = $("ListButton_" + _timestamp);
	this.listButton.writeAttribute("id", null);

    this.clearButton = $("ClearButton_" + _timestamp);
	this.clearButton.writeAttribute("id", null);
	this.closerNode = this.clearButton;

	this.listNode = $("ListNode_" + _timestamp);
	this.listNode.writeAttribute("id", null);

	this.selectWrapperNode = $("SelectWrapperNode_" + _timestamp);
	this.selectWrapperNode.writeAttribute("id", null);

    this.selectFieldNode = $("SelectNode_" + _timestamp);
	this.selectFieldNode.writeAttribute("id", null);
    // per compatibilità
    this.fieldNode = this.selectFieldNode;

    this.pGroup = ctorArgs.pGroup;

    this.dataKey = ctorArgs.dataKey || "";
	
	this.options = this.listNode.getElementsByTagName("li");
	this.promptText = ctorArgs.promptText;

    this.onLoad = ctorArgs.onLoad || this.onLoad;
    this.onComplete = ctorArgs.onComplete || this.onComplete;

    this.onChange = ctorArgs.onChange || this.onChange;
    
    this.onFirstChange = ctorArgs.onFirstChange || this.onFirstChange;

    this.firstOption = ctorArgs.firstOption || "";

    this.onClean = ctorArgs.onClean || this.onClean;

    this.enclosingObject = ctorArgs.enclosingObject;

    this.onClose = ctorArgs.onClose || this.onClose;
    
    this.asynchLoad = ctorArgs.asynchLoad === false ? false : true;

    this.searchLanguage = ctorArgs.searchLanguage || this.searchLanguage;
    this.contentType = ctorArgs.contentType || "";
    
	this.disable();
	this.bindEvents();
    this.pushInstance();
};
ch.exmachina.bravofly.Select._instances = [];
ch.exmachina.bravofly.Select.blurHandler = function(evt){
    var _inst = ch.exmachina.bravofly.Select._instances,
        trg = evt.target
    ;
    // IE pNode hack. find a better way asap
    for(var i = 0; i < _inst.length; i++){
        (ch.exmachina.bravofly.Select.events["open"] != _inst[i]) &&
        _inst[i].pNode != trg && _inst[i].hideList();

    }
    if(ch.exmachina.bravofly.Select.events["open"]){
        ch.exmachina.bravofly.Select.events["open"] = null;
    }
};

ch.exmachina.bravofly.Select.prototype = {
	// class name
	cName: "Select",
	// nodes
	domNode: null,
    pNode: null,
	listButton: null,
	clearButton: null,
	closerNode: null,
	listNode: null,
	nationFieldNode: null,
	areaFieldNode: null,
	selectFieldNode: null,
	fieldNode: null,
    selectWrapperNode: null,
    asynchLoad: true,
	// data
    dataKey: "",
    firstOption: "",
	options: [],
	listData: [],
	disabled: true,
	selectedIndex: 0,
	promptText: "",
	searchLanguage: "EN",
    pGroup: null,
    _evtFired: false,
	
	url: "",
    enclosingObject: null,

	template: '<div id="DomNode_${SelectId}" class="ta_rich_field" style="position:relative;width:${width}px;height:17px;padding:0;margin:0 auto">' +
        '<div id="SelectWrapperNode_${SelectId}" style="padding:0;margin:0">' +
    	'<input readonly="readonly" type="text" name="" value="" style="height:17px;margin:0;width:${width}px;border:none;cursor:default" class="ta_rich_field" ' +
		'id="SelectNode_${SelectId}" />' + 
		'<img id="ListButton_${SelectId}" style="position:absolute;right:0;top:0" src="/images/pricefinder/select_button_disabled.png" />' +
		'<img id="ClearButton_${SelectId}" style="position:absolute;right:-19px;top:0;display:none;cursor:pointer" src="/images/pricefinder/ta_x.gif" />' +
        '</div>' +
		'<div style="position:absolute;top:19px;left:0;width:${width}px;display:none" class="aeroList" id="ListNode_${SelectId}"></div>',
	pushInstance: function(){
	    ch.exmachina.bravofly[this.cName]._instances.push(this);	
	},
	bindEvents: function(){
		this.listButton.observe("click", this.toggleList.bindAsEventListener(this));
		this.clearButton.observe("click", this.clean.bindAsEventListener(this));
		this.selectFieldNode.observe("click", this.toggleList.bindAsEventListener(this));
		this.listNode.observe("mouseover", this.hilightOption.bindAsEventListener(this));
		this.listNode.observe("click", this.clickHandler.bindAsEventListener(this));
		this.selectFieldNode.observe("keydown", this.keydownHandler.bindAsEventListener(this));
//		this.selectFieldNode.observe("blur", this.blurHandler.bindAsEventListener(this));
	},
	hilightOption: function(evt){
		var trg = evt.element();
		if(trg.tagName && trg.tagName.toUpperCase() === "LI"){
			for(var i = 0, l = this.options.length; i < l; i++){
				(this.options[i] === trg) && this.highlightOptionIndex(i);
			}
		}
	},
	highlightOptionIndex: function(/** Number */ index){
        if(!this.options.length){ return; }
		Element.removeClassName(this.options[this.selectedIndex], "selected");
		this.selectedIndex = index % this.options.length;
		Element.addClassName(this.options[this.selectedIndex], "selected");
	},
	// hooks
	onClose: function(){
	},
	onFirstChange: function(){
	},
	onLoadOnce: function(){
	},
	onLoad: function(){
	},
    onComplete: function(){
    },
	onChange: function(){
	},
	onClean: function(){
	},
	addFirstOption: function(/** Object */ fo){
		this.firstOption = fo;
		this.listData.unshift(fo);
		this.createList();
	},
	setIndex: function(/** Integer */ newIndex){
		this.selectedIndex = newIndex;
		this.setValue(this.listData[newIndex].value);
	},
	setKey: function(/** String */ key){
		for(var i = 0; i < this.listData.length; i++){
            if(this.listData[i].key == key){
                this.setValue(this.listData[i].value);
            }
        }
	},
    getKeyIndex: function(/** String */ key){
		for(var i = 0; i < this.listData.length; i++){
            if(this.listData[i].key == key){
                return i;
            }
        }
        return -1;
    },
    getKey: function(){
        for(var i = 0; i < this.listData.length; i++){
            if(ch.exmachina.bravofly.utils.unescapeHTML(this.listData[i].value) == this.selectFieldNode.value){
                var key = this.listData[i].key;
            }
        }
        return key;
    },
    get_Key: function(){
        for(var i = 0; i < this.listData.length; i++){
            if(ch.exmachina.bravofly.utils.unescapeHTML(this.listData[i].value) == this.selectFieldNode.value){
                var key = this.listData[i]._key;
            }
        }
        return key;
    },
	getValue: function(){
		return this.selectFieldNode.value;
	},
	setValue: function(/** String */ value){
        value = value || "";
        var nextValue = ch.exmachina.bravofly.utils.unescapeHTML(value),
            fireChange = (this.selectFieldNode.value !== nextValue)
        ;
		this.selectFieldNode.value = nextValue;
        if(fireChange && this._evtFired){
	        this.onFirstChange();
        	this.onChange();
        	this.onFirstChange = function(){};
        }
        this._evtFired = false;
	},
    fillInData: function(/** Object */ d){
		this.selectedIndex = 0;
	    var ld = this.listData = d.clone();
        if(this.firstOption && ld[0].key){
            ld.unshift(this.firstOption);
        }
        this.createList();
        this.setValue(ld[0]["value"]);
    },
	onShowList: function(){
	},
	onHideList: function(){
	},
	loadData: function(/** Object */ args){
        var self = this;
        args.json = (this.contentType == "json");
		new Ajax.Request(this.url, {
			asynchronous: this.asynchLoad,
	  		method: 'POST',
			evalJSON: true,
			parameters: args,
			onSuccess: function(transport){
				self.fillInData(self.dataKey ? transport.responseJSON[self.dataKey] : transport.responseJSON);
                self.onLoad.call(self);
				self.onLoadOnce.call(self);
				self.onLoadOnce = function(){};
			},
			onFailure: function(){
				window.alert("failure");
			},
			onException: function(req, exc){
				window.alert(this + " " + exc);
			}
		});
	},
    clean: function(){
        this.onClean();
    },
	toggleList: function(evt){
		if(this.disabled){ return; }
		var dis = this.listNode.style.display === "none" ? "block" : "none";
		this.listNode.style.display = dis;
		if(dis === "block"){
			this.onShowList();
            ch.exmachina.bravofly[this.cName].events["open"] = this;
			this.highlightOptionIndex(this.selectedIndex);
			this.selectFieldNode.focus();
		}else{
			this.onHideList();
            ch.exmachina.bravofly[this.cName].events["open"] = null;
        }
	},
	showList: function(){
		this.onShowList();
		this.highlightOptionIndex(this.selectedIndex);
		this.listNode.style.display = "block";
		this.selectFieldNode.focus();
	},
	hideList: function(){
		this.onHideList();
		this.listNode.style.display = "none";
	},
	serializeData: function(){
		return this.listData.toJSON();
	},
	trimList: function(){
		while(this.listData[0] && !this.listData[0].key){
			this.listData.shift();
		}
	},
	createList: function(){
		var d = this.listData,
			content = "<ul>"
		;
		// optionType
		// 1 normale
		// 2 separatore (titoletto) - NON SELEZIONABILE
		// 3 sottochiave (valore indentato)
		for(var i = 0, dlen = d.length; i < dlen; i++){
			if(d[i]._delimiter === true || d[i].optionType === 2){
				content += "<li class='item_delimiter";
			}else if(d[i]._delimiter === false || d[i].optionType === 1){
				content += "<li class='item_delimited";
			}else if(typeof d[i]._delimiter === "undefined" || d[i].optionType === 3){
				content += "<li class='";
			}
			content += " " + (d[i].imposedClassName || "" ) + "'>"
			content += d[i]["value"] + "</li>";
		}
		content += "</ul>";
		this.listNode.innerHTML = content;
		return content;
	},
	disable: function(/** Object */args){
        args = args || {};
		this.hideList();
		this.disabled = true;
		this.listButton.src = "/images/pricefinder/select_button_disabled.png";
		!args.keepData && this.setValue(this.promptText);
	},
	enable: function(){
		this.disabled = false;
		this.listButton.src = "/images/pricefinder/select_button.png";
	},
	setOption: function(/** String */ optValue){
		for(var i = 0; i < this.listData; i++){
			if(optValue == ""){}
		}
	},
    isValid: function(){
        return !!this.getKey();
    },
	keydownHandler: function(evt){
		if(this.disabled){ return; }
		switch(evt.keyCode){
			case Event.KEY_RETURN:
                this._evtFired = true;
				this.setValue(this.listData[this.selectedIndex]["value"]);
                this.onComplete();
			case Event.KEY_ESC:
				this.hideList();
			return;
			case Event.KEY_UP:
				this.highlightOptionIndex(this.selectedIndex - 1 + this.options.length);
				Event.stop(evt);
			return;
			case Event.KEY_DOWN:
				this.highlightOptionIndex(this.selectedIndex + 1);
				Event.stop(evt);
			return;
			case Event.KEY_PAGEUP:
				this.highlightOptionIndex(Math.max(this.selectedIndex - 10, 0));
				Event.stop(evt);
			return;
			case Event.KEY_PAGEDOWN:
				this.highlightOptionIndex(Math.min(this.selectedIndex + 10, this.options.length - 1));
				Event.stop(evt);
			return;
			case Event.KEY_HOME:
				this.highlightOptionIndex(0);
				Event.stop(evt);
			return;
			case Event.KEY_END:
				this.highlightOptionIndex(this.options.length - 1);
				Event.stop(evt);
			return;
			default:
				var kp = String.fromCharCode(evt.keyCode).toLowerCase(),
					opts = this.options,
					si = this.selectedIndex + 1
				;
				for(var i = 0, l = opts.length, oIdx; oIdx = (si + i) % l, i < l; i++){
					if(opts[oIdx].innerHTML.toLowerCase().startsWith(kp)){
						this.highlightOptionIndex(oIdx);
						break;
					}
				}
			return;
		}
	},
    unbindEvents: function(){},
	destroy: function(){
    	this.onClose();
		this.unbindEvents();
		this.domNode.parentNode.parentNode.removeChild(this.domNode.parentNode);
        var _inst = ch.exmachina.bravofly[this.cName]._instances;
        _inst.splice(_inst.indexOf(this), 1);
	},
	clickHandler: function(evt){
		if(this.disabled){ return; }
		var trg = evt.element();
		if(trg.tagName && trg.tagName.toUpperCase() === "LI" && !trg.hasClassName("item_delimiter")){
            this._evtFired = true;
			this.setValue(trg.innerHTML);
			this.hideList();
            this.onComplete();
		}
	},
    toString: function(){
        return "[ch.exmachina.bravofly.Select] key = " + this.getKey() + "; value = " + this.getValue();
    }
};
ch.exmachina.bravofly.Select.events = {};
Event.observe(document, "click", ch.exmachina.bravofly.Select.blurHandler);
