# Source: open-layers/ol-map.js

    /**

     * @namespace WPGMZA

     * @module OLMap

     * @requires WPGMZA.Map

     * @pro-requires WPGMZA.ProMap

     */

    (function($) {

    	var Parent;

    	WPGMZA.OLMap = function(element, options)

    	{

    		var self = this;

    		Parent.call(this, element);

    		this.setOptions(options);

    		var viewOptions = this.settings.toOLViewOptions();

    		$(this.element).html("");

    		this.olMap = new ol.Map({

    			target: $(element)[0],

    			layers: [

    				new ol.layer.Tile({

    					source: new ol.source.OSM()

    				})

    			],

    			view: new ol.View(viewOptions)

    		});

    		// TODO: Re-implement using correct setting names

    		// Interactions

    		this.olMap.getInteractions().forEach(function(interaction) {

    			// NB: The true and false values are flipped because these settings represent the "disabled" state when true

    			if(interaction instanceof ol.interaction.DragPan)

    				interaction.setActive( (this.settings.map_draggable ? false : true) );

    			else if(interaction instanceof ol.interaction.DoubleClickZoom)

    				interaction.setActive( (this.settings.map_clickzoom ? false : true) );

    			else if(interaction instanceof ol.interaction.MouseWheelZoom)

    				interaction.setActive( (this.settings.map_scroll ? false : true) );

    		}, this);

    		// Controls

    		this.olMap.getControls().forEach(function(control) {

    			// NB: The true and false values are flipped because these settings represent the "disabled" state when true

    			if(control instanceof ol.control.Zoom && this.settings.map_zoom)

    				this.olMap.removeControl(control);

    		}, this);

    		if(!this.settings.map_full_screen_control)

    			this.olMap.addControl(new ol.control.FullScreen());

    		// Marker layer

    		this.markerLayer = new ol.layer.Vector({

    			source: new ol.source.Vector({

    				features: []

    			})

    		});

    		this.olMap.addLayer(this.markerLayer);

    		// Listen for end of pan so we can wrap longitude if needs be

    		this.olMap.on("moveend", function(event) {

    			self.wrapLongitude();

    			self.dispatchEvent("dragend");

    			self.onIdle();

    		});

    		// Listen for zoom

    		this.olMap.getView().on("change:resolution", function(event) {

    			self.dispatchEvent("zoom_changed");

    			self.dispatchEvent("zoomchanged");

    			self.onIdle();

    			$(self.element).trigger("zoomchanged.wpgmza");

    		});

    		// Listen for bounds changing

    		this.olMap.getView().on("change", function() {

    			// Wrap longitude

    			self.onBoundsChanged();

    		});

    		self.onBoundsChanged();

    		// Store locator center

    		var marker;

    		if(this.storeLocator && (marker = this.storeLocator.centerPointMarker))

    		{

    			this.olMap.addOverlay(marker.overlay);

    			marker.setVisible(false);

    		}

    		// Cycling layer

    		console.log(this.settings);

    		// Right click listener

    		$(this.element).on("click contextmenu", function(event) {

    			var isRight;

    			event = event || window.event;

    			if("which" in event)

    				isRight = event.which == 3;

    			else if("button" in event)

    				isRight = event.button == 2;

    			if(!isRight)

    				return;

    			return self.onRightClick(event);

    		});

    		// Dispatch event

    		if(!WPGMZA.isProVersion())

    		{

    			this.dispatchEvent("created");

    			WPGMZA.events.dispatchEvent({type: "mapcreated", map: this});

    		}

    	}

    	if(WPGMZA.isProVersion())

    		Parent = WPGMZA.ProMap;

    	else

    		Parent = WPGMZA.Map;

    	WPGMZA.OLMap.prototype = Object.create(Parent.prototype);

    	WPGMZA.OLMap.prototype.constructor = WPGMZA.OLMap;

    	WPGMZA.OLMap.prototype.wrapLongitude = function()

    	{

    		var center = this.getCenter();

    		if(center.lng >= -180 && center.lng <= 180)

    			return;

    		center.lng = center.lng - 360 * Math.floor(center.lng / 360);

    		if(center.lng > 180)

    			center.lng -= 360;

    		this.setCenter(center);

    	}

    	WPGMZA.OLMap.prototype.getCenter = function()

    	{

    		var lonLat = ol.proj.toLonLat(

    			this.olMap.getView().getCenter()

    		);

    		return {

    			lat: lonLat[1],

    			lng: lonLat[0]

    		};

    	}

    	WPGMZA.OLMap.prototype.setCenter = function(latLng)

    	{

    		var view = this.olMap.getView();

    		WPGMZA.Map.prototype.setCenter.call(this, latLng);

    		view.setCenter(ol.proj.fromLonLat([

    			latLng.lng,

    			latLng.lat

    		]));

    		this.wrapLongitude();

    		this.onBoundsChanged();

    	}

    	WPGMZA.OLMap.prototype.getBounds = function()

    	{

    		var bounds = this.olMap.getView().calculateExtent(this.olMap.getSize());

    		var topLeft = ol.proj.toLonLat([bounds[0], bounds[1]]);

    		var bottomRight = ol.proj.toLonLat([bounds[2], bounds[3]]);

    		return {

    			topLeft: {

    				lat: topLeft[1],

    				lng: topLeft[0]

    			},

    			bottomRight: {

    				lat: bottomRight[1],

    				lng: bottomRight[0]

    			}

    		};

    	}

    	/**

    	 * Fit to given boundaries

    	 * @return void

    	 */

    	WPGMZA.OLMap.prototype.fitBounds = function(southWest, northEast)

    	{

    		this.olMap.getView().fitExtent(

    			[southWest.lng, southWest.lat, northEast.lng, northEast.lat],

    			this.olMap.getSize()

    		);

    	}

    	WPGMZA.OLMap.prototype.panTo = function(latLng)

    	{

    		var view = this.olMap.getView();

    		view.animate({

    			center: ol.proj.fromLonLat([

    				parseFloat(latLng.lng),

    				parseFloat(latLng.lat),

    			]),

    			duration: 500

    		});

    	}

    	WPGMZA.OLMap.prototype.getZoom = function()

    	{

    		return Math.round( this.olMap.getView().getZoom() ) + 1;

    	}

    	WPGMZA.OLMap.prototype.setZoom = function(value)

    	{

    		this.olMap.getView().setZoom(value);

    	}

    	WPGMZA.OLMap.prototype.getMinZoom = function()

    	{

    		return this.olMap.getView().getMinZoom();

    	}

    	WPGMZA.OLMap.prototype.setMinZoom = function(value)

    	{

    		this.olMap.getView().setMinZoom(value);

    	}

    	WPGMZA.OLMap.prototype.getMaxZoom = function()

    	{

    		return this.olMap.getView().getMaxZoom();

    	}

    	WPGMZA.OLMap.prototype.setMaxZoom = function(value)

    	{

    		this.olMap.getView().setMaxZoom(value);

    	}

    	WPGMZA.OLMap.prototype.setOptions = function(options)

    	{

    		Parent.prototype.setOptions.call(this, options);

    		if(!this.olMap)

    			return;

    		this.olMap.getView().setProperties( this.settings.toOLViewOptions() );

    	}

    	/**

    	 * TODO: Consider moving all these functions to their respective classes, same on google map (DO IT!!! It's very misleading having them here)

    	 */

    	WPGMZA.OLMap.prototype.addMarker = function(marker)

    	{

    		this.olMap.addOverlay(marker.overlay);

    		Parent.prototype.addMarker.call(this, marker);

    	}

    	WPGMZA.OLMap.prototype.removeMarker = function(marker)

    	{

    		this.olMap.removeOverlay(marker.overlay);

    		Parent.prototype.removeMarker.call(this, marker);

    	}

    	WPGMZA.OLMap.prototype.addPolygon = function(polygon)

    	{

    		this.olMap.addLayer(polygon.layer);

    		Parent.prototype.addPolygon.call(this, polygon);

    	}

    	WPGMZA.OLMap.prototype.removePolygon = function(polygon)

    	{

    		this.olMap.removeLayer(polygon.layer);

    		Parent.prototype.removePolygon.call(this, polygon);

    	}

    	WPGMZA.OLMap.prototype.addPolyline = function(polyline)

    	{

    		this.olMap.addLayer(polyline.layer);

    		Parent.prototype.addPolyline.call(this, polyline);

    	}

    	WPGMZA.OLMap.prototype.removePolyline = function(polyline)

    	{

    		this.olMap.removeLayer(polyline.layer);

    		Parent.prototype.removePolyline.call(this, polyline);

    	}

    	WPGMZA.OLMap.prototype.addCircle = function(circle)

    	{

    		this.olMap.addLayer(circle.layer);

    		Parent.prototype.addCircle.call(this, circle);

    	}

    	WPGMZA.OLMap.prototype.removeCircle = function(circle)

    	{

    		this.olMap.removeLayer(circle.layer);

    		Parent.prototype.removeCircle.call(this, circle);

    	}

    	WPGMZA.OLMap.prototype.pixelsToLatLng = function(x, y)

    	{

    		if(y == undefined)

    		{

    			if("x" in x && "y" in x)

    			{

    				y = x.y;

    				x = x.x;

    			}

    			else

    				console.warn("Y coordinate undefined in pixelsToLatLng (did you mean to pass 2 arguments?)");

    		}

    		var coord = this.olMap.getCoordinateFromPixel([x, y]);

    		if(!coord)

    			return {

    				x: null,

    				y: null

    			};

    		var lonLat = ol.proj.toLonLat(coord);

    		return {

    			lat: lonLat[1],

    			lng: lonLat[0]

    		};

    	}

    	WPGMZA.OLMap.prototype.latLngToPixels = function(latLng)

    	{

    		var coord = ol.proj.fromLonLat([latLng.lng, latLng.lat]);

    		var pixel = this.olMap.getPixelFromCoordinate(coord);

    		if(!pixel)

    			return {

    				x: null,

    				y: null

    			};

    		return {

    			x: pixel[0],

    			y: pixel[1]

    		};

    	}

    	WPGMZA.OLMap.prototype.enableBicycleLayer = function(value)

    	{

    		if(value)

    		{

    			if(!this.bicycleLayer)

    				this.bicycleLayer = new ol.layer.Tile({

    					source: new ol.source.OSM({

    						url: "http://{a-c}.tile.opencyclemap.org/cycle/{z}/{x}/{y}.png"

    					})

    				});

    			this.olMap.addLayer(this.bicycleLayer);

    		}

    		else

    		{

    			if(!this.bicycleLayer)

    				return;

    			this.olMap.removeLayer(this.bicycleLayer);

    		}

    	}

    	WPGMZA.OLMap.prototype.onElementResized = function(event)

    	{

    		this.olMap.updateSize();

    	}

    	WPGMZA.OLMap.prototype.onRightClick = function(event)

    	{

    		if($(event.target).closest(".ol-marker, .wpgmza_modern_infowindow, .wpgmza-modern-store-locator").length)

    			return true;

    		var parentOffset = $(this.element).offset();

    		var relX = event.pageX - parentOffset.left;

    		var relY = event.pageY - parentOffset.top;

    		var latLng = this.pixelsToLatLng(relX, relY);

    		this.trigger({type: "rightclick", latLng: latLng});

    		$(this.element).trigger("rightclick.wpgmza");

    		event.preventDefault();

    		return false;

    	}

    })(jQuery);