function GoogleMaps() {	
	this.map = null;
	this.scale = 0;
	this.markerIcon = null;
	this.clusterIcon = null;
	this.marker_array = new Array();
	this.culture = 'pl';
	this.host;
	this.marker_counter = 0;
	
	this.addEvent = function(_object,event,_function) {
		checkEventParameters(_object,event);
		GEvent.addListener(_object, event, function() {
  			eval(_function);
		});
	}
		
	var checkEventParameters = function(_object,event) {
		if(Validator.isObject(_object) == false)
			throw new Error("[AddEvent]: Parameter is not an object.");
		if(Validator.isUndefined(event) == true)
			throw new Error("[AddEvent]: Parameter is not an event.");
	}

} 

GoogleMaps.prototype.setHost = function(host) {
	this.host = host;
}

/**
 * Inicjalizacja mapy
 * @argument container : Id elementu DIV
 * $argument googlemenu : Boolean 
 * @return void
 */
GoogleMaps.prototype.initialize = function(container,googlemenu) {   
	if(!GBrowserIsCompatible())
		throw new Error("Browser is incompatible.");
	if(document.getElementById(container) == null)
		throw new Error("There is no such element as: "+container);
	 
	this.map = new GMap2(document.getElementById(container));
	this.map.disableDoubleClickZoom();
	
	if(!Validator.isUndefined(googlemenu)) {
		if(googlemenu == "large") {
			this.map.addControl(new GLargeMapControl());
		} else if(googlemenu == "small") {
			this.map.addControl(new GSmallMapControl());
		}
			this.map.addControl(new GMapTypeControl());
	}
}

/**
 * Ustawianie nowej pozycji
 * @argument point : Punkt GLatLng
 * @argument scale : Skala mapy
 * @return void
*/
GoogleMaps.prototype.setPosition = function(point,scale) {
	if(!Validator.isGoogleCoordinates(point))
		point = new GLatLng('51.919438','19.145136');
	scale = (!Validator.hasValue(scale))?this.scale:scale;	
	this.map.setCenter(point, scale);
}

GoogleMaps.prototype.getMap = function() {
	return this.map;
}

GoogleMaps.prototype.getActualZoom = function() {
	return this.map.getZoom();
}

/**
 * Ustawienie typu mapy
 * @argument num_type : numer w tablicy types
 */
GoogleMaps.prototype.setMapType = function(num_type) {
	var types = new Array(G_HYBRID_MAP,
					  G_SATELLITE_MAP,
					  G_NORMAL_MAP,
					  G_DEFAULT_MAP_TYPES,
					  G_MOON_ELEVATION_MAP,
					  G_MOON_VISIBLE_MAP,
					  G_MARS_ELEVATION_MAP,
					  G_PHYSICAL_MAP,
					  G_MARS_VISIBLE_MAP,
					  G_MARS_INFRARED_MAP,
					  G_SKY_VISIBLE_MAP
					  //G_SATELLITE_3D_MAP
					 );
						  
	if(num_type > types.length)
		num_type = 0;
	this.map.setMapType(types[num_type]);
}

/**
 * Pobranie długości
 * @return tablica wartości
 */
GoogleMaps.prototype.getBoundsSpan = function() {
	var bounds = this.map.getBounds();
	var spans = new Array();
	spans["southWest"] = bounds.getSouthWest();
	spans["northEast"] = bounds.getNorthEast();
	spans["lngSpan"] = spans["northEast"].lng() - spans["southWest"].lng();
	spans["latSpan"] = spans["northEast"].lat() - spans["southWest"].lat();
	return spans;
}

/**
 * Tworzenie punktu
 * @argument point : Punkt GLatLng
*/
GoogleMaps.prototype.createMarker = function(point) {
	this.checkCoordinates(point);
	var marker = new GMarker( point, this.markerIcon );
	this.map.addOverlay(marker);
	return marker;
}

/*
 * Usunięcie markera
 * @argument marker
 */	
