function CitySelector() {
	this.cityurl = "/locationquery.jhtml";
	this.cityaction = "cityBestMatchesJSON";
	this.cityFormName = "tripForm";
	this.termFieldName = "queryTerm";
	this.termFieldId = "cityinput";
	this.cityListDivId = "selectCityPrompt";
	this.updateFunction;
	this.clearFunction;
	this.maxResults=10;
	this.querycount=0;
	this.cityIds = new Array();
	this.regionIds = new Array();
	this.countryIds = new Array();
	this.fieldchanged = false;
	this.cityform;
	this.termfield;
	this.citylist;
	this.citylistUL;
	this.citylistDIV;
	this.currentTerm = "";
	this.selection_in_process = false;
	this.emptySearchCallbackFunction;
	this.selectactive = false;
	this.listVals = new Array();
	this.cityselected;
	this.visibleList = new Array();
	this.enter_exempt = false;
	this.termFieldHeight;
	this.cityPromptStartPos=null;
}

CitySelector.prototype.setTermFieldName = function(termFieldName) {
	var oo = this;
	oo.termFieldName = termFieldName;
}

CitySelector.prototype.setTermFieldId = function(termFieldId) {
	var oo = this;
	oo.termFieldId = termFieldId;
}

CitySelector.prototype.setCityListDivId = function(cityListDivId) {
	var oo = this;
	oo.cityListDivId = cityListDivId;
}

CitySelector.prototype.setUpdateFunction = function(func) {
	var oo = this;
	oo.updateFunction = func;
}

CitySelector.prototype.setClearFunction = function(func) {
	var oo = this;
	oo.clearFunction = func;
}

CitySelector.prototype.setEmptySearchCallbackFunction = function(func) {
	var oo = this;
	oo.emptySearchCallbackFunction = func;
}


CitySelector.prototype.retrieveCityList = function() {
	var oo = this;

	oo.querycount++;
	var cnt = oo.querycount;
	var data = new Object();
	data["term"] = oo.termfield.val();
	data["action"] = oo.cityaction;
	data["suggestLength"] = oo.maxResults;
	$.ajax({
		url: oo.cityurl,
		type: 'POST',
    dataType: 'json',
    timeout: 10000,
    data:data,
    error: function(req, textStatus, errorThrown){
    	oo.processCityListJSONError(textStatus+" "+errorThrown, cnt);
		},
    success: function(data){
    	oo.processCityListFromJSON(data,cnt);
		}
	});
}

CitySelector.prototype.processCityListJSONError = function(errorThrown, cnt) {
	var oo = this;

	if (cnt != oo.querycount) {
		return;
	}
	if (typeof oo.emptySearchCallbackFunction == "function") {
			oo.emptySearchCallbackFunction();
	}
	oo.selection_in_process = false;
}

CitySelector.prototype.processCityListFromJSON = function(data, cnt) {
	var oo = this;
	if (cnt != oo.querycount) {
		return;
	}

	if(data.result.error > 0) {
		oo.processCityListJSONError(data.result.error);
		return;
	}

	if (!data.result.recommendation && !data.result.suggestions) {
		if (typeof oo.emptySearchCallbackFunction == "function") {
			oo.emptySearchCallbackFunction();
		}
	}

	var listHTML = "";
	var locations = new Array();
	if (data.result.recommendation && data.result.recommendation.length > 0) {
		locations.push(data.result.recommendation);
	}

	if (data.result.suggestions) {
		for (i=0;i<data.result.suggestions.length;i++) {
			locations.push(data.result.suggestions[i]);
		}
	}

	for (i=0;i<locations.length;i++) {
		var location = locations[i];
		var locationStr = "";
		if (!location || !location.city) {
			continue;
		}
		if (location.city.name && location.city.name.length > 0) {
			locationStr += location.city.name+", ";
		}
		if (location.region.name && location.region.name.length > 0) {
			locationStr += location.region.name+", ";
		}
		if 	(location.country.name && location.country.name.length > 0) {
			locationStr += location.country.name;
		}
		locationStr = "<li id='loc-"+i+"'>"+locationStr+"</li>";
		oo.cityIds[i] = location.city.id;
		oo.regionIds[i] = location.region.id;
		oo.countryIds[i] = location.country.id;
		listHTML+=locationStr;
	}

	if (locations.length > 0 ) {
		$(oo.citylistUL).html(listHTML);
		oo.initVars(); //refresh the vars that we are using
		oo.setUpList($(oo.citylist));
		oo.highlightCity( $(oo.termfield).val(),$(oo.citylist));
 		oo.selection_in_process = true;
		$(oo.citylist).bgiframe({height: $("#"+oo.cityListDivId).height()});
	} else  {
    oo.selection_in_process = false;
    $(oo.citylistDIV).addClass("hide");
	}
}

