
/**
 * 	@package GMap
 *	@extends HTMLElement.GMap
 *	@extends HTMLElement.GMapLocalizer
 */

/////////////////////////////////////////////////////////////////////////

var gmaps = {
	objects: [],
	selected: null,
	add: function (gmap) {
		this.objects.push(gmap);
		this.selected = gmap;
	},
	geocoder: new GClientGeocoder()
};

/////////////////////////////////////////////////////////////////////////

HTMLElement.prototype.GMap = function (options) {
	
	gmap = new GMap(this, options);
	gmap.initialize();
	
	return gmap;
};

HTMLElement.prototype.GMapLocalizer = function (options) {
	
	options = {
		center: 'Deutschland',
		zoom: 6,
		inputTextLabel: 'Strasse, Stadt oder Postleitzahl ...',
		startLocation: { lat: 49.3172844, lng: 8.4310066 }//,
		//params: { values: {lat:0,lng:0}, labels: {lat:0,lng:0} }
	};
	
	localizer = new GMapLocalizer(this, options);
	localizer.initialize();
	
	return localizer;
};

/////////////////////////////////////////////////////////////////////////

GMap = function (selector, options) {
	
	/**
	 *	Parent HTML Selector
	 *	@var HTMLElement
	 */
	this.selector = selector;
	
	/**
	 *	Transformation Options for this Run
	 *	@var Object
	 */
	this.options = options;
	
	/**
	 *	Google Map Object
	 *	@var GMap2
	 */
	this.googleMap = null;
		
	/**
	 *	GMap Markers
	 *	@var Array
	 */
	this.markers = [];
	
	/**
	 *	GMap Points
	 *	@var Array
	 */
	this.points = [];
	
	/**
	 *	Calls the Google-Map Function
	 *	@return void
	 */
	this.initialize = function () {
		
		this.googleMap = new GMap2(this.selector);
		
		gmaps.add(this);
		
		if ( ! /((^)|(\s))gmap-gmap(($)|(\s))/.test(this.selector.className)) 
			this.selector.className += ' gmap-gmap';
		
		this.googleMap.addControl(new GSmallMapControl());
		this.googleMap.addControl(new GMapTypeControl());

		if (this.options.center) 
			setTimeout( function () {
				gmaps.selected.setCenter(gmaps.selected.options.center);
			}, 1000);
			
		return this;
	};

	/**
	 *	Adds Marker to GMap
	 *	@return void
	 */
	this.marker = function (latlng) {
		
		if ( ! latlng instanceof GLatLng) {
			latlng = new GLatLng(latlng.lat, latlng.lng);
		}
		marker = new GMarker(latlng);
		this.googleMap.addOverlay(marker);
		GEvent.addListener(marker, 'mouseover', function(coordKey) { 
			//$('#c5r-popup-gmap').html('$html').show(); 
		});
		GEvent.addListener(marker, 'click', function(coordKey) {	
			//document.location.href = '$url'; 
		});
		
		this.markers.push(marker);
	};
		
	/**
	 *	Uses Google Geocoder to get the Coordinates to Address
	 *	@return void
	 */
	this.addressToLatLng = function (address, callback) {
		
		gmaps.geocoder.getLatLng(address, callback);
	};
	
	/**
	 *	Sets the Center of Google Map
	 *	@return void
	 */
	this.setCenter = function (center, zoom) {
		
		if ( ! center) return false;
		
		if (zoom) this.options.zoom = zoom;
				
		setizeCenter = function (latlng) {
			if ( ! latlng instanceof GLatLng) return false;
			gmaps.selected.googleMap.setCenter(latlng, gmaps.selected.options.zoom);
		};
		if (typeof(center) == 'string') this.addressToLatLng(center, setizeCenter);
		else setizeCenter(center);
	};
	
	return this;
}

GMapLocalizer = function (selector, options) {

	if (options.params) {
		if (options.params.values) {
			options.params.values.lat = document.getElementById(options.params.values.lat);
			options.params.values.lng = document.getElementById(options.params.values.lng);  
		}
		if (options.params.labels) {
			options.params.labels.lat = document.getElementById(options.params.labels.lat);
			options.params.labels.lng = document.getElementById(options.params.labels.lng);
		}
	}

	/**
	 *	GMap Object
	 *	@var GMap
	 */
	this.gmap = null;
	
	/**
	 *	Address Input Object
	 *	@var Object: text(HTMLInputElement), button(HTMLInputElement)
	 */
	this.input = {
		text: null,
		button: null,
		lat: null, 
		lng: null,
		gmap: null
	};
	
	/**
	 *	Event Wrapper Function
	 *	@param String event
	 *	@param String attribute
	 *	@param Callback = 
	 */
	this.decorate = function (attribute, event, callback) {
		
		method = function (object, element) {
			return function (event) {
				return callback(object, element, event);
			};
		};
		
		eval('this.'+attribute+'.'+event+' = method(this, this.'+attribute+')');
	};
	
	/**
	 *	Parent HTML Selector
	 *	@var HTMLElement
	 */
	this.selector = selector;
	
	/**
	 *	Transformation Options for this Run
	 *	@var Object
	 */
	this.options = options;
	
	/**
	 *	Generates the HTML-Code
	 *	@return String (HTML)
	 */
	this.html = function () {
		
		var code = '';
		
		code += '<style type="text/css">';
		code += 	'div.gmap-localizer {  } ';
		code += 	'div.gmap-localizer-yes { background: #f0ffef; color: #60a625; border: 1px #60a625 solid; }';
		code += 	'div.gmap-localizer-no { background: #fff0ef; color: #900; border: 1px #900 solid; }';
		code += 	'div.gmap-localizer-wait { background: #ffffdf; color: #990; border: 1px #990 solid; }';
		code += 	'div.gmap-localizer-input { height: 40px; } ';
		code += 	'div.gmap-localizer-input>* { float: left; } ';
		code += 	'div.gmap-localizer-gmap { clear: both; width: 100%; height: 100%; min-width: 600px; min-height: 300px; } ';
		code += 	'div.gmap-localizer-gmap { margin-top: 10px; } ';
		code += 	'div.gmap-localizer-input-coord { padding: 0px 10px 0px 10px; } ';
		code += 	'div.gmap-localizer-input-status { margin: 4px; -moz-border-radius: 6px; width: 32px; height: 32px; font-size: 12px; opacity: 0.4; } ';
		code += 	'div.gmap-localizer-input-text { padding: 8px; -moz-border-radius: 6px;  font-size: 18px; color: #333; background: #fff ! important; border: 1px #d0d0d0 solid ! important; } ';
		code += 	'div.gmap-localizer-input-text input { font-size: 14px; width: 300px; background: transparent; border-width:0px; color: #888888; } ';
		code += 	'input.gmap-localizer-input-coord { padding: 2px 5px 2px 5px; -moz-border-radius: 4px; font-size: 10px; color: #a0a0a0; } ';
		code += 	'input.gmap-localizer-input-button { border: 1px #a0a0a0 outset;  padding: 3px 10px 3px 10px; opacity: 0.5; background: #f8f8f8; -moz-border-radius: 8px; width: 100px; font-size: 16px; cursor: pointer; } ';
		code += 	'input.gmap-localizer-input-button-over {  border: 1px #fff inset; padding: 4px 9px 2px 11px; opacity: 1.0; background: #fafafa; color: #aaa; } ';
		code += 	'div.gmap-localizer-input input { margin: 1px; text-align: center; }';
		code += '</style>';

		code += '<div class="gmap-localizer">';
		code += 	'<div id="'+this.options.id+'-input" class="gmap-localizer-input">';
		code += 		'<div class="gmap-localizer-input-status gmap-localizer-wait">&nbsp;</div>';
		code += 		'<div class="gmap-localizer-input-text"><input type="text" value="'+this.options.inputTextLabel+'" size="40" /></div>';
		code += 		'<div class="gmap-localizer-input-coord">';
		code += 			'<input type="text" value="Breitengrad" class="gmap-localizer-input-coord gmap-localizer-wait" size="10" disabled="disabled" readonly="readonly" />';
		code +=				'<br style="clear: both;" />';
		code += 			'<input type="text" value="Längengrad" class="gmap-localizer-input-coord gmap-localizer-wait" size="10" disabled="disabled" readonly="readonly" />';
		code +=			'</div>';
		code += 		'<input type="button" value="Suchen" class="gmap-localizer-input-button" />';
		code +=		'</div>';
		code += 	'<div id="'+this.options.id+'-gmap" class="gmap-localizer-gmap"></div>';
		code += '</div>';
		
		return code;
	};
	
	/**
	 *	GMap-Localizer and appends to Selector
	 *	@return void
	 */
	this.initialize = function () {
		
		this.selector.innerHTML = this.html();
		
		this.gmap = document.getElementById(this.options.id+'-gmap').GMap(this.options);
		
		input = document.getElementById(this.options.id+'-input');
		this.input.status = input.firstChild;
		this.input.text = input.firstChild.nextSibling.firstChild;
		this.input.lat = input.firstChild.nextSibling.nextSibling.firstChild;
		this.input.lng = input.firstChild.nextSibling.nextSibling.firstChild.nextSibling.nextSibling;
		this.input.button = input.firstChild.nextSibling.nextSibling.nextSibling;
		
		//// BUTTON
		this.decorate('input.button', 'onclick', function (object, element, event) {	object.gmap.addressToLatLng(object.input.text.value, function (latlng) {
			if ( ! latlng) {
				object.input.lat.className = object.input.lat.className.replace(/(wait)|(yes)/, 'no');
				object.input.lng.className = object.input.lng.className.replace(/(wait)|(yes)/, 'no');
				object.input.status.className = object.input.status.className.replace(/(wait)|(yes)/, 'no');
				return true;
			}
			object.input.lat.className = object.input.lat.className.replace(/(wait)|(no)/, 'yes');
			object.input.lng.className = object.input.lng.className.replace(/(wait)|(no)/, 'yes');
			object.input.status.className = object.input.status.className.replace(/(wait)|(no)/, 'yes');
		
			object.input.lat.value = latlng.lat();
			object.input.lng.value = latlng.lng();
								
			this.gmap.marker(latlng);
			
			gmaps.selected.setCenter(latlng, 12);
		})});
		this.decorate('input.button', 'onmouseover', function (object, element, event) {	
			element.className += ' gmap-localizer-input-button-over';
		});
		this.decorate('input.button', 'onmouseout', function (object, element, event) {	
			element.className = element.className.replace('gmap-localizer-input-button-over', '');
		});
		//// TEXT
		this.decorate('input.text', 'onkeyup', function (object, element, event) {	
			object.input.text.onkeypress = function (event) {
				if (event.keyCode == 13) {
					object.input.button.onclick();
					return false;
				}
			}
		});
		this.decorate('input.text', 'onblur', function (object, element, event) {	
			if (/^\s*$/.test(element.value))
				element.value = object.options.inputTextLabel;
				
		});
		this.input.text.onfocus = function () {
			this.value = '';
		};

		this.input.text.onclick = function () {
			this.value = '';
		};
	};
	
	return this;
};