GoogleMaps.prototype.removeMarker = function(marker) {
	if(!(marker instanceof GMarker))
		throw new Error("Marker is not valid.");
	this.map.removeOverlay(marker);
}

/*
 * Utworzenie punktu z oknem informacyjnym
 * @argument point : punkt geograficzny
 * @argument event : na jakie zdarzenie reaguje
 * @argument html : treść wiadomości w oknie
 * @return marker
 */
GoogleMaps.prototype.createMarkerWithInfoWindow = function(point,event,html) {
	this.checkCoordinates(point);
	if(Validator.isUndefined(event) == true)
		event = "click";
		
	var marker = new GMarker(point, this.markerIcon);
	var that = this;
   	GEvent.addListener(marker, event, function() {
		marker.openExtInfoWindow(
              that.map,
              "love_info_window",
              "<p>"+html+"</p>",
              {beakOffset: 2}
            ); 
   	});
   	this.map.addOverlay(marker);
   	return marker;
}

GoogleMaps.prototype.EWwindowOnEventAjax = function(obj,event,url) {
	var that = this;
	GEvent.addListener(obj, event, function() {
    	obj.openExtInfoWindow(
        	that.map,
        	"love_info_window",
            "<p><img src='/images/loading-white.gif' /></p>",
            {
            	ajaxUrl: url, 
             	beakOffset: 2
            }
         );
	});
}

/**
 * Przygotowanie punktu GLatLng na podstawie wartości geograficznych
 * @return punkt GlatLng 
 */
GoogleMaps.prototype.setCoordinates = function(lng,lat) {
	return new GLatLng(lng,lat);
}

/**
 * Ustawienie nowej grafiki na marker
 * @argument icon : url do nowej ikony
*/
GoogleMaps.prototype.setMarkerIcon = function(url) {
	if(Validator.isUndefined(url) || url == null) {
		this.markerIcon = null;
		return;
	}
		
	//var newIcon = new GIcon(G_DEFAULT_ICON);
	var newIcon = new GIcon();
	newIcon.image = url;
	//newIcon.iconSize = new GSize(20, 34);
	newIcon.iconSize = new GSize(23, 25);
	newIcon.shadowSize = new GSize(22, 20);
	newIcon.iconAnchor = new GPoint(12, 25);
	newIcon.infoWindowAnchor = new GPoint(12, 0);
    markerOptions = { icon:newIcon, zIndexProcess:orderOfCreation };
	this.markerIcon = markerOptions;
}

GoogleMaps.prototype.checkCoordinates = function(point) {
	if(!Validator.isGoogleCoordinates(point))
		throw new Error("Wrong coordinates!");
}

GoogleMaps.prototype.setClusterIcon = function(icon_name) {
	var iconCluster = new GIcon();
	if(Validator.isUndefined(icon_name)){
		iconCluster.image = this.host+"/images/icon-cluster.png";
	}
	else{
		iconCluster.image = this.host+"/images/"+icon_name;
	}
	iconCluster.shadow = this.host+"/images/icon-cluster-shadow.png";
	iconCluster.iconSize = new GSize(30, 29);
	iconCluster.shadowSize = new GSize(22, 20);
	iconCluster.iconAnchor = new GPoint(15, 29);
	iconCluster.infoWindowAnchor = new GPoint(15, 0);
	iconCluster.infoShadowAnchor = new GPoint(26, 13);
	this.clusterIcon = iconCluster;
}

/**
 * MAPS LOVE
 */
MapsLove.prototype = new GoogleMaps();
MapsLove.prototype.constructor=MapsLove;

function MapsLove(culture) { 
	this.profileMainPointListener = null;
	if(!Validator.isUndefined(culture))
		this.culture = culture;
}

MapsLove.prototype.profileMainPoint = function(is_heart,point) {
	var choosen_marker = null;
	
	if(!Validator.isUndefined(point))
	{
		if(Validator.isUndefined(is_heart) || is_heart == false)
			this.setMarkerIcon(this.host+'/images/icon-myplace.png');
		else
			this.setMarkerIcon(this.host+'/images/icon-heart.png');
		this.map.addOverlay((choosen_marker = new GMarker(point, this.markerIcon)));
	}
	
	var that=this;

	var profileMainPointListner = GEvent.bind(this.map, "click", this, 
		function(marker,point) {
		      if (point) 
		      {
		      	if(choosen_marker != null) {
		      		this.map.removeOverlay(choosen_marker);
					$('mapdescription').hide();
					$('googlepoint').value='0';
					$('googlescale').value='10';
		      	}
		      	if(Validator.isUndefined(is_heart) || is_heart == false)
			      	this.setMarkerIcon(this.host+'/images/icon-myplace.png');
			    else
			    	this.setMarkerIcon(this.host+'/images/icon-heart.png');
		        this.map.addOverlay((choosen_marker = new GMarker(point, this.markerIcon)));
		        if($('jointopoint'))
			        $('jointopoint').value='0';
			    if($('pointname'))
			        $('pointname').value='';
		        $('mapdescription').show();
		        $('googlepoint').value=point;
		        $('googlescale').value=this.map.getZoom();
		      }
			else if(marker) {
				if(choosen_marker!=null) {
					this.map.removeOverlay(choosen_marker);
					$('mapdescription').hide();
					$('googlepoint').value='0';
					$('googlescale').value='10';
				}
			}
		});
}

    

MapsLove.prototype.automateZoomIn = function(maxzoom) {
	var map = this.map;
	GEvent.addListener(this.map, "click", function(marker, point) {
		if(!Validator.isUndefined(maxzoom))
		{
			if(maxzoom > map.getZoom())
				map.zoomIn();
		}
		else
	  		map.zoomIn();
	 });
}

function orderOfCreation(marker,b) {
		return 1;
	}
function inverseOrder(marker,b) {
return -GOverlay.getZIndex(marker.getPoint().lat());	
}	

MapsLove.prototype.setTargetIcon = function() {
	
	var newIcon = new GIcon(G_DEFAULT_ICON);
	newIcon.image = this.host+'/images/icon-target.png';
	newIcon.iconSize = new GSize(130, 130);
	newIcon.shadowSize = new GSize(1, 1);
	newIcon.iconAnchor = new GPoint(65,65);
	newIcon.infoWindowAnchor = new GPoint(65, 1);
    markerOptions = { icon:newIcon };
	this.markerIcon = markerOptions;
}

MapsLove.prototype.setTileLayersToMap = function(detailLayer) {
	detailMapLayers = G_NORMAL_MAP.getTileLayers();
    detailMapLayers.push(detailLayer);
    detailMapLayers = G_SATELLITE_MAP.getTileLayers();
    detailMapLayers.push(detailLayer);
    detailMapLayers = G_HYBRID_MAP.getTileLayers();
    detailMapLayers.push(detailLayer);
}

MapsLove.prototype.removeListener = function() {
	if(this.profileMainPointListener != null)
		GEvent.removeListener(this.profileMainPointListener);
}

MapsLove.prototype.setZoomEvent = function(field) {
	var map = this.map;
	GEvent.addListener(this.map, "zoomend", function() {
     		if(!Validator.isUndefined(field))
     			$(field).value = map.getZoom();
	});	
}

MapsLove.prototype.setZoomOutInformation = function() {
	if(this.getActualZoom() < 7) {
		this.map.clearOverlays();
		$('mapInfo').show();
		return true; 
	} else {
		$('mapInfo').hide();
		return false;
	}
}

MapsLove.prototype.updatePlacesMarkersWithClusters = function(my_place_id,addnewpoint,callback_type) {
	if(this.setZoomOutInformation())
		return; 
		
	var bounds = this.getBoundsSpan();
	
	var request = GXmlHttp.create();
	request.open('GET', this.host+'/Ajax/Places/Clusters/'+bounds["northEast"].toUrlValue()
				  +'/'+bounds["southWest"].toUrlValue()+'/list.html', true);
	var that = this;
	
	//this.map.closeExtInfoWindow();  
	
	request.onreadystatechange = function() {
		if (request.readyState == 4) {
			if(that.scale != that.getActualZoom()) {
				if(that.scale != 0) {
					that.map.closeExtInfoWindow(); 
					that.map.clearOverlays();
				}
				that.scale = that.getActualZoom(); 
			}
			var counter=0;
			var points;

			if(that.culture == 'pl')
				var info = "W tym miejscu jest więcej punktów.<br>Przybliż mapę aby uzyskać lepszy wynik.";
			else
				var info = "Zoom the map to see more points in the area.";
				
			eval(request.responseText);
			//that.map.clearOverlays();
			that.marker_counter=0;

			for (var i = 0; i < that.marker_array.length; i++) {
		        that.map.removeOverlay(that.marker_array[i]);
		    }
			that.marker_array = new Array();
			
			for (i in points) 
			{
				var point = new GLatLng(points[i].lat,points[i].lng);
				if(points[i].type=='c') 
				{
					that.markerIcon = that.clusterIcon;
					var marker = that.createMarkerWithInfoWindow(point,"click",info);
				} 
				else 
				{
					if(addnewpoint)
						var url = that.host+'/Ajax/Place/Info/'+points[i].id+'/join.html';
					else
						var url = that.host+'/Ajax/Place/Info/'+points[i].id+'/get.html';
					
					if(points[i].id == my_place_id)
						that.setTargetIcon();//that.setMarkerIcon(that.host+'/images/icon-myplace.png');
					else
						that.setMarkerIcon(that.host+'/images/icon-place.png');
					
					var marker = that.createMarker(point);		
					
					if(Validator.isUndefined(callback_type))
						that.EWwindowOnEventAjax(marker,"click",url);
					else if(callback_type == 'list-users')
						that.PlaceWindowAjaxCallback(marker,"click",url,points[i].id);
				}
				that.marker_array[counter++] = marker;
				
			}
		}
	};
	request.send(null);
}

MapsLove.prototype.PlaceWindowAjaxCallback = function(obj,event,url,id_localization) {
	var that = this;
	GEvent.addListener(obj, event, function() {
    	obj.openExtInfoWindow(
        	that.map,
        	"love_info_window",
            "<p><img src='/images/loading-white.gif' /></p>",
            {
            	ajaxUrl: url, 
            	callback: that.ajaxGetUsersListsInPlace(id_localization),
             	beakOffset: 2
            }
         );
	});
}

MapsLove.prototype.ajaxGetUsersListsInPlace = function(id_localization) {
	var browser=navigator.appName;

	new Ajax.Updater(
		'list-users',
		'/'+this.culture+'/Lists/Users/'+id_localization+'/0/1/P/whohasit.html', 
		{
			asynchronous:true, 
			evalScripts:false,
		    onLoading: function() {
		    	if(browser != "Microsoft Internet Explorer") {
			    	$('list-users').hide(); 
			    	$('loaderwhohasit').show();
		    	}
		    },
		 	onComplete: function(request, json) {
		 		$('list-users').show()
		 		$('loaderwhohasit').hide();
		 	}
		}
	);
}

