var demandmap = demandmap || {};

// TODO implement _t()
var i18n = i18n || {};

// language strings
jQuery.i18n.addDictionary({
	'REALLYDELETE': "Do you really want to delete this point?"
});

;(function($) {
	
	$.fn.DemandMap_MapEdit = function(mapSelector, _options) { 
		
		// config
		var defaults = {
			'zoomSelected': 12,
			'baseCountryCode': "NZ",
			'markerIconsByID': [],
			'zoomStart': 5, // roughly fits New Zealand boundaries
			'lat': -41.28648,
			'lng': 174.776217, // Wellington, New Zealand
			'zoomAccuracyBase': 9, // @see http://code.google.com/apis/maps/documentation/reference.html#GGeoAddressAccuracy
			'defaultMarkerIcon': null
		};
		

		
		return this.each(function(){
			defaults.defaultMarkerIcon

			// ######## private instance properties #########
			var options = $.extend({}, defaults, _options);			

			// Reference to this control
			var $this = $(this);
			var container = this;
			
			var map = $(mapSelector);
			
			var myMarker;
			
			var addressFields = $("input[name='StreetNumber'], input[name='Street'], input[name='Suburb'], input[name='City'], input[name='PostalCode'], select[name='Region']", container);
			
			// alert user before deleting a point
			$('.deletepoint a', container).bind('click',function(e) {
				return confirm($.i18n._t('REALLYDELETE'));
			});
			
			// Build the JSON version of a single point
			var existingCategoryID = $('select[name=CategoryID]', container).val();
			var markerData = {};

			//addMode = document.URL.match('/addpoint');
			editMode = document.URL.match('/point');

			// if categoryID is NOT specified and NOT in addMode, it is in edit mode
			if(existingCategoryID || editMode) {
				var zoom = options.zoomSelected;
					
				// populate markerdata from form and load it as a marker
				$("input, select", container).each(function() {
					markerData[$(this).attr('name')] = $(this).val();
				});

				markerData.Point = { x : markerData['Point[x]'], y : markerData['Point[y]'] };
				
				myMarker = updateMarker(
					new GLatLng(Number(markerData.Point.y), Number(markerData.Point.x)),
					zoom,
					false
				);
			} else {
				markerData.Point = { x : options.lng, y : options.lat };
				markerData.icon = options.defaultMarkerIcon;
				var zoom = options.zoomStart;
				// add marker to map
				var markers = map.fn('addMarkers', [markerData]);
				myMarker = markers[0];
				// don't show the marker initially if no data was loaded
				myMarker.hide();
				// if it's in addMode and CategoryID is specify, show the marker
				if (existingCategoryID) {
					updateMarker(
						myMarker.getPoint(),
						$('select[name=CategoryID]', container).val(),
						false
					);
					myMarker.show();
				}
			}
			
			map.fn('setCenter', 
				new GLatLng(Number(markerData.Point.y), Number(markerData.Point.x)),
				zoom
			);
	
			// Set up geo-coding on address fields
			addressFields.bind('change', function() {
					// geocoding only if we have a city value
					if($("input[name='City']", container).val()) {
						var address = '';
						if(val = $("input[name='StreetNumber']", container).val()) address += val;
						if(val = $("input[name='Street']", container).val()) address += ' ' + val;
						if(val = $("input[name='Suburb']", container).val()) address += ', ' + val;
						if(val = $("input[name='City']", container).val()) address += ', ' + val;
						if(val = $("input[name='Postalcode']", container).val()) address += ', ' + val;
						if(val = $("select[name='Region']", container).val()) address += ', ' + val;
	
						var geocoder = new GClientGeocoder();
						geocoder.setBaseCountryCode(options.baseCountryCode);
						geocoder.getLocations(address, updateFromPlacemarks);
					}
				});
				
			$('select[name=CategoryID]', container).bind('change', function(e) {
				updateMarker(
					myMarker.getPoint(),
					$('select[name=CategoryID]', container).val(),
					true
				);
			});
	
			/*
			var url = $.sprintf('api/v1/DemandPoint.json?OwnerID=%d', currentUserID); 
	
			// Do a JSON request for my points
			$.getJSON(url, function(data) {
				// Add those points to the map
				map.fn('addMarkers', data);
			});
			*/
		
			/**
			 * @param GPlacemark collection placemark
			 * @param boolean override If set to TRUE, overrides previously filled out fields
			 */
			function updateFields(placemark, overrideExisting, clearFilledOutFields) {
				var latLng = new GLatLng(placemark.Point.coordinates[1], placemark.Point.coordinates[0]);

				updateMarker(latLng, $('select[name=CategoryID]', container).val(), false);
				
				// Update latlng point and zoom based on placemark accuracy
				map.fn('setCenter', latLng, options.zoomAccuracyBase + placemark.AddressDetails.Accuracy);
				
				// override is ignored, we always want to update the point data
				$('#Point-x', container).val(latLng.lng());
				$('#Point-y', container).val(latLng.lat());
				
				// Decode address
				// somehow google has two XAL formatting standards in reverse and traditional geocoding
				if(typeof placemark.AddressDetails.Country != 'undefined' && typeof placemark.AddressDetails.Country.AdministrativeArea != 'undefined') {
					var locality = placemark.AddressDetails.Country.AdministrativeArea.Locality;
				} else if(typeof placemark.AddressDetails.Country != 'undefined' && typeof placemark.AddressDetails.Country.Locality != 'undefined') {
					var locality = placemark.AddressDetails.Country.Locality;
				} else {
					var locality = null;
				}
				if(!locality) return false;
				
				if(typeof locality.Thoroughfare != 'undefined') {
					var thoroughfare = locality.Thoroughfare.ThoroughfareName;
					if(thoroughfare.match(/^([0-9\-\s]+) +(.*)$/)) {
						var streetNumber = RegExp.$1;
						var street = RegExp.$2;
					} else {
						var streetNumber = "";
						var street = thoroughfare;
					}
				} else {
					var thoroughfare = null;
					var streetNumber = null;
					var street = null;
				}
				var postalCode = (typeof locality.PostalCode != 'undefined') ? locality.PostalCode.PostalCodeNumber : null;
				//var city = locality.LocalityName;
				var suburb = locality.LocalityName;
				var country = (typeof placemark.AddressDetails.Country != 'undefined') ? placemark.AddressDetails.Country.CountryNameCode : null;
				var region = (typeof placemark.AddressDetails.Country != 'undefined' && typeof placemark.AddressDetails.Country.AdministrativeArea != 'undefined') ? placemark.AddressDetails.Country.AdministrativeArea.AdministrativeAreaName : null;
			
				// clear address fields if necessary
				addressFields.each(function(i) {
					var field = $(addressFields[i]);
					if(clearFilledOutFields) field.val('');
				});
				
				// Update empty address fields (or explicitly override)
				if(overrideExisting || !$("input[name='StreetNumber']", container).val()) $("input[name='StreetNumber']", container).val(streetNumber);
				if(overrideExisting || !$("input[name='Street']", container).val()) $("input[name='Street']", container).val(street);
				if(overrideExisting || !$("input[name='Suburb']", container).val()) $("input[name='Suburb']", container).val(suburb);
				//if(overrideExisting || !$("input[name='City']", container).val()) $("input[name='City']", container).val(city);
				if(overrideExisting || !$("input[name='PostalCode']", container).val()) $("input[name='PostalCode']", container).val(postalCode);
				if(overrideExisting || !$("input[name='Country']", container).val()) $("input[name='Country']", container).val(country);
				if(overrideExisting || !$("select[name='Region']", container).val()) $("select[name='Region']", container).val(region);
			}
			
			function updateMarker(latLng, categoryID, doUpdateFields) {
				var geocoder = new GClientGeocoder();
				
				if(doUpdateFields) {
					geocoder.setBaseCountryCode(options.baseCountryCode)
					geocoder.getLocations(latLng , overrideFromPlacemarks);
				}
				
				var markerData = {
					CategoryID: categoryID,
					Point: latLng,
					draggable: true
				};
				map.fn('clearMarkers');
				if(!Number(categoryID)) markerData.icon = options.defaultMarkerIcon;
				
				var markers = map.fn('addMarkers', [markerData]);
				markers[0].show();
				
				GEvent.addListener(markers[0], 'dragend', function(e) {
					var latLng = this.getPoint();
					$('#Point-x', container).val(latLng.lng());
					$('#Point-y', container).val(latLng.lat());
					
					// when a point is moved, the whole address data incl. region is regarded as invalid
					geocoder.getLocations(latLng, overrideFromPlacemarks);
				});
				
				myMarker = markers[0];
				
				return markers[0];
			}
			
			function overrideFromPlacemarks(placemarks) {
				if(placemarks.Status.code == 200 && placemarks.Placemark[0].AddressDetails.Country.CountryNameCode == options.baseCountryCode) {
					var placemark = placemarks.Placemark[0]
					updateFields(placemark, true, true);
				}
			}
			
			function updateFromPlacemarks(placemarks) {
				if(placemarks.Status.code == 200 && placemarks.Placemark[0].AddressDetails.Country.CountryNameCode == options.baseCountryCode) {
					var placemark = placemarks.Placemark[0]
					updateFields(placemark, false);
				}
			}
		})
	}
	
	// reset dropdownfile region to nothing at first
	$("select[name='Region']").val('');
})(jQuery);