CitySelector.prototype.moveHover = function(offset) {
	var oo = this;
	var selected = -1;
	var newindex = -1;

	for (i =0; i < oo.visibleList.length; i++){
		var item = oo.visibleList[i];
		if($(item).is(".over")) {
			selected = i;
		}
	}
	$(oo.citylist).each(function(){$(this).removeClass("over")});
	newindex = selected +offset;
	if (newindex > -1 && newindex < oo.visibleList.length) {
		$(oo.visibleList[newindex]).addClass("over");
	 	oo.cityselected = $(oo.visibleList[newindex]);
	}
}

CitySelector.prototype.setUpList = function(list) {
	var oo = this;

	$(".selectCityPrompt").addClass("hide");

	oo.listVals = new Array();
	if ($(list).length == 0) {
		return;
	}
	$(list).each(function(i){
		oo.listVals[i] = $(this).html();
	});
	$(oo.citylistDIV).removeClass("hide");
	$(oo.citylistDIV).css("z-index",2000);

	if (!$.browser.msie) {
		var x = $(oo.citylistDIV).position();
		if (this.cityPromptStartPos==null) {
			this.cityPromptStartPos = x;
		}
		var newTop = this.cityPromptStartPos.top + this.termFieldHeight;
		$(oo.citylistDIV).css({top: newTop});
	}
}

CitySelector.prototype.refreshVisible = function(list) {
	var oo = this;
	oo.visibleList = new Array();
	if ($(list).length == 0) {
		return;
	}
	$(list).each(function(i){
		if (!$(this).is(".hide")) {
			oo.visibleList.push($(this));
		}
	});
}

CitySelector.prototype.selectCity = function(item) {
	var oo = this;

	if (!oo.selectionUnderway()) {
  	return;
	}

	if (!item ||  $(item).length <=0) {
		return;
	}

  $(oo.citylistDIV).addClass("hide");
	var id = $(item).attr("id").replace("loc-","");
	$(oo.termfield).val(oo.listVals[id]);

	oo.enter_exempt = true;

	if (oo.updateFunction) {
		oo.updateFunction(oo.cityIds[id], oo.regionIds[id], oo.countryIds[id]);
	}
}

CitySelector.prototype.doCityLookup = function(e) {
	var oo = this;

	if ($(oo.termfield).val() == oo.currentTerm) {
		return;
	}
	oo.currentTerm = $(oo.termfield).val();

	if (typeof oo.clearFunction == "function") {
		oo.clearFunction();
	}
	oo.retrieveCityList();
	oo.activateCitySelect(e);
}


CitySelector.prototype.cityinputKeyUp = function(e) {
	var oo = this;
	switch (e.which) {
  	case 9:
    	break;
		case 38: // up
    	oo.moveHover(-1);
			break;
		case 40: // down
    	oo.moveHover(1);
			break;
		case 13: // enter
    	if (oo.enter_exempt) {
				oo.enter_exempt = false;
				return;
			} else { oo.doCityLookup(e) };
			break;
		case 27: //	escape
    	$(oo.citylistDIV).addClass("hide");
	    oo.selection_in_process = false;
      break;
		case 39: // right arrow
    	break;
    case 37: // left arrow
			break;
		default:
    	oo.doCityLookup(e);
	}
}

CitySelector.prototype.activateCitySelect = function(e) {
	var oo = this;

	oo.highlightCity($(e.target).val(), oo.citylist );
	oo.currentTerm = $(oo.termfield).val();
}

CitySelector.prototype.highlightCity = function(inputStr,list) {
	var oo = this;

	if (!inputStr || $(list).length == 0 || inputStr.length == 0) {
		return;
	}

	var matchdone = false;

	$(list).each(function(i) {
			if ($(this).is(".hide")) {
				$(this).removeClass("hide");
			}
			$(this).html(oo.listVals[i]); 	// reset each one
			var matching = ($(this).html().toLowerCase().indexOf(inputStr.toLowerCase()) == 0);

			if (!matchdone && matching)  {
				matchdone = true;
				oo.boldTextPortion(inputStr, $(this));
			}
	});
	if (matchdone && $(oo.citylistDIV).is(".hide")) {
		$(oo.citylistDIV).removeClass("hide");
	}
	oo.refreshVisible(list);
}

CitySelector.prototype.boldTextPortion = function(inputString, listitem) {
	var oo = this;

	if ($(listitem).length == 0 || inputString.length == 0 ) {
		return;
	}

	var fullstr = $(listitem).html();
	if (fullstr.toLowerCase().indexOf(inputString.toLowerCase()) == -1 ) {
		return;
	}

	var index = 	inputString.length;
	var prevstr = fullstr.substring(0,index);
	var afterstr = "";

	if (fullstr.length > inputString.length) {
		afterstr = fullstr.substring(inputString.length);
	}

	$(listitem).html("<span class='hilited'>"+prevstr+"</span>"+afterstr);

	oo.refreshBehaviours();
}

CitySelector.prototype.initVars = function() {
	var oo = this;

	oo.cityform = $('form[name="'+oo.cityFormName+'"]');
	oo.termfield =  $('#'+oo.termFieldId); //'form[name="'+cityFormName+'"] input[name="'+ termFieldName +'"]');
	oo.currentTerm = $(oo.termfield).val();
	oo.citylist =  $('#'+oo.cityListDivId+' ul li');
	oo.citylistUL =  $('#'+oo.cityListDivId+' ul');
	oo.citylistDIV =  $('#'+oo.cityListDivId);
}

CitySelector.prototype.setCitySelectorTop = function(val) {
	var oo = this;
	if (val >0) {
  	if ($(oo.termfield).outerHeight() > 0) {
  		this.termFieldHeight = val;
		}
	}
}

CitySelector.prototype.refreshBehaviours = function() {
	var oo = this;

	oo.initVars();
	if ($(oo.citylist).length > 0) {
		$(oo.citylist).hover(
			function () {$(this).addClass("over");
				oo.cityselected = $(this);
			},
			function () {if (   $(this).is(".over") )
				$(this).removeClass("over");
			}
		);
		$(oo.citylist).click(function () {oo.selectCity($(this));}   );
	}
}

CitySelector.prototype.selectionUnderway = function() {
	var oo = this;

	if ($(oo.citylistDIV).is(".hide")) {
    return false;
	}
 	return true;
}

CitySelector.prototype.reattachCitySelector = function() {
	var oo = this;
	oo.initVars();

	try {
		$(oo.termfield).attr("autocomplete","off");
		$(oo.termfield).keyup(function(e) {
			return oo.cityinputKeyUp(e);
		});
		$(oo.termfield).keydown(function(e){
			if (e.keyCode == 13)oo.selectCity(oo.cityselected);
		});
		$(oo.termfield).keypress(function(e){
			if (e.keyCode == 13) return false;
		});
		$(oo.termfield).blur(function(e) {
			//$(oo.citylistDIV).addClass("hide");
	    //oo.selection_in_process = false;
		})

		if ($(oo.termfield).outerHeight() > 0) {
			oo.setCitySelectorTop($(oo.termfield).outerHeight());
		}
	} catch (e) {}
}

$(document).ready(function() {
	//reattachCitySelector();
});