/*
 * jQuery geo_autocomplete plugin 2.1.1
 *
 * Copyright (c) 2010 Bob Hitching
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 *
 * Requires jQuery UI Autocomplete
 * 
 */

function remove_accents(s){
	var r=s.toLowerCase();
    //r = r.replace(new RegExp("\\s", 'g'),"");
    r = r.replace(new RegExp("[àáâãäå]", 'g'),"a");
    r = r.replace(new RegExp("æ", 'g'),"ae");
    r = r.replace(new RegExp("ç", 'g'),"c");
    r = r.replace(new RegExp("[èéêë]", 'g'),"e");
    r = r.replace(new RegExp("[ìíîï]", 'g'),"i");
    r = r.replace(new RegExp("ñ", 'g'),"n");                            
    r = r.replace(new RegExp("[òóôõö]", 'g'),"o");
    r = r.replace(new RegExp("œ", 'g'),"oe");
    r = r.replace(new RegExp("[ùúûü]", 'g'),"u");
    r = r.replace(new RegExp("[ýÿ]", 'g'),"y");
    //r = r.replace(new RegExp("\\W", 'g'),"");
    return r;
};
                
$.widget( "ui.geo_autocomplete", {
	// setup the element as an autocomplete widget with some geo goodness added
	_init: function() {
		this.options._geocoder = new google.maps.Geocoder; // geocoder object
		this.options._cache = {}; // cache of geocoder responses
		this.element.autocomplete(this.options);
		
		// _renderItem is used to prevent the widget framework from escaping the HTML required to show the static map thumbnail
		this.element.data('autocomplete')._renderItem = function(_ul, _item) {
			return $('<li></li>').data('item.autocomplete', _item).append(this.options.getItemHTML(_item)).appendTo(_ul);
		};
	},
	
	// default values
	options: {
		geocoder_region: '', // filter to a specific region, e.g. 'Europe'
		geocoder_types: 'locality,political,sublocality,neighborhood,country', // array of acceptable location types, see http://code.google.com/apis/maps/documentation/javascript/services.html#GeocodingAddressTypes
		geocoder_address: true, // true = use the full formatted address, false = use only the segment that matches the search term

		mapwidth: 100, // width of static map thumbnail
		mapheight: 100, // height of static map thumbnail
		maptype: 'terrain', // see http://code.google.com/apis/maps/documentation/staticmaps/#MapTypes
		mapsensor: false, // see http://code.google.com/apis/maps/documentation/staticmaps/#Sensor

		minLength: 3, // see http://jqueryui.com/demos/autocomplete/#option-minLength
		delay: 300, // see http://jqueryui.com/demos/autocomplete/#option-delay
		// callback function to get autocomplete results
		source: function(_request, _response) {
			if (_request.term in this.options._cache) {
				_response(this.options._cache[_request.term]);
			} else {
				var self = this;
				var _address = _request.term + (this.options.geocoder_region ? ', ' + this.options.geocoder_region : '');
				this.options._geocoder.geocode({'address': _address}, function(_results, _status) {
					var _parsed = [];
					if (_results && _status && _status == 'OK') {
						var _types = self.options.geocoder_types.split(',');
						$.each(_results, function(_key, _result) {
							// if this is an acceptable location type with a viewport, it's a good result
							if ($.map(_result.types, function(_type) {
								return $.inArray(_type, _types) != -1 ? _type : null;
							}).length && _result.geometry && _result.geometry.viewport) {

								if (self.options.geocoder_address) {
									_place = _result.formatted_address;
								} else {
									// place is first matching segment, or first segment
									var _place_parts = _result.formatted_address.split(',');
									var _place = _place_parts[0];
									$.each(_place_parts, function(_key, _part) {
										if (_part.toLowerCase().indexOf(_request.term.toLowerCase()) != -1) {
											_place = $.trim(_part);
											return false; // break
										}
									});
								}
								
								var address  = _result.address_components;
								var short_city;
								var short_state;
								var short_country;
								var long_city;
								var long_state;
								var long_country;
								for (i=0; i<address.length; i++){ 
									types=address[i].types; 
									for(j=0; j<types.length; j++){
										if (types[j] == 'locality'){ 
											short_city = address[i].short_name;
											long_city = address[i].long_name;
										}; 
										if (types[j] == 'administrative_area_level_1'){ 
											short_state = address[i].short_name;
											long_state = address[i].long_name;
										};  
										if (types[j] == 'country'){ 
											short_country = address[i].short_name;
											long_country = address[i].long_name;
										};  
									}
								}
								if (short_city)
									short_city = remove_accents(short_city).toLowerCase()
								if (long_city)
									long_city = remove_accents(long_city).toLowerCase();
								
								_parsed.push({
									//value: _place,
									value: _result.formatted_address,
									label: _result.formatted_address,
									viewport: _result.geometry.viewport,
									short_city: short_city,
									long_city: long_city,
									short_state: short_state,
									long_state: long_state,
									short_country: short_country,
									long_country: long_country,
									lat: _result.geometry.location.lat(),
									lng: _result.geometry.location.lng(),
									result: _result
								});
							}
						});
					}
					self.options._cache[_request.term] = _parsed;
					_response(_parsed);
				});
			}
		},
		// returns the HTML used for each autocomplete list item
		getItemHTML: function(_item) {		
			var _src = 'http://maps.google.com/maps/api/staticmap?visible=' + _item.viewport.getSouthWest().toUrlValue() + '|' + _item.viewport.getNorthEast().toUrlValue() + '&size=' + this.mapwidth + 'x' + this.mapheight + '&maptype=' + this.maptype + '&sensor=' + (this.mapsensor ? 'true' : 'false');
			return '<a><img style="float:left;margin-right:5px;" src="' + _src + '" width="' + this.mapwidth + '" height="' + this.mapheight + '" /> ' + _item.label.replace(/,/gi, ',<br/>') + '<br clear="both" /></a>'
		}
	}
});
