function CICOverlay(json) {

	var ZOOM_LEVEL_LAND 		= 6;
	var ZOOM_LEVEL_REGION 	= 8;
	var ZOOM_LEVEL_ORT 			= 10;
	var ZOOM_LEVEL_OBJECT 	= 12;
	var ZOOM_LEVEL_DEFAULT	= 12;
	var MAP_LOADED = false;


	/*
   * @param is a json object containing the search parameters
	 *				- IDReiseart
	 *				-	Hotelart
	 *				-	IDLand
	 *				- Region
   */
	this.param = json.param;

	/*
   * @zielgebiet is an Array containing name and geodata of zielgebiet (Lang, Region, Ort oder Objekt) 
   */
	this.zielgebiet = json.data;

	/*
   * @hasOverlayText is boolean variable, overlays are the custom icons that represent zielgebiet
										 on googlemap. After creating overlays the text will be dynamically appended
										 in overly DIVs. after appending text it will be set to true.	
   */
	this.hasOverlayText = false;	

	/*
   * @zielgebietReference is a Hash representation of zielgebiet object. with zielgebiet ID as Key.
   */
	this.zielgebietReference = {};

	/*
	 * zoomlevelContainer is a temprary information container.
	 * It container information like whether the MapBounds should be fitted or not
	 * Similarly it contains the lat & lng of map center. This information will be set in updateMap function
	 * before loading the map again.
	 */	
	var zoomlevelContainer = cic.$('zoomlevelContainer');
	var mapcenter = zoomlevelContainer.getAttribute('mapcenter');

	/*
   * @latlng is an instance of google.maps.LatLng.
   */
	if(mapcenter == null) {
		this.latlng = new google.maps.LatLng(this.zielgebiet[0].lat, this.zielgebiet[0].lng);
	} else {
		mapcenter =  eval( '(' + mapcenter + ')' );
		this.latlng = new google.maps.LatLng(mapcenter.lat, mapcenter.lng);
	}	

//	this.latlng = new google.maps.LatLng(52.639121, 14.864258);
	
	/*
   * @mapBounds represents a rectangle in geographical coordinates, including 
								one that crosses the 180 degrees longitudinal meridian
   */
	this.mapBounds = new google.maps.LatLngBounds(); 

	/*
   * @options is json object contining the setting for our googlemap.
   */

	switch(this.param.typeParent) {
		case 'null'		: zoomLevel = ZOOM_LEVEL_LAND; 		break;
		case 'land'		: zoomLevel = ZOOM_LEVEL_REGION; 	break;
		case 'region'	: zoomLevel = ZOOM_LEVEL_ORT; 		break;
		case 'ort'		: zoomLevel = ZOOM_LEVEL_OBJECT; 	break;
		default				: zoomLevel = ZOOM_LEVEL_DEFAULT;
	}

	this.options = {
    		zoom: zoomLevel,
    		center: this.latlng,
    		mapTypeId: google.maps.MapTypeId.ROADMAP,
				mapTypeControl: true, 
	    	mapTypeControlOptions: {style: google.maps.MapTypeControlStyle.DEFAULT}
  		};


		/*
  	 * @map is an instance of google.maps.Map.
		 */
    this.map = new google.maps.Map(document.getElementById("googlemapsearch_body"),this.options);

		this.iconarray = [];

		/*
		 * @that is a global reference to this object.
		 */
		that = this;

		/*
		 * registring googlemaps event listeners.
		 */
    google.maps.event.addListener(this.map, 'tilesloaded', function(overlayControl, countries) {
			return function() {
			 setTimeout("that.setOverlaysText(that.overlayControl, that.countries)",1000)	
//	     that.setOverlaysText(that.overlayControl, that.countries);
			}
    }(this.overlayControl, this.zielgebiet));

		
		zoomChangeBoundsListener = google.maps.event.addListener(this.map, 'bounds_changed', function(event) {
			if (this.getZoom() > 14) // Change max/min zoom here
            this.setZoom(14);
           google.maps.event.removeListener(zoomChangeBoundsListener);
    });

		google.maps.event.addListener(this.map, 'zoom_changed', function() {
				if(!MAP_LOADED) {MAP_LOADED = true; return;}
				switch(that.map.getZoom())
				{
					case ZOOM_LEVEL_LAND:
							 that.updateMap('land');   	
							 break;
	

					case ZOOM_LEVEL_REGION:
							 that.updateMap('region');   	
							 break;

					case ZOOM_LEVEL_ORT:
							 that.updateMap('ort');   	
							 break;

					case ZOOM_LEVEL_OBJECT:
							 that.updateMap('objekt');   	
							 break;
				}
  	});
}

CICOverlay.prototype = {
	setMarkers: function() {

		/*
		 * @image is a custom image of Markers on googlemap.
		 */
		var image = new google.maps.MarkerImage('/images/icon.png', new google.maps.Size(170, 52), 
																						 new google.maps.Point(0,0), new google.maps.Point(0, 52));

		/*
		 * @_url contains the URL for each marker, which will be remotely called on clicking
						 the marker.
		 */
		var querystring = this.getQueryStringfromParam();

		this.mapBounds = new google.maps.LatLngBounds();

		/*
		 * Looping over zielgebiet, to place Markers on googlemap.
		 */
  	for (var i = 0; i < this.zielgebiet.length; i++) {
    	var jsonObj = this.zielgebiet[i];
			var markerIndex = jsonObj.idparent;

			/*
			 * appending zielgebiet Hash reference.
			 */
			this.zielgebietReference[markerIndex] = {'name': jsonObj.name, 'angebot':jsonObj.numberOfProducts, 'id': jsonObj.idparent}
			
			
			/*
			 * appending _url with object specific values.
			 */
			if(jsonObj.type == 'null')
				var url = querystring + "&suchartfrom=googlemap&idobjekt=" + jsonObj.idparent;
			else	
				var url = querystring + "&sucheGoogleMapType=" + jsonObj.type + "&sucheGoogleMapIDParent=" + jsonObj.idparent;
			
			/*
			 * instantiate LatLng object for the zielgebiet object.
			 */	
	    var latlng = new google.maps.LatLng(parseFloat(jsonObj.lat), parseFloat(jsonObj.lng));

			
			/*
			 * Creating customized for the zielgebiet object.
			 */	

  	  var marker = new google.maps.Marker({
    	    position: latlng,
      	  map: this.map,
        	icon: image,
				  zIndex: parseInt(markerIndex)
    	});
			this.iconarray.push(marker);
			
			/*
			 * Creating customized for the zielgebiet object.
			 */	
			this.mapBounds.extend(latlng); 
			
			google.maps.event.addListener(marker, 'click', function(_url, type) {
				return function() {
					if(type == 'null') {
						window.location.href = "/web/index.cfm/pm/detail" + _url;
					}
					else {
	     			cic.$('zoomlevelContainer').innerHTML = 1;
						updateKarteRecherche(_url)
					}
				}
    	}(url, jsonObj.type));
  	}

		/*
 		 * @overlayControl is an instance of IconControl class. which is extension
											 of OverlayView class. in Order to gat access to the googlemao
												Panes.	
		 */	
    this.overlayControl = new IconControl(this.map);


	},
	
	getQueryStringfromParam: function() {

		var _querystring = "?";

		// Looping over the param object's properties.
		for(property in this.param) {

			var value = (this.param[property]) ? this.param[property] : "";

			if(_querystring.length > 1) {	_querystring +=  "&"; }

			_querystring +=  property + "=" + value;
		}
		return _querystring;
		
	},

	updateMap: function(type) {
		var zoomlevelContainer = cic.$('zoomlevelContainer'); 
				zoomlevelContainer.innerHTML = 0;
				zoomlevelContainer.setAttribute('mapCenter', '{lat:"'+this.map.getCenter().lat()+'", lng:"'+this.map.getCenter().lng()+'"}');

		// Check if Current data is same that user wants to access.
		if(type == 'land' 	&& this.param.typeParent == 'null') 	return;
		if(type == 'region' && this.param.typeParent == 'land') 	return;
		if(type == 'ort' 		&& this.param.typeParent == 'region') return;
		if(type == 'objekt' && this.param.typeParent == 'ort') 		return;

		var _querystring = "?";
		_querystring = _querystring.concat("sucheGoogleMapIDReiseart=", this.param.sucheGoogleMapIDReiseart);
		_querystring = _querystring.concat("&sucheGoogleMapHotelart=", this.param.sucheGoogleMapHotelart);
		_querystring = _querystring.concat("&sucheGoogleMapIDLand=", this.param.sucheGoogleMapIDLand);
		_querystring = _querystring.concat("&sucheGoogleMapRegion=", this.param.sucheGoogleMapRegion);
		_querystring = _querystring.concat("&sucheGoogleMapType=", type);
		_querystring = _querystring.concat("&sucheGoogleMapIDParent=", 0);

		updateKarteRecherche(_querystring);
		return _querystring;
		
	},

	setOverlaysText: function(overlayControl, countries) {
	/*	ol = this.overlayControl.getIcons();
map = this.map;		
		console.dir(ol);
				overlayControl= new IconControl(this.map);
console.dir(overlayControl.getIcons());
*/


				 for(var i = 0; i < this.overlayControl.icons_.length; i++) {
  	      
					if( this.overlayControl.icons_ &&  this.overlayControl.icons_[i]) {
						var zIndex = this.overlayControl.icons_[i].style.zIndex;

							if(zIndex < 1) continue;
				
							var overlay = this.overlayControl.icons_[i];
							var childs = overlay.childNodes;
							var len = childs.length;
							while (len--) {
     						if (childs[len].className.indexOf("gmap") >= 0 ) {
         					overlay.removeChild(childs[len]);
    						 }
							}

							var name = document.createElement('div');
	 								name.className = 'gmapZielgebietName';
									name.id = "gmapIconZielgebietName_" + this.zielgebietReference[zIndex].id;
									name.appendChild(document.createTextNode(this.zielgebietReference[zIndex].name));
				    	    this.overlayControl.icons_[i].appendChild(name);

							var angebot = document.createElement('div');
									angebot.className = 'gmapAngebot';
									angebot.id = "gmapIconZielgebietAngebote_" + this.zielgebietReference[zIndex].id;
									if(this.zielgebietReference[zIndex].angebot.indexOf("-1") < 0) {
										angebot.appendChild(document.createTextNode(this.zielgebietReference[zIndex].angebot ));
									}
									this.overlayControl.icons_[i].appendChild(angebot);
				}
     }
		this.hasOverlayText = true;
			

	}, /* End: setOverlaysText*/
	
	fitBounds: function() {
		if(parseInt(cic.$('zoomlevelContainer').innerHTML) == 1)	
			this.map.fitBounds(this.mapBounds); 	
	}
}

/*
 In Order to get access to the Pans and MapCanvasProjection
 create a custom class that extends OverlayView.
*/
function IconControl(map) { 
	this.setMap(map);
}

// Extend OverlayView so we can access MapCanvasProjection.
IconControl.prototype = new google.maps.OverlayView();
IconControl.prototype.onAdd = function() {};
IconControl.prototype.draw = function() {
		this.icons_ = this.getPanes().overlayImage.childNodes;
};
IconControl.prototype.getIcons = function() {
		return  this.getPanes().overlayImage.childNodes;
};
