var fbGoogleMap = FbElement.extend({
	initialize : function(element, options) {
		this.parent(element, options);
		this.element = $(element);

		// this.element_map = element + "_map";
		this.options = {
			'lat' : 0,
			'lat_dms' : 0,
			'key' : '',
			'lon' : 0,
			'lon_dms' : 0,
			'threeD' : false,
			'zoomlevel' : '13',
			'control' : '',
			'maptypecontrol' : '0',
			'overviewcontrol' : '0',
			'scalecontrol' : '0',
			'drag' : 0,
			'maptype' : 'G_NORMAL_MAP',
			'geocode' : false,
			'latlng' : false,
			'latlng_dms' : false,
			'staticmap' : 0,
			'auto_center' : false,
			'center' : 0
		};
		$extend(this.options, options);
		this.setOptions(element, options);
		if (this.options.center == 1) {
			if (geo_position_js.init()) {
				geo_position_js.getCurrentPosition(this.geoCenter.bind(this), this.geoCenterErr.bind(this), {
					enableHighAccuracy : true
				});
			} else {
				fconsole('Geo locaiton functionality not available');
			}
		}
		switch (this.options.maptype) {
			case 'G_NORMAL_MAP':
				this.options.maptype = G_NORMAL_MAP;
				break;
			case 'G_SATELLITE_MAP':
				this.options.maptype = G_SATELLITE_MAP;
				break;
			case 'G_HYBRID_MAP':
				this.options.maptype = G_HYBRID_MAP;
				break;
		}
		document.addEvent('domready', function() {
			this.makeMap();
		}.bind(this));
	},

	getValue : function() {
		if ($type(this.field) !== false) {
			return this.field.getValue();
		}
		;
		return false;
	},

	makeMap : function() {
		if ($type(this.element) === false) {
			return;
		}
		this.field = this.element.getElement('input.fabrikinput');
		this.watchGeoCode();
		if (GBrowserIsCompatible() && this.options.staticmap) {
			var i = this.element.getElement('img');
			var w = i.getStyle('width').toInt();
			var h = i.getStyle('height').toInt();
		}

		if (GBrowserIsCompatible() && !this.options.staticmap) {
			this.map = new GMap2($(this.element).getElement('.map'));
			this.map.setCenter(new GLatLng(this.options.lat, this.options.lon), this.options.zoomlevel.toInt());
			if (this.options.scrollwheel != '0') {
				this.map.enableScrollWheelZoom();
			}
			var point = new GLatLng(this.options.lat, this.options.lon);
			var opts = {};
			if (this.options.drag == 1) {
				opts.draggable = true;
			} else {
				opts.draggable = false;
			}
			if (this.options.latlng == true) {
				$(this.element).getElement('.lat').addEvent('blur', this.updateFromLatLng.bindAsEventListener(this));
				$(this.element).getElement('.lng').addEvent('blur', this.updateFromLatLng.bindAsEventListener(this));
			}

			if (this.options.latlng_dms == true) {
				$(this.element).getElement('.latdms').addEvent('blur', this.updateFromDMS.bindAsEventListener(this));
				$(this.element).getElement('.lngdms').addEvent('blur', this.updateFromDMS.bindAsEventListener(this));
			}

			this.marker = new GMarker(point, opts);

			if (this.options.latlng == true) {
				$(this.element.id).getElement('.lat').value = this.marker.getLatLng().lat() + '° N';
				$(this.element.id).getElement('.lng').value = this.marker.getLatLng().lng() + '° E';
			}

			if (this.options.latlng_dms == true) {
				$(this.element.id).getElement('.latdms').value = this.latDecToDMS();
				$(this.element.id).getElement('.lngdms').value = this.lngDecToDMS();
			}

			GEvent.addListener(this.marker, "dragend", function() {
				this.field.value = this.marker.getLatLng() + ":" + this.map.getZoom();
				if (this.options.latlng == true) {
					$(this.element).getElement('.lat').value = this.marker.getLatLng().lat() + '° N';
					$(this.element).getElement('.lng').value = this.marker.getLatLng().lng() + '° E';
				}
				if (this.options.latlng_dms == true) {
					$(this.element).getElement('.latdms').value = this.latDecToDMS();
					$(this.element).getElement('.lngdms').value = this.lngDecToDMS();
				}
			}.bind(this));
			GEvent.addListener(this.map, "zoomend", function(oldLevel, newLevel) {
				this.field.value = this.marker.getLatLng() + ":" + this.map.getZoom();
			}.bind(this));
			if (this.options.auto_center && this.options.editable) {
				GEvent.addListener(this.map, "moveend", function() {
					this.marker.setLatLng(this.map.getCenter());
					this.field.value = this.marker.getLatLng() + ":" + this.map.getZoom();
					if (this.options.latlng == true) {
						$(this.element).getElement('.lat').value = this.marker.getLatLng().lat() + '° N';
						$(this.element).getElement('.lng').value = this.marker.getLatLng().lng() + '° E';
					}
					if (this.options.latlng_dms == true) {
						$(this.element).getElement('.latdms').value = this.latDecToDMS();
						$(this.element).getElement('.lngdms').value = this.lngDecToDMS();
					}
				}.bind(this));
			}
			this.map.addOverlay(this.marker);
			switch (this.options.control) {
				case 'GLargeMapControl':
					this.options.threeD == true ? this.map.addControl(new GLargeMapControl3D()) : this.map.addControl(new GLargeMapControl());
					break;
				case 'GSmallMapControl':
					this.map.addControl(new GSmallMapControl());
					break;
				case 'GSmallZoomControl':
					this.options.threeD == true ? this.map.addControl(new GSmallZoomControl3D()) : this.map.addControl(new GSmallZoomControl());
					break;
			}
			if (this.options.scalecontrol != '0') {
				this.map.addControl(new GScaleControl());
			}
			if (this.options.maptypecontrol != '0') {
				this.map.addControl(new GMapTypeControl());
			}
			if (this.options.overviewcontrol != '0') {
				this.map.addControl(new GOverviewMapControl());
			}
			this.map.setMapType(this.options.maptype);
		}
	},

	updateFromLatLng : function() {
		var lat = $(this.element.id).getElement('.lat').get('value').replace('° N', '').toFloat();
		var lng = $(this.element.id).getElement('.lng').get('value').replace('° E', '').toFloat();
		var pnt = new GLatLng(lat, lng);
		this.marker.setLatLng(pnt);
		this.map.setCenter(pnt, this.map.getZoom());
		this.field.value = this.marker.getLatLng() + ":" + this.map.getZoom();
		$(this.element).getElement('.latdms').value = this.latDecToDMS();
		$(this.element).getElement('.lngdms').value = this.lngDecToDMS();
	},

	updateFromDMS : function() {
		var latdms = $(this.element.id).getElement('.latdms').get('value').replace('S', '-');
		latdms = latdms.replace('N', '');
		var lngdms = $(this.element.id).getElement('.lngdms').get('value').replace('W', '-');
		lngdms = lngdms.replace('E', '');

		var latdms_d_ms = latdms.split('°');
		var latdms_topnt = latdms_d_ms[0];
		var latdms_m_s = latdms_d_ms[1].split('\'');
		var latdms_m = latdms_m_s[0].toFloat() * 60;
		var latdms_ms = (latdms_m + latdms_m_s[1].replace('"', '').toFloat()) / 3600;
		latdms_topnt = Math.abs(latdms_topnt.toFloat()) + latdms_ms.toFloat();
		if (latdms_d_ms[0].toString().indexOf('-') != -1) {
			latdms_topnt = -latdms_topnt;
		}

		var lngdms_d_ms = lngdms.toString().split('°');
		var lngdms_topnt = lngdms_d_ms[0];
		var lngdms_m_s = lngdms_d_ms[1].split('\'');
		var lngdms_m = Math.abs(lngdms_m_s[0].toFloat()) * 60;
		var lngdms_ms = (lngdms_m + Math.abs(lngdms_m_s[1].replace('"', '').toFloat())) / 3600;
		lngdms_topnt = Math.abs(lngdms_topnt.toFloat()) + lngdms_ms.toFloat();
		if (lngdms_d_ms[0].toString().indexOf('-') != -1) {
			lngdms_topnt = -lngdms_topnt;
		}

		var pnt = new GLatLng(latdms_topnt.toFloat(), lngdms_topnt.toFloat());
		this.marker.setLatLng(pnt);
		this.map.setCenter(pnt, this.map.getZoom());
		this.field.value = this.marker.getLatLng() + ":" + this.map.getZoom();
		$(this.element).getElement('.lat').value = latdms_topnt + '° N';
		$(this.element).getElement('.lng').value = lngdms_topnt + '° E';
	},

	latDecToDMS : function() {
		var latdec = this.marker.getLatLng().lat();
		var dmslat_d = parseInt(Math.abs(latdec));
		var dmslat_m_float = 60 * (Math.abs(latdec).toFloat() - dmslat_d.toFloat());
		var dmslat_m = parseInt(dmslat_m_float);
		var dmslat_s_float = 60 * (dmslat_m_float.toFloat() - dmslat_m.toFloat());
		// var dmslat_s = Math.round(dmslat_s_float.toFloat()*100)/100;
		var dmslat_s = dmslat_s_float.toFloat();

		if (dmslat_s == 60) {
			dmslat_m = dmslat_m.toFloat() + 1;
			dmslat_s = 0;
		}
		if (dmslat_m == 60) {
			dmslat_d = dmslat_d.toFloat() + 1;
			dmslat_m = 0;
		}

		var dmslat_dir = 'N';
		if (latdec.toString().indexOf('-') != -1) {
			dmslat_dir = 'S';
		} else {
			dmslat_dir = 'N';
		}

		return dmslat_dir + dmslat_d + '°' + dmslat_m + '\'' + dmslat_s + '"';

	},

	lngDecToDMS : function() {
		var lngdec = this.marker.getLatLng().lng();
		var dmslng_d = parseInt(Math.abs(lngdec));
		var dmslng_m_float = 60 * (Math.abs(lngdec).toFloat() - dmslng_d.toFloat());
		var dmslng_m = parseInt(dmslng_m_float);
		var dmslng_s_float = 60 * (dmslng_m_float.toFloat() - dmslng_m.toFloat());
		// var dmslng_s = Math.round(dmslng_s_float.toFloat()*100)/100;
		var dmslng_s = dmslng_s_float.toFloat();

		if (dmslng_s == 60) {
			dmslng_m.value = dmslng_m.toFloat() + 1;
			dmslng_s.value = 0;
		}
		if (dmslng_m == 60) {
			dmslng_d.value = dmslng_d.toFloat() + 1;
			dmslng_m.value = 0;
		}

		var dmslng_dir = '';
		if (lngdec.toString().indexOf('-') != -1) {
			dmslng_dir = 'W';
		} else {
			dmslng_dir = 'E';
		}

		return dmslng_dir + dmslng_d + '°' + dmslng_m + '\'' + dmslng_s + '"';

	},

	geoCode : function(event) {
		var e = new Event(event);
		this.geocoder = new GClientGeocoder();
		var address = '';
		if (this.options.geocode == '2') {
			this.options.geocode_fields.each(function(field) {
				address += $(field).value + ',';
			});
			address = address.slice(0, -1);
		} else {
			address = $(this.element.id).getElement('.geocode_input').value;
		}
		this.geocoder.getLatLng(address, function(geocoded_point) {
			if (!geocoded_point) {
				// alert(address + " not found!");
			} else {
				this.marker.setLatLng(geocoded_point);
				this.map.setCenter(geocoded_point, this.map.getZoom());
				this.field.value = geocoded_point + ":" + this.map.getZoom();
				if (this.options.latlng == true) {
					$(this.element.id).getElement('.lat').value = geocoded_point.lat() + '° N';
					$(this.element.id).getElement('.lng').value = geocoded_point.lng() + '° E';
				}
				if (this.options.latlng_dms == true) {
					$(this.element.id).getElement('.latdms').value = this.latDecToDMS();
					$(this.element.id).getElement('.lngdms').value = this.lngDecToDMS();
				}
			}
		}.bind(this));
	},

	watchGeoCode : function() {
		if (!this.options.geocode || !this.options.editable) {
			return false;
		}
		if (this.options.geocode == '2') {
			if (this.options.geocode_event != 'button') {
				this.options.geocode_fields.each(function(field) {
					if ($type($(field)) !== false) {
						$(field).addEvent('keyup', this.geoCode.bindAsEventListener(this));
					}
				}.bind(this));
			} else {
				if (this.options.geocode_event == 'button') {
					$(this.element).getElement('.geocode').addEvent('click', this.geoCode.bindAsEventListener(this));
				}
			}
		}
		if (this.options.geocode == '1' && $(this.element).getElement('.geocode_input')) {
			if (this.options.geocode_event == 'button') {
				$(this.element.id).getElement('.geocode').addEvent('click', this.geoCode.bindAsEventListener(this));
			} else {
				$(this.element.id).getElement('.geocode_input').addEvent('keyup', this.geoCode.bindAsEventListener(this));
			}
		}
	},

	unclonableProperties : function() {
		return [ 'form', 'marker', 'map', 'maptype' ];
	},

	cloned : function(c) {
		var f = [];
		this.options.geocode_fields.each(function(field) {
			var bits = $A(field.split('_'));
			var i = bits.getLast();
			if (i != i.toInt()) {
				return bits.join('_');
			}
			i++;
			bits.splice(bits.length - 1, 1, i);
			f.push(bits.join('_'));
		});
		this.options.geocode_fields = f;
		this.makeMap();
	},

	update : function(v) {
		v = v.split(':');
		if (v.length < 2) {
			v[1] = this.options.zoomlevel;
		}
		var zoom = v[1].toInt();
		this.map.setZoom(zoom);
		v[0] = v[0].replace('(', '');
		v[0] = v[0].replace(')', '');
		var pnts = v[0].split(',');
		if (pnts.length < 2) {
			pnts[0] = this.options.lat;
			pnts[1] = this.options.lon;
		}
		// $$$ hugh - updateFromLatLng blows up if not displayinbg lat lng
		// also, not sure why we would do this, as all we want to do is set map back
		// to default
		// location, not read location from lat lng fields?
		// this.updateFromLatLng(pnts[0], pnts[1]);
		// So instead, lets just set marker to default and recenter
		var pnt = new GLatLng(pnts[0], pnts[1]);
		this.marker.setLatLng(pnt);
		this.map.setCenter(pnt, this.map.getZoom());
	},

	geoCenter : function(p) {
		this.map.setCenter(new GLatLng(p.coords.latitude.toFixed(2), p.coords.longitude.toFixed(2)));
	},

	geoCenterErr : function(p) {
		fconsole('geo location error=' + p.message);
	}

});
