/*
 * MapObject - The JavaScript Mapping Library.
 * http://MapObject.net
 * 
 * Copyright (c) 2006-2007, Mashup Technologies, LLC
 * All rights reserved.
 * http://www.MashupTechnologies.com
 * 
 * The JavaScript code distributed with Google Maps Samples (the "Software") is licensed under the
 * Lesser GNU (LGPL) open source license version 3.
 * 
 * http://www.gnu.org/licenses/lgpl.html
 * 
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 */

/**
* MapObject - The JavaScript Mapping Library.
* http://MapObject.net
* 
* Copyright (c) 2006-2007, Mashup Technologies, LLC
* All rights reserved.
* http://www.MashupTechnologies.com
* 
* The JavaScript code distributed with Google Maps Samples (the "Software") is licensed under the
* Lesser GNU (LGPL) open source license version 3.
* 
* http://www.gnu.org/licenses/lgpl.html
* 
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*/

// Create MapObject namespace
Ext.namespace('MapObject.proxy');

/**
* Google geocoder proxy class.
* @namespace MapObject.proxy
* @class GoogleGeocoder
* @constructor
* @param none
* Notes: See notes.txt
* 
*/
MapObject.proxy.GoogleGeocoder = function () {
	this.addEvents({
		/**
		* @event beforegeocoding
		* Fires before gecoding is done.
		*/
		beforegeocoding : true,

		/**
		* @event aftergeocoding
		* Fires after gecoding
		* @param {String} Lat Latitute.
		* @param {String} Lng Longitude.
		* @param {Integer} Zoom Zoom level.
		*/
		aftergeocoding : true
	});

    MapObject.proxy.GoogleGeocoder.superclass.constructor.call(this);
}

Ext.extend(MapObject.proxy.GoogleGeocoder, Ext.util.Observable, {

	// Singleton
	gGeocoder: null,

	/* Accuracy Levels
	* 0 	Unknown location. (Since 2.59)
	* 1 	Country level accuracy. (Since 2.59)
	* 2 	Region (state, province, prefecture, etc.) level accuracy. (Since 2.59)
	* 3 	Sub-region (county, municipality, etc.) level accuracy. (Since 2.59)
	* 4 	Town (city, village) level accuracy. (Since 2.59)
	* 5 	Post code (zip code) level accuracy. (Since 2.59)
	* 6 	Street level accuracy. (Since 2.59)
	* 7 	Intersection level accuracy. (Since 2.59)
	* 8 	Address level accuracy. (Since 2.59)
	*/

	accuracy: [
		{
			version: '2.67',
			levels: [
				1, //0
				4, //1
				7, //2
				9, //3
				10, //4
				11, //5
				13, //6
				14, //7
				16 //8
			]
		}
	],

	/**
	* Geocode given address and re-center map. Geocode using GClientGeocoder or Yahoo service.
	* @param	{String}	location	Location address
	*/
	geocode: function(address) 
	{
		// Is GClientGeocoder defined
		if (this.gGeocoder == null)
			this.gGeocoder = new GClientGeocoder();
			
		if (this.gGeocoder) 
		{
			this.fireEvent("beforegeocoding");

			/* use more advanced method with results analyses
			this.gGeocoder.getLatLng(
				address,
				function(point) 
				{
					if (!point) 
					{
						alert(address + " not found");
					} else 
					{
						this.mapObject.setCenter(point, 14);
					}
				}.bind(this));
			*/

			// Use accuracy for setting proper zoom level
			// getLatLngAsync ???
			this.gGeocoder.getLocations(
				address,

				GEvent.callback(this, function(response) 
				{
					if (!response || response.Status.code != 200) {
						alert("\"" + address + "\" not found. Error code: " + response.Status.code);
					} else {
						place = response.Placemark[0];
						accuracy = place.AddressDetails.Accuracy;
						point = new GLatLng(place.Point.coordinates[1],
											place.Point.coordinates[0]);
						if (this.debug) this.LogWriter.log('"' + address + '" geocoded to accuracy ' + accuracy + ", which is converted to " + this.accuracy[0].levels[accuracy] + ' zoom level', "Info");
						
						// Original map set center code
						//this.mapObject.setCenter(point, this.accuracy[0].levels[accuracy]);

						//Run callback method. See notes.txt.
				       	this.fireEvent("aftergeocoding",
				       		place.Point.coordinates[1], 
				       		place.Point.coordinates[0], 
				       		this.accuracy[0].levels[accuracy]
				       	);
					}
				}));
		}
	},


	// avoid trailing commas
	EOF:null
});
