﻿var Class = {
  create: function() {
    return function() {
      this.initialize.apply(this, arguments);
    }
  }
}

var PlaceSelector = Class.create();

PlaceSelector.prototype = 
{
	initialize: function(mapContainer, placeSelectorContainer, options)
	{
		Event.observe($$("body")[0], "unload", GUnload);
		
		this.mapTypeContainer = options.mapTypeContainer;
		this.mapZoomContainer = options.mapZoomContainer;
		
		this.mapWidth = (options.width != undefined) ? options.width : 446;
		this.mapHeight = (options.height != undefined) ? options.height : 300;
		
		this.map = new GMap2($(mapContainer), { size: new GSize(this.mapWidth, 300) } );
		this.map.addControl(new GLargeMapControl());
		this.map.addControl(new GMapTypeControl());
		
		this.markerInitailized = false;
		this.changedHandler = options.pointChangedHandler;
		this.errorHandler = options.errorHandler;
		
		this.selectorElement = $(placeSelectorContainer);
		this.selectorLeftOffset = this.selectorElement.style.left.replace("px", "");
		this.selectorTopOffset = this.selectorElement.style.top.replace("px", "");
		
		this.place_selector = new GDraggableObject($(placeSelectorContainer), 
			{ 
				delayDrag:true, 
				left:this.selectorLeftOffset, 
				top:this.selectorTopOffset
			} );
			
		this.place_selector.moveTo(new GPoint(this.selectorLeftOffset, this.selectorTopOffset));
		
		GEvent.addListener(this.place_selector, "dragstart", this.reset.bindAsEventListener(this));
		GEvent.addListener(this.place_selector, "dragend", this.selectorDragged.bindAsEventListener(this));
		GEvent.addListener(this.map, "load", this.mapLoaded.bindAsEventListener(this));
		GEvent.addListener(this.map, "dragend", this.mapDragEnd.bindAsEventListener(this));
		
		if(options.mapLoadedHandler)
		{
			GEvent.addListener(this.map, "load", options.mapLoadedHandler);
		}
		
		this.geocoderCache = new GGeocodeCache();
		this.geocoder = new GClientGeocoder(this.geocoderCache);
		this.geocoderCompleteHandler = this.geocoderComplete.bindAsEventListener(this);
		
		//загрузка состояния карты
		if(options.centerLat != "" && options.centerLng != "")
		{
			var zoom = ($F(this.mapZoomContainer) != "") ? parseInt($F(this.mapZoomContainer)) : 14;
			
			this.map.setCenter(new GLatLng(options.centerLat, options.centerLng), zoom);
			this.initializeMarker();
			
			if(options.lat != "" && options.lng != "")
			{
				this.marker.setPoint(new GLatLng(options.lat, options.lng));
				this.marker.show();
				this.selectorElement.addClassName("inactive");
			}
		}
		
		switch($F(this.mapTypeContainer))
		{
			case "G_NORMAL_MAP":
				this.map.setMapType(G_NORMAL_MAP);
				break;
			case "G_SATELLITE_MAP":
				this.map.setMapType(G_SATELLITE_MAP);
				break;				
			case "G_HYBRID_MAP":
				this.map.setMapType(G_HYBRID_MAP);
				break;
		}
		
		GEvent.addListener(this.map, "maptypechanged", this.mapTypeChanged.bindAsEventListener(this));
		GEvent.addListener(this.map, "zoomend", this.mapZoomEnd.bindAsEventListener(this));
	},
	mapDragEnd: function()
	{
		var center = this.map.getCenter();
		
		if(this.marker)
		{
			if(!this.marker.isHidden())
			{
				var point = this.marker.getPoint();
				this.changedHandler(center.lat(), center.lng(), point.y, point.x);
				return;
			}
		}
		
		this.changedHandler(center.lat(), center.lng(), "", "");
	},
	reset: function()
	{
		this.selectorElement.removeClassName("inactive");
		if(this.marker)
		{
			this.marker.hide();
		}
		this.changedHandler("", "", "", "");
	},
	mapTypeChanged: function(eventArgs)
	{
		switch(this.map.getCurrentMapType())
		{
			case G_NORMAL_MAP:
				this.mapTypeContainer.value = "G_NORMAL_MAP";
				break;
			case G_SATELLITE_MAP:
				this.mapTypeContainer.value = "G_SATELLITE_MAP";
				break;
			case G_HYBRID_MAP:
				this.mapTypeContainer.value = "G_HYBRID_MAP";
				break;
		}
	},
	mapZoomEnd: function(oldLevel, newLevel)
	{
		this.mapZoomContainer.value = this.map.getZoom();
	},
	selectorDragged: function(selector)
	{
			selector = Event.extend(selector);
			
			Position.prepare();
			
			if( !Position.within(
				this.map.getContainer(), selector.pointerX(), selector.pointerY()) )
			{
				this.place_selector.moveTo(new GPoint(this.selectorLeftOffset, this.selectorTopOffset));
				this.marker.hide();
				
				this.selectorElement.removeClassName("inactive");
				this.changedHandler("", "", "", "");
				return ;
			}
			
			var offset = $(this.map.getContainer()).cumulativeOffset();
			var leftOffset = selector.pointerX() - offset[0];
			var topOffset = selector.pointerY() - offset[1] + 12;
			var point = this.map.fromContainerPixelToLatLng(new GPoint(leftOffset,topOffset));
			
			this.marker.setPoint(point);
			this.marker.show();
			
			this.place_selector.moveTo(new GPoint(this.selectorLeftOffset, this.selectorTopOffset));
			this.selectorElement.addClassName("inactive");
			
			var center = this.map.getCenter();
			this.changedHandler(center.lat(), center.lng(), point.y, point.x);
	},
	markerDrugged: function()
	{
		var center = this.map.getCenter();
		this.changedHandler(center.lat(), center.lng(), this.marker.getPoint().y, this.marker.getPoint().x);
	},
	initializeMarker: function()
	{
		if(!this.markerInitailized)
		{
			//создаем маркер для выделения места
			this.markerIcon = new GIcon();
			this.markerIcon.image = rootUrl + "/images/map_arrow.png";
			this.markerIcon.iconSize = new GSize(51, 38);
			this.markerIcon.iconAnchor = new GPoint(27, 36);
			
			this.marker = new GMarker(this.map.getCenter(), 
				{
					draggable: true,
					icon: this.markerIcon
				} );
			
			GEvent.addListener(this.marker, "dragend", this.markerDrugged.bindAsEventListener(this));
			
			this.map.addOverlay(this.marker);
			this.marker.hide();
			this.markerInitailized = true;
		}
	},
	mapLoaded: function()
	{
		this.initializeMarker();
	},
	setLocation: function(address, zoom)
	{
		this._zoom = zoom;
		this.geocoder.getLatLng(address, this.geocoderCompleteHandler);
	},
	geocoderComplete: function(point)
	{
		if(point != null)
		{
			this.map.setCenter(point, this._zoom);
			this.changedHandler(point.lat(), point.lng(), "", "");
		}
		else
		{
			if(this.errorHandler)
			{
				//set center point to Moscow and chenging zoom	level
				var p = new GLatLng(55.753588, 37.626114);
				this.map.setCenter(p, 1);
				this.changedHandler(p.lat(), p.lng(), "", "");
				this.errorHandler("GEOCODER_ERROR");
			}
		}
	}
};