MapsLove.prototype.updateMomentsMarkersWithClusters = function() {
	if(this.setZoomOutInformation())
		return;
		
	var bounds = this.getBoundsSpan();
	
	var request = GXmlHttp.create();
	request.open('GET', this.host+'/Ajax/Moments/Clusters/'+bounds["northEast"].toUrlValue()
				  +'/'+bounds["southWest"].toUrlValue()+'/'+this.getActualZoom()+'/list.html', true);
	var that = this;
	
	request.onreadystatechange = function() {
		if (request.readyState == 4) {
			if(that.scale != that.getActualZoom()) {
				if(that.scale != 0) {
					that.map.closeExtInfoWindow(); 
					that.map.clearOverlays();
				}
				that.scale = that.getActualZoom(); 
			}
	
			var counter=0;
			var points;

			if(that.culture == 'pl')
				var info = "W tym miejscu jest więcej punktów.<br>Przybliż mapę aby uzyskać lepszy wynik.";
			else
				var info = "Zoom the map to see more points in the area.";
				
			eval(request.responseText);
			//that.map.clearOverlays();
			that.marker_counter=0;

			for (var i = 0; i < that.marker_array.length; i++) {
		        that.map.removeOverlay(that.marker_array[i]);
		    }
			that.marker_array = new Array();
			
			for (i in points) 
			{
				var point = new GLatLng(points[i].lat,points[i].lng);
				if(points[i].type=='c') 
				{
					that.setClusterIcon();
					that.markerIcon = that.clusterIcon;
					var marker = that.createMarkerWithInfoWindow(point,"click",info);
				} 
				else 
				{
					var url = that.host+'/Ajax/Moment/Info/'+points[i].id+'/get.html';
					if(points[i].num == 1) {
						/*if(points[i].icon == '1')
							that.setMarkerIcon(that.host+'/images/icon-man.png');
						else if(points[i].icon == '2')
							that.setMarkerIcon(that.host+'/images/icon-woman.png');
						else if(points[i].icon == '3')
							that.setMarkerIcon(that.host+'/images/icon-heart.png');*/
						that.setMarkerIcon(that.host+'/'+points[i].icon);	
					} else {
						that.setClusterIcon('icon-clust-moments.png');
						that.markerIcon = that.clusterIcon;
					}
					var marker = that.createMarker(point);		
					that.EWwindowOnEventAjax(marker,"click",url);
					
				}
				that.marker_array[counter++] = marker;
			}
		}
	};
	request.send(null);
}

MapsLove.prototype.setCompareMoments = function(points) 
{
	for (var i=0;i<points.length;i++) 
	{
		var point = new GLatLng(points[i]["lat"],points[i]["lng"]);
		var sum = points[i]["sum"]*1;
		
		if(sum >= 0 && sum < 5)
			this.setMarkerIcon(this.host+'/images/icon-moment0.png');
		else if(sum >= 5 && sum <20)
			this.setMarkerIcon(this.host+'/images/icon-moment20.png');
		else if(sum >= 20 && sum <50)
			this.setMarkerIcon(this.host+'/images/icon-moment50.png');	
		else if(sum >= 50 && sum <70)
			this.setMarkerIcon(this.host+'/images/icon-moment70.png');
		else if(sum >= 70)
			this.setMarkerIcon(this.host+'/images/icon-moment100.png');
		this.createMarkerWithInfoWindow(point,"click",points[i]["msg"]);
	}
}

/**
 * VALIDATOR
 */

var Validator = {
	isObject: function(_object) {
		if(typeof(_object) != "object")
			return false;
		return true;
	},
	
	isUndefined: function(value) {
		if(typeof(value) == "undefined")
			return true;
		return false;
	},
	
	hasValue: function(element) {
		if(Validator.isUndefined(element) == true || element == null)
			return false;
		return true;
	},
	
	isGoogleCoordinates: function(point) {
		if(!(point instanceof GLatLng))
			return false;
		return true;
	},
	
	showObjectProperties: function(_object) {
		for(x in _object)
			alert(x+":"+_object[x]);
	}
}

var Browser = {
	x: 0,
	y: 0,
	
	getXYCoordinates: function() {
		var IE = document.all?true:false;
		if (!IE) 
			document.captureEvents(Event.MOUSEMOVE);
		
		var that=this;
		document.onmousemove = function(e) {
			if (IE) {
		    	that.x = event.clientX;
    			that.y = event.clientY;
  			} else {
 		    	that.x = e.pageX;
    			that.y = e.pageY;
  			}

  	  		if (that.x < 0)
		  		that.x = 0;
		  	if (that.y < 0)
		  		that.y = 0;  
		}
	},
	
	getX: function() {
		return this.x;
	},
	
	getY: function() {
		return this.y;
	}
}
