function SloppyRegExp (matchOn, mods)
{
	var cm, matched, upper, i, realMatch = '', sub = myObjHints.Hints.sub;
	for (var c = 0; c < matchOn.length; c++) 
	{
		matched = false;
		upper = isUpperCase(matchOn.charAt(c));
		cm = matchOn.charAt(c).toLowerCase();
		for (i in sub) 
		{
			if (sub[i].indexOf(cm) != -1) 
			{
				cm = '[' + sub[i] + ']';
				matched = true;
				break;
			}
		}
		if (upper)
		{
			cm = cm.toUpperCase();
		}
		realMatch += cm + ' ?'; // add optional whitespace
	}
	return new RegExp('(' + realMatch + ')', mods);
}

function isUpperCase (text)
{
	return (text == text.toUpperCase());
}

function highlightSloppy (text, matchOn)
{
	var sloppyMatch = SloppyRegExp(matchOn, 'i');
	if (sloppyMatch.test(text)) 
	{
		var hlss = sloppyMatch.exec(text)[1];
		return text.replace(sloppyMatch, '<strong>'+hlss+'</strong>');
	}
	else
	{
		return text;
	}
}

if (!myObjHints)
	var myObjHints = {};

/*
myObjHints Hints interface
*/
myObjHints.Hints = {
    // il seguente url non dovrebbe includere un dominio. Vedi http://www.captain.at/howto-ajax-permission-denied-xmlhttprequest.php
	BS_URI: './getSuggestedCities.asp?city=',
	BS_TIMEOUT: 100,
	BS_INITIALIZED: false,
	sub: ['aàáâãäåæāăą', 'iìíîïīĭĩ', 'eèéêëēĕėęě', 'oòóôõöōŏő', 'uyùúûüýũūŭůű', ' ?'],
	request: null,
	timeout: false,
	element: null,
	popup: null,
	append: null,
	popupActive: false,
	lastValue: '',
	init: function( elm ) {
		if(!myObjHints.Hints.popup) {
			var contentBody = document.getElementById('bodyconstraint') || document.body;
			// Strange whitespaces/indentation of entries in IE if I remove this table...
			var markup = '<table cellspacing="0" cellpadding="0"><tr><td></td></tr></table>';
			if(document.all && !window.opera)
				markup = '' + markup;
			myObjHints.Hints.popup = document.createElement('div');
			myObjHints.Hints.popup.setAttribute('id', 'suggest_popup');
			myObjHints.Hints.popup.style.display = 'none';
			myObjHints.Hints.popup.innerHTML = markup;
			contentBody.appendChild(myObjHints.Hints.popup);
			myObjHints.Hints.append = myObjHints.Hints.popup.getElementsByTagName('td')[0];
		}
		myObjHints.Hints.element = elm;
		myObjHints.Hints.BS_INITIALIZED = true;
	},
	initRequestObject: function() {
		myObjHints.Hints.request = null;
		// Informazioni sul nome del browser
		browserUser = navigator.userAgent.toUpperCase();
		var req;
		req = getXMLHttpRequest ();
		myObjHints.Hints.request = req;
	},
	handleKeyNav: function( evt, isUp ) {
	if (gClientIsIE5) return true;
		if (evt.keyCode)
		{
			switch (evt.keyCode)
			{
				case 9: // TAB
					if (myObjHints.Hints.popup.selectedSuggestion)
						myObjHints.Hints.popup.selectedSuggestion.onmousedown();
					break;
				case 13: // ENTER
					if (isUp)
						return false;
					if (myObjHints.Hints.popup.selectedSuggestion)
					{
						
						myObjHints.Hints.popup.selectedSuggestion.onmousedown();
						if (evt.preventDefault) evt.preventDefault();
						return false;
					}
					break;
				case 27: // ESC
					myObjHints.Hints.__hidePopup();
					myObjHints.Hints.lastValue = myObjHints.Hints.element.value;
					break;
				case 38: // UP
					if (myObjHints.Hints.popupActive)
						myObjHints.Hints.__previousSuggestion();
					if (evt.preventDefault) evt.preventDefault();
					break;
				case 40: // DOWN
					if (myObjHints.Hints.popupActive)
						myObjHints.Hints.__nextSuggestion();
					if (evt.preventDefault) evt.preventDefault();
					break;
				default:
					return true;
					break;
			}
		}
	},
	handleActivity: function( elm, evt ) {
		if(gClientIsIE5) return;
		if(!myObjHints.Hints.BS_INITIALIZED)
			myObjHints.Hints.init(elm);
		if(elm.value == '') {
			myObjHints.Hints.__hidePopup();
			myObjHints.Hints.lastValue = elm.value;
		}
		else if(elm.value != myObjHints.Hints.lastValue) {
			if(myObjHints.Hints.timeout)
				clearTimeout(myObjHints.Hints.timeout);
			myObjHints.Hints.timeout = setTimeout(myObjHints.Hints.requestSuggestion, myObjHints.Hints.BS_TIMEOUT)
		}
	},
	requestSuggestion: function() {
		if(myObjHints.Hints.element.value=='') {
			myObjHints.Hints.__hidePopup();
			return;
		}
		myObjHints.Hints.initRequestObject();
		var req = myObjHints.Hints.request,
		    url = myObjHints.Hints.BS_URI + encodeURIComponent(myObjHints.Hints.element.value) + '&state='+encodeURIComponent(document.getElementById('statePicker').value),
		    mp = myObjHints.Hints.BS_URI + encodeURIComponent(myObjHints.Hints.element.value)  + '&state='+encodeURIComponent(document.getElementById('statePicker').value);
		    
		req.onreadystatechange = myObjHints.Hints.responseHandler;
		req.open('GET', url, true);
		req.send('');
		
		myObjHints.Hints.lastValue = myObjHints.Hints.element.value;
	},
	responseHandler: function() {
		if(myObjHints.Hints.request.readyState==4) {
			switch(myObjHints.Hints.request.status) {
				case 200: // 200 OK
					
					myObjHints.Hints.parseResponse(myObjHints.Hints.request.responseText);
					break;
				default:
					window.status = statusText[myObjHints.Hints.request.status];
					break;
			}
		}
	},
	parseResponse: function( response ) {
		var append = myObjHints.Hints.append,
		    elm = myObjHints.Hints.element;
		var suggestList = [];
		var rl = response.split('_');
		for(var i=0; rl[i]; i+=2)
			suggestList.push({
				n: rl[i],
				d: rl[i+1]
			});
		
		if(suggestList.length) {
			var spt = '';
			var mstr='';
			myObjHints.Hints.suggestions = [];
			for(var i=0; suggestList[i]; i++) {
				
				var check = suggestList[i].n.indexOf('>');
			  if (check>0){
			  	mstr=suggestList[i].n.substr(check+1)
			  	//alert (mstr);
			  }
				else
					mstr=suggestList[i].n;
					
				
				
				myObjHints.Hints.suggestions[i] = mstr;//suggestList[i].n;
				
				spt += '<div class="suggest_entry" onmouseover="myObjHints.Hints.__setActiveSuggestion(this)" onmouseout="myObjHints.Hints.__unsetActiveSuggestion(this)" onmousedown="myObjHints.Hints.__useSuggestion(' + i + ')">';
				spt += highlightSloppy(suggestList[i].n, myObjHints.Hints.lastValue);
				spt += '<div class="suggest_dist">' + suggestList[i].d + '</div>';
				spt += '</div>';
			}
			append.innerHTML = spt;
			myObjHints.Hints.__showPopup();
			
			spt='';
			for(var i=0; suggestList[i]; i++) {
				spt += myObjHints.Hints.suggestions[i];
			}
			
		}
		else {
			myObjHints.Hints.__hidePopup();
		}
		myObjHints.Hints.popup.selectedSuggestion = null;
	},
	__setActiveSuggestion: function( elm ) {
		if(myObjHints.Hints.popup.selectedSuggestion)
			myObjHints.Hints.__unsetActiveSuggestion(myObjHints.Hints.popup.selectedSuggestion);
		DOM.addClass(elm, 'suggest_entry_selected');
		myObjHints.Hints.popup.selectedSuggestion = elm;
	},
	__unsetActiveSuggestion: function( elm ) {
		DOM.removeClass(elm, 'suggest_entry_selected');
	},
	__nextSuggestion: function() {
		if(myObjHints.Hints.popup.selectedSuggestion && myObjHints.Hints.popup.selectedSuggestion.nextSibling)
			var newSuggestion = myObjHints.Hints.popup.selectedSuggestion.nextSibling;
		else // wrap around
			var newSuggestion = myObjHints.Hints.append.firstChild;
		myObjHints.Hints.__setActiveSuggestion(newSuggestion);
	},
	__previousSuggestion: function() {
		if(myObjHints.Hints.popup.selectedSuggestion && myObjHints.Hints.popup.selectedSuggestion.previousSibling)
			var newSuggestion = myObjHints.Hints.popup.selectedSuggestion.previousSibling;
		else // wrap around
			var newSuggestion = myObjHints.Hints.append.lastChild;
		myObjHints.Hints.__setActiveSuggestion(newSuggestion);
	},
	__useSuggestion: function( index ) {
		myObjHints.Hints.element.value = myObjHints.Hints.suggestions[index] ;
		myObjHints.Hints.__hidePopup();
		//var frm = DOM.getParentOrSelf(myObjHints.Hints.element, 'form');
		//if(frm['ifl']) frm['ifl'].value = '1';
	},
	__showPopup: function() {
		if (myObjHints.Hints.element.value=='')
		{
			myObjHints.Hints.__hidePopup();
			return;
		}
		var elm = myObjHints.Hints.element;
		var popup = myObjHints.Hints.popup;
		var elmPos = getDimensions(elm);
		var left = elmPos.x;
		var top = elmPos.y + (elm.offsetHeight);
		popup.style.left = left + 'px';
		popup.style.top  = top + 'px';
		popup.style.display = 'none'; // hide to force redraw, fixes rendering bug in ff 1.0.x
		popup.style.display = 'block';
		myObjHints.Hints.popupActive = true;
	},
	__hidePopup: function() {
		if(gClientIsIE5) return;
		var hideIt = function() {
			myObjHints.Hints.popup.style.display = 'none';
		}
		setTimeout(hideIt, 100);
		myObjHints.Hints.popupActive = false;
		// XXX: really do this here?
		myObjHints.Hints.popup.selectedSuggestion = null;
		myObjHints.Hints.lastValue = '';
	}
};
