/* ---------------------------------------

	Google Map

--------------------------------------- */


var mapLoaded;
CuSoonMap = Class.create();
CuSoonMap.prototype = {
	formName: null,
	maxBounds: null,
	afterInitFunction: null,
	doNotInitControls: null,
	maxShown: 50,
	categoryNames: $H(),
	listening: true,
	mapId: null,

	icon: null,

	initialize: function(formName, afterInitFunction, mapId, doNotInitControls) {
		this.formName = formName;
		this.mapId = mapId;
		this.doNotInitControls = doNotInitControls;
		this.afterInitFunction = afterInitFunction;
		Event.asap(this.scheduleInit.bind(this));
    },

    scheduleInit: function() {
		setTimeout(this.loadApi.bind(this), 200);
    },
    
    loadApi: function() {
    	mapLoaded = this.initMap.bind(this);
    	var script = document.createElement("script");
	    script.type = "text/javascript";
	    script.src = "http://maps.google.com/maps?file=api&v=2.x&key="+googleKey+"&hl=de&async=2&callback=mapLoaded";
	    document.body.appendChild(script);
    },

	initMap: function() {
    	if (GBrowserIsCompatible()) {
   			Event.observe(window, 'unload', GUnload);
			this.map = new GMap2($(this.mapId ? this.mapId : "map"));
		}

		this.icon = new GIcon();

		this.icon.iconSize = new GSize(36, 36);
		this.icon.iconAnchor = new GPoint(1, 35);
		this.icon.image = defaulticon;

    	if (GBrowserIsCompatible()) {
			if (this.formName) {
				this.map.addControl(new GLargeMapControl());
				this.map.addControl(new GMapTypeControl());
				// this.map.addControl(new GOverviewMapControl());
				this.map.enableDoubleClickZoom();
				this.map.enableContinuousZoom();
				//this.map.enableScrollWheelZoom();
				//this.map.enableDragging();

				GEvent.addListener(this.map, "moveend", this.scheduleUpdate.bind(this));
			}
			else if(!this.doNotInitControls) {
				this.map.addControl(new GSmallZoomControl());
				this.map.enableDoubleClickZoom();
				this.map.enableContinuousZoom();
				//this.map.enableScrollWheelZoom();
				this.map.enableDragging();
			}

			this.maxBounds = new GLatLngBounds();
			this.entryCache = $H();

			this.afterInitFunction(this);
		}
  	},

  	scheduleUpdate: function() {
  		if (this.listening) {
  			clearTimeout(this.executer);
			this.executer = setTimeout(this.updateMap.bind(this),500);
  		}
  	},

  	zoomTo: function(lat, lng, zoomlevel) {
		this.map.setCenter(new GLatLng(lat, lng), zoomlevel);
	},

	adjustZoom: function(lat, lng, zoomlevel) {
		zoomLevel = this.map.getBoundsZoomLevel(this.maxBounds);
		this.map.setZoom(zoomLevel);
		
		while(!this.map.getBounds().containsBounds(this.maxBounds)) {
			this.map.setZoom(this.map.getZoom()-1);	
		}
		// this.map.setCenter(this.maxBounds.getCenter());
	},



    currentInfo: null,

    getIconUrl: function(result, type){
        return result['icon'].replace(/_blau\.png/, '_' + type +'.png');
    },

	zIndex: 0,

	createMarker: function(result) {
		var entry = new Object();
		var _this = this;
		entry.overlayed = false;
		entry.point = new GLatLng(result.lat,result.lng);
		this.maxBounds.extend(entry.point);

		var options = {draggable: false, icon: this.icon};
		options.icon.image = result.icon;

		// Should we use a custom z-index function?
		if (this.map.getCenter().lat() == result.lat && this.map.getCenter().lng() == result.lng) {
			options.zIndexProcess = function(marker, undef) { return 900 + (zIndex++) };
		}
		else {
			options.zIndexProcess = function(marker, undef) { return (_this.zIndex++) };
		}

		entry.marker = new GMarker(entry.point, options);
		entry.result = result;
		// entry.marker.enableDragging();
		entry.defaultImage = entry.marker.getIcon().image;

		if ($(entry.result.id)) {
			entry.info = $(entry.result.id).innerHTML;

			GEvent.addListener(entry.marker, "mouseover", function() {
					_this.currentInfo = entry;
					_this.selectPoint(entry.marker, _this.getIconUrl(entry.result, 'gruen'));
					overlib(entry.info);
			});

			GEvent.addListener(entry.marker, "mouseout", function() {
					_this.selectPoint(entry.marker, entry.defaultImage);
					nd();
			});

			GEvent.addListener(entry.marker, "click", function() {
					location.href = '/' + result.url;
			});
		}

		return entry;
	},

	updateMap: function() {
		var params = $H({
			swlat: this.map.getBounds().getSouthWest().lat(),
			swlng: this.map.getBounds().getSouthWest().lng(),
			nelat: this.map.getBounds().getNorthEast().lat(),
			nelng: this.map.getBounds().getNorthEast().lng(),
			keyword: '',
			q: query
		});

		this.submit(params);
	},

	submitSearch: function(page) {
     	var params = null;
		if (page) {
			$('page').value = page;
			params = $H({
				swlat: this.map.getBounds().getSouthWest().lat(),
				swlng: this.map.getBounds().getSouthWest().lng(),
				nelat: this.map.getBounds().getNorthEast().lat(),
				nelng: this.map.getBounds().getNorthEast().lng(),
				keyword: '',
				q: query
			});
		}
		else {
			$('page').value = '';
		}
		this.submit(params);
	},

	oldMap : null,

	submit: function(params) {
		if (!params) {
			params = $H();
		}

		$(this.formName).fire('form:submit');
		// params = params.merge(Form.serialize($(this.formName), true));
		
		var _this = this;
		this.oldMap = $('map');
		$('mapbox').replaceChild(this.oldMap.cloneNode(true), this.oldMap);
		// oldMap.style.display = 'none';
		// $('contentcolumn').appendChild(oldMap);
		new Ajax.Updater('resultarea', $(this.formName).action, {
		  asynchronous: true,
		  parameters: params.toObject(),
		  method: 'post',
		  evalScripts:true,
		  onComplete: function() {
			$('mapbox').replaceChild(_this.oldMap, $('map'));
		  }
		});
	},

	hideMarkers: function(result) {
		// Todo: Performance: Only Hide markers not in result
	    this.entryCache.each(function (pair) {
			entry = pair.value;

			if (!entry.marker.isHidden())
				entry.marker.hide();
		});
	},

	selectPoint: function(marker, image) {
		marker.setImage(image);
		this.entryCache.each(function (pair) {
			otherEntry = pair.value;

			if (otherEntry.point.equals(marker.getPoint()))
				otherEntry.marker.setImage(image);
		});
	},

	addJsonResult: function(json, keep) {
		var _this = this;
		_this.results = json;
		if (!keep) {
			_this.hideMarkers();
		}
	    json.each(
   			function (resultEntry) {
				var entry = _this.entryCache.get(resultEntry.id);
				if (!entry) {
					entry = _this.createMarker(resultEntry);
					_this.entryCache.set(entry.result.id, entry);
					_this.map.addOverlay(entry.marker);
				}

				if (entry.marker.isHidden())
					entry.marker.show();

				entry.li = $(entry.result.id);
		   	}
	    )
	},
	
	highlightMarker: function(id) {
		if (this.entryCache.get(id)) {
			this.entryCache.get(id).defaultImage = this.getIconUrl(this.entryCache.get(id).result, 'gruen');
			this.selectPoint(this.entryCache.get(id).marker, this.getIconUrl(this.entryCache.get(id).result, 'gruen'));
		}
	}
}