GRMap = function (config){
	//GrandReality Map variables definition

	this.contId = config.contId;	//id of the map container;
	this.mode = config.mode;		//default mode
	this.paintElement = config.paintElement;
	this.Lat = config.Lat;
	this.Lng = config.Lng;
	this.zoom = config.zoom;
	this.markers = config.markers;
	this.current_object = config.current_object;
	this.overlaysArray = new Array();

	this.isMarker = 0;
	this.isPolygon = 0;
	this.isLine = 0;
	this.isMarkerControl = 0;

	this.listings = new Array();
	this.k = 0;

	this.isEditing = false;

	//object contsructor

	this.map = new YMaps.Map(document.getElementById(this.contId));
	this.map.addControl(new YMaps.TypeControl());
	this.map.addControl(new YMaps.Zoom());

	// A function to create the marker and set up the event window
	this.createMarker = function(obid,lat,lng,name,url,type) {

	 if(obid == this.current_object){
		//showing custom icon to show current object
		var listing = new YMaps.Placemark(new YMaps.GeoPoint(lng,lat),{draggable: false, hasBalloon: false, id : obid});
	 }else{
		 var img = new Image();
		 img.src = filesPath+"css/images/gmapsicons/"+ type +".png";
		 
			if(img.complete != true){
				 //hack
				 img.width = '20';
				 img.height = '20';
			 }
			 
			 var icon = new YMaps.Style();
			 icon.iconStyle = new YMaps.IconStyle();
	
			 icon.iconStyle.href = img.src;
			 icon.iconStyle.size = new YMaps.Point(img.width, img.height);
	
			 var listing = new YMaps.Placemark(new YMaps.GeoPoint(lng,lat),{style: icon, draggable: false, hasBalloon: false, hasHint:true});

			 setTimeout(function(){
			 	$('.YMaps-placemark img').css({'height':'auto','width':'auto'});
			 },100);
	}

	 YMaps.Events.observe(listing,listing.Events.Click, function (evpoly) {
		 window.location = url;
		});

//	  fixMarker(obid);

	 listing.description = name;
	 listing.name = name;
	 this.map.addOverlay(listing);
	 
	 this.overlaysArray.push(listing);


	}

	this.updateMarkers = function (){		
		$('#map_loading').html('&nbsp;&nbsp;&nbsp;&nbsp;<img src="/images/ajax-loader.gif" />&nbsp;Loading');
	  	 var bounds = this.map.getBounds();
	  	 var southWest = bounds.getRightBottom();
	  	 var northEast = bounds.getLeftTop();
	  	 var Long2 = northEast.getX();
	  	 var Long1 = southWest.getX();
	  	 var Lat1 = southWest.getY();
	  	 var Lat2 = northEast.getY();

	  	 var data_send='';
	  	 if(this.k != 0){
	  		 for(z=1; z<=this.k; z++){
	  			 data_send += "exist_data["+ z + "]="+this.listings[z] + "&";
	  		 }
	  	 }

	  	 var update_url = siteUrl + "object/get_objects_radius";

	  	 _this = this;
			
	  	 $.ajax({
	  		  type: "POST",
	  		  dataType: 'json',
	  		  url: update_url,
	  		  data: data_send+"ajax_mode=true&find=1&Longitude1="+Long1+"&Longitude2="+Long2+"&Latitude1="+Lat1+"&Latitude2="+Lat2+"&Zoom="+_this.map.getZoom()+"&current_object="+_this.current_object,
	  		  async: true,
	  		  success: function(data){	  		  	
		  		  if(data.data.objects){

			   		jQuery.each(data.data.objects, function(obid, val) {
			   			if(obid != _this.current_object && val.otype != 'land')
			   			{
			   				_this.k++;
			   				_this.createMarker(obid,val.location.latitude, val.location.longitude, val.html, val.url, val.otype);
			   				_this.listings[_this.k] = obid;
			   			}
					});
		  		  }

	  		 $('#map_loading').html('');
	  		 msgSystem.finishLoading();
	  		 },
	  		 error: function (XMLHttpRequest, textStatus, errorThrown) {
	  			 $('#map_loading').html('');
	  			 msgSystem.message('Произошла ошибка. Пожалуйста, повторите попытку. Если ошибка повторяется, просим Вас обратиться к администратору: admin@vukraine.com.ua.');
	  		 }
	  	});
	}

	if(this.mode == 'view'){
		_this = this;
		
		YMaps.Events.observe(this.map,this.map.Events.BoundsChange, function (mar) {
			if(_this.overlaysArray.length > 0){
		$.each(_this.overlaysArray,function () {
				_this.map.removeOverlay(this);
				});
				
				_this.map.removeOverlay(_this.marker);
				_this.overlaysArray = new Array();
				
				_this.initCurrentMarker(true);
			}
				
			_this.updateMarkers();
		});

	}

	this.initCurrentMarker = function (noCenter){
		
		
		if(this.markers != '')
		{
			
			switch(this.paintElement)
			{
				case 'marker':
				{
					tmpMap = this.map;
					_this = this;
					$.each(this.markers,function () {
						if(_this.mode != 'view') markertmp = new YMaps.Placemark(new YMaps.GeoPoint(this.Lng,this.Lat),{draggable: true, hasBalloon: false});
						else markertmp = new YMaps.Placemark(new YMaps.GeoPoint(this.Lng,this.Lat),{draggable: false, hasBalloon: false});
						tmpMap.addOverlay(markertmp);
						tmpLng = this.Lng;
						tmpLat = this.Lat;
					});
					this.marker = markertmp;
					this.Lng = tmpLng;
					this.Lat = tmpLat;
	
					if(!noCenter) this.map.setCenter(new YMaps.GeoPoint(this.Lng,this.Lat), this.zoom);
					this.isMarker++;
					this.isMarkerControl = 1;
	
					if(this.mode != 'view')
					{
						YMaps.Events.observe(this.marker,this.marker.Events.PositionChange, function (mar) {
							_this.saveValues(mar.getGeoPoint());
						});
					}
					break;
				}
	
				case 'polygon':
				{
					var style = new YMaps.Style("default#greenPoint");
					style.polygonStyle = new YMaps.PolygonStyle();
					style.polygonStyle.fill = 1;
					style.polygonStyle.outline = 1;
					style.polygonStyle.strokeWidth = 3;
					style.polygonStyle.strokeColor = "ff000099";
					style.polygonStyle.fillColor = "ff000044";
					YMaps.Styles.add("polygon#Example", style);
					var style = new YMaps.Style("default#greenPoint");
					style.polygonStyle = new YMaps.PolygonStyle();
					style.polygonStyle.fill = 1;
					style.polygonStyle.outline = 1;
					style.polygonStyle.strokeWidth = 3;
					style.polygonStyle.strokeColor = "00ff0099";
					style.polygonStyle.fillColor = "ff000044";
					YMaps.Styles.add("polygon#Selected", style);
	
					this.polygon = new YMaps.Polygon([], {
					    style: "polygon#Example",
					    hasHint: 0,
					    hasBalloon: 0
					});
	
					ind = 0;
					Lat = 0;
					Lng = 0;
					_this = this;
					marksize = $(this.markers).size();
	
					marksize--;
	
					jQuery.each(this.markers, function(pol_name, pol_val) {
						if(marksize != pol_name)_this.polygon.addPoint(new YMaps.GeoPoint(pol_val.Lng * 1,pol_val.Lat * 1), ind);
						Lat += pol_val.Lat * 1;
						Lng += pol_val.Lng * 1;
						ind++;
					});
					Lat = Lat / ind;
					Lng = Lng / ind;
					ind--;
					if(ind < 3)
					{
						if(this.mode != 'view') this.marker = new YMaps.Placemark(new YMaps.GeoPoint(Lng,Lat),{draggable: true, hasBalloon: false});
						else this.marker = new YMaps.Placemark(new YMaps.GeoPoint(Lng,Lat),{draggable: false, hasBalloon: false});
						this.map.addOverlay(this.marker);
	
						if(this.mode != 'view')
						{
							YMaps.Events.observe(this.marker,this.marker.Events.PositionChange, function (mar) {
								_this.isPolygon=0;
								_this.isMarker = 1;
								_this.saveValues(mar.getGeoPoint());
							});
						}
					}
					else
					{
						this.map.addOverlay(this.polygon);
	
						if(this.mode != 'view')
						{
							YMaps.Events.observe(this.polygon,this.polygon.Events.MouseEnter, function (evpoly) {
								if(!_this.isEditing) evpoly.setOptions({style: "polygon#Selected"});
							});
							YMaps.Events.observe(this.polygon,this.polygon.Events.MouseLeave, function (evpoly) {
								if(!_this.isEditing)evpoly.setOptions({style: "polygon#Example"});
							});
	
							YMaps.Events.observe(this.polygon,this.polygon.Events.PositionChange, function (evpoly) {
								_this.saveValues('');
							});
	
							YMaps.Events.observe(this.polygon,this.polygon.Events.Click, function (evpoly) {
	
								if(!_this.isEditing)
								{
								evpoly.startEditing();
								}
								else
								{
								evpoly.stopEditing();
								}
	
								_this.isEditing = !_this.isEditing;
							});
						}
					}
	
					if(!noCenter) this.map.setCenter(new YMaps.GeoPoint(Lng,Lat), this.zoom);
					this.isPolygon++;
					this.isMarkerControl = 1;
	
					break;
				}
	
				default:
				{
					break;
				}
			}
		}
		else
		{
			if(!noCenter) this.map.setCenter(new YMaps.GeoPoint(this.Lng,this.Lat), this.zoom);
		}
	}
	
	this.initCurrentMarker();

	if(this.mode != 'view') this.map.addControl(new PlaceMarkerTogglerControl(this));
	else this.updateMarkers();

	//GRMap methods definition

	this.placeMarker = function() {
		if (this.isMarker == 0) {
			this.marker = new YMaps.Placemark(new YMaps.GeoPoint(0,0), {draggable: true, hasBalloon: false});
			this.map.addOverlay(this.marker);
			_this = this;

			var movelisten = YMaps.Events.observe(this.map,this.map.Events.MouseMove, function (map, mEvent) {
				if(_this.isMarker == 0) _this.marker.setGeoPoint(mEvent.getGeoPoint());
			});

			var listener_clk = YMaps.Events.observe(this.map,this.map.Events.Click, function (map, mEvent) {
				if(mEvent.getGeoPoint())
				{
					listener_clk.cleanup();
					movelisten.cleanup();

					_this.isMarker++;
					_this.saveValues(mEvent.getGeoPoint());
				}
			});
			var listener_clk2 = YMaps.Events.observe(this.marker,this.marker.Events.Click, function (mEvent) {
				if(mEvent.getGeoPoint())
				{
					listener_clk.cleanup();
					listener_clk2.cleanup();
					movelisten.cleanup();

					_this.isMarker++;
					_this.saveValues(mEvent.getGeoPoint());
				}
			});

		}
	}

	this.saveValues = function(geoPoint) {
		$("#" + this.contId + "_Zoom").val( this.map.getZoom());
		$("#" + this.contId + "_Mode").val(this.mode);

		if (this.isMarker != 0 ) {
			$("#" + this.contId + "_Markers").val('[' + this.point_to_json(geoPoint) + ']');
		}else if (this.isPolygon != 0 ){
			index = 0;
			markers_data = '['
			while (index < this.polygon.getNumPoints()) {
				markers_data += this.point_to_json(this.polygon.getPoint(index)) + ',';
				index++;
			}
			markers_data += this.point_to_json(this.polygon.getPoint(0));
			markers_data += ']'
			$("#" + this.contId + "_Markers").val(markers_data);
		}
	}

	this.point_to_json = function(geoPoint){
		return '{"Lat":' + geoPoint.getLat() + ',"Lng":' + geoPoint.getLng() + '}';

	}

	this.Clear = function() {
		$("#" + this.contId + "_Zoom").val("");
		$("#" + this.contId + "_Mode").val("delete");
		$("#" + this.contId + "_Markers").val("");



		if (this.isMarker == 1 || (this.marker != '' && this.isPolygon == 0) || ind < 3) {
			this.map.removeOverlay(this.marker);
			this.isMarker = 0;
		}
		if (this.isPolygon == 1) {

			$('#' + this.contId).css('cursor','');
			$('#' + this.contId).addClass('YMaps-cursor-grab');

			this.polygon.stopEditing();
			this.map.removeOverlay(this.polygon);
			this.isPolygon = 0;
		}

	}

	this.startShape = function () {
		if (this.isPolygon == 0){
			$('#' + this.contId).css('cursor','crosshair');

			_this = this;

			var style = new YMaps.Style("default#greenPoint");
			style.polygonStyle = new YMaps.PolygonStyle();
			style.polygonStyle.fill = 1;
			style.polygonStyle.outline = 1;
			style.polygonStyle.strokeWidth = 3;
			style.polygonStyle.strokeColor = "ff000099";
			style.polygonStyle.fillColor = "ff000044";
			YMaps.Styles.add("polygon#Example", style);
			var style = new YMaps.Style("default#greenPoint");
			style.polygonStyle = new YMaps.PolygonStyle();
			style.polygonStyle.fill = 1;
			style.polygonStyle.outline = 1;
			style.polygonStyle.strokeWidth = 3;
			style.polygonStyle.strokeColor = "00ff0099";
			style.polygonStyle.fillColor = "ff000044";
			YMaps.Styles.add("polygon#Selected", style);

			_this.polygon = new YMaps.Polygon([], {
			    style: "polygon#Example",
			    hasHint: 0,
			    hasBalloon: 0
			});

			_this.startDrawing(_this.polygon);

			_this.isPolygon++;


		} else {
			polygon.show();
		}
	}

	this.startDrawing = function(poly) {
		this.map.addOverlay(poly);
		poly.startEditing();
		poly.setEditingOptions({drawing: true, maxPoints: 4})

		$('#' + this.contId).removeClass('YMaps-cursor-default');

		_this = this;

		YMaps.Events.observe(poly,poly.Events.StopDrawing, function (evpoly) {
			$('#' + _this.contId).css('cursor','');
			$('#' + _this.contId).addClass('YMaps-cursor-grab');

			_this.saveValues('');
			evpoly.setEditingOptions({drawing: false});
			evpoly.stopEditing();

			YMaps.Events.observe(poly,poly.Events.MouseEnter, function (evpoly) {
				if(!_this.isEditing) evpoly.setOptions({style: "polygon#Selected"});
			});
			YMaps.Events.observe(poly,poly.Events.MouseLeave, function (evpoly) {
				if(!_this.isEditing)evpoly.setOptions({style: "polygon#Example"});
			});

			YMaps.Events.observe(poly,poly.Events.Click, function (evpoly) {

				if(!_this.isEditing)
				{
				evpoly.startEditing();
				}
				else
				{
				evpoly.stopEditing();
				}

				_this.isEditing = !_this.isEditing;
			});


		});

		YMaps.Events.observe(poly,poly.Events.PositionChange, function (evpoly) {
			_this.saveValues('');
		});
	}


};

//defining custom controls

function PlaceMarkerTogglerControl (obj) {
    this.element = document.createElement("DIV");
    this.element.style.position = 'absolute';
    this.element.style.zIndex = '1000';
    this.grobj = obj;
}

PlaceMarkerTogglerControl.prototype = {
    onAddToMap: function (map, position) {
        this.map = map;
        this.position = position || new YMaps.ControlPosition(YMaps.ControlPosition.TOP_LEFT, new YMaps.Size(5, 5));
        this._init();
    },

    onRemoveFromMap: function () {
        if (this.element.parentNode) {
            this.map.getContainer().removeChild(this.element);
        }
        this.map = null;
    },

   _init: function (map) {
		var MarkerDiv = document.createElement("input");
		MarkerDiv.type = 'button';
		MarkerDiv.className = 'button';
		if (this.grobj.isMarkerControl == 0) {
			MarkerDiv.value = 'Отметить на карте';
		} else {
			MarkerDiv.value = 'Убрать ометку с карты';
		}
		this.element.appendChild(MarkerDiv);
        _this_ctrl = this;

        MarkerDiv.onclick  = function () {
        	if ( _this_ctrl.grobj.isMarkerControl == 0) {
        		_this_ctrl.grobj.isMarkerControl = 1;
				MarkerDiv.value = 'Убрать ометку с карты';

				if (_this_ctrl.grobj.paintElement == "marker") {
					_this_ctrl.grobj.placeMarker();
				} else if (_this_ctrl.grobj.paintElement == "polygon") {
					_this_ctrl.grobj.startShape();

				}

			} else {
				_this_ctrl.grobj.isMarkerControl = 0;
				MarkerDiv.value = 'Отметить на карте';
				_this_ctrl.grobj.Clear();
			}
        };

        this.position.apply(this.element);
        this.map.getContainer().appendChild(this.element);
    }
}