# Source: bemap-map.js

    /**
     * BeNomad BeMap JavaScript API - Map abstract class
     */

    /**
     * @classdesc
     * Base class for map.
     * @public
     * @constructor
     * @abstract
     * @param {bemap.Context} context BeMap-JS-API Context.
     * @param {object} options.
     */
    bemap.Map = function(context, options) {
      /**
       * @protected
       */
      this.ctx = context;

      /**
       * @protected
       */
      this.native = null;

      /**
       * @protected
       */
      this.layers = [];

      /**
       * @protected
       */
      this.events = [];

      if (context === undefined) {
        console.error("Context is required!");
        return;
      }

      /**
       * @protected
       */
      this.callback = [];
    };

    /**
     * Reserved name used to store the bemap object into the native properties of OpenLayers.
     */
    bemap.Map.OWNREF = '__bemap_own_ref__';

    /**
     * List of available layer name by default.
     * @public
     * @enum bemap.Map.DEFAULT_LAYER
     */
    bemap.Map.DEFAULT_LAYER = {
      BACKGROUND: 'background',
      CIRCLE: 'circle',
      POLYGON: 'polygon',
      POLYLINE: 'polyline',
      MARKER: 'marker',
      ROUTE: 'route'
    };

    /**
     * List of available projections.
     * @public
     * @enum bemap.Map.PROJ
     */
    bemap.Map.PROJ = {
      EPSG_WGS84: 'EPSG:4326',
      EPSG_MERCATOR: 'EPSG:3857'
    };

    bemap.Map.EventType = {
      LOAD: 'load',
      CHANGE: 'change',
      CHANGE_SIZE: 'change:size',
      CHANGE_VIEW: 'change:view',
      RESIZE: 'resize',
      CLICK: 'click',
      SINGLECLICK: 'singleclick',
      DBLCLICK: 'dblclick',
      MOVESTART: 'movestart',
      MOVEEND: 'moveend',
      POINTERUP: 'pointerup',
      POINTERDOWN: 'pointerdown',
      POINTERDRAG: 'pointerdrag',
      POINTERMOVE: 'pointermove',
      POSTCOMPOSE: 'postcompose',
      POSTRENDER: 'postrender',
      PRECOMPOSE: 'precompose',
      PROPERTYCHANGE: 'propertychange',
      WHEEL: 'wheel',
      KEYDOWN: 'keydown',
      KEYPRESS: 'keypress',
      TOUCHSTART: 'touchstart',
      TOUCHMOVE: 'touchmove',
      TOUCHEND: 'touchend'
    };

    /**
     * Add default layers.
     * @public
     * @param {object} options
     * @param {boolean} options.markerAsCluster
     * @return {bemap.Map} this
     */
    bemap.Map.prototype.defaultLayers = function(options) {
      var opts = options || {};

      this.addLayer(new bemap.BemapLayer({
        name: bemap.Map.DEFAULT_LAYER.BACKGROUND,
        styles: opts.styles ? opts.styles : '',
      }));

      this.defaultOverlayLayers();

      return this;
    };

    /**
     * Add default overlay layers, like dedicated for markers or polyline, etc.
     * @public
     * @param {object} options
     * @param {boolean} options.markerAsCluster
     * @return {bemap.Map} this
     */
    bemap.Map.prototype.defaultOverlayLayers = function(options) {
      var opts = options || {};

      this.addLayer(new bemap.VectorLayer({
        name: bemap.Map.DEFAULT_LAYER.POLYGON
      }));

      this.addLayer(new bemap.VectorLayer({
        name: bemap.Map.DEFAULT_LAYER.CIRCLE
      }));

      this.addLayer(new bemap.VectorLayer({
        name: bemap.Map.DEFAULT_LAYER.ROUTE
      }));

      this.addLayer(new bemap.VectorLayer({
        name: bemap.Map.DEFAULT_LAYER.POLYLINE
      }));

      if (opts.markerAsCluster) {
        this.addLayer(new bemap.ClusterLayer({
          name: bemap.Map.DEFAULT_LAYER.MARKER
        }));
      } else {
        this.addLayer(new bemap.VectorLayer({
          name: bemap.Map.DEFAULT_LAYER.MARKER
        }));
      }

      return this;
    };

    /**
     * Create a background layer for each geoserver name.
     * @public
     * @param {array} geoservers List of geoserver name.
     * @return {bemap.Map} this
     */
    bemap.Map.prototype.backgroundLayers = function(geoservers, options) {
      var opts = options ? options : {};
      for (var i = 0; i < geoservers.length; i++) {
        var geoserver = geoservers[i];
        var layer = new bemap.BemapLayer({
          name: bemap.Map.DEFAULT_LAYER.BACKGROUND + '_' + geoserver,
          styles: opts.styles ? opts.styles : '',
          geoserver: geoserver
        });

        this.addLayer(layer);

        if (i == 0) {
          layer.setVisible(true);
        } else {
          layer.setVisible(false);
        }
      }

      return this;
    };

    /**
     * Switch bytween several background layers.
     * @public
     * @param {String} geoserver Name of geoserver.
     * @return {bemap.Map} this
     */
    bemap.Map.prototype.switchBackgroundLayer = function(geoserver) {
      var filter = bemap.Map.DEFAULT_LAYER.BACKGROUND + '_' + geoserver;
      for (var j = 0; j < this.layers.length; j++) {
        var layer = this.layers[j];
        if (layer.name.indexOf(bemap.Map.DEFAULT_LAYER.BACKGROUND) != 0) {
          continue;
        }
        if (layer.name == filter) {
          layer.setVisible(true);
        } else {
          layer.setVisible(false);
        }
      }

      return this;
    };

    /**
     * Add a layer to the map
     * @public
     * @param {bemap.Layer} layer
     * @param {object} options
     * @return {bemap.Map} this
     */
    bemap.Map.prototype.addLayer = function(layer, options) {
      if (layer !== null && bemap.inheritsof(layer, bemap.Layer)) {
        this.layers.push(layer);
      }
      return this;
    };

    /**
     * Search the layer by name.
     * @public
     * @param {String} name of layer.
     * @return {bemap.Layer} Return the layer or null if not found.
     */
    bemap.Map.prototype.getLayerByName = function(name) {
      var key, l;
      for (key in this.layers) {
        l = this.layers[key];
        if (l.name == name) {
          return l;
        }
      }
      return null;
    };

    /**
     * Return the satus of drag pan of map.
     * @public
     * @abstract
     * @param {Object} options.dragPan.
     * @return {boolean} true to enable the drag pan of map, otherwise false.
     */
    bemap.Map.prototype.isDragPan = function(options) {
      return false;
    };

    /**
     * Enable or disable the drag pan of map.
     * @public
     * @abstract
     * @param {boolean} active true to enable the drag pan of map, otherwise false.
     * @param {Object} options.dragPan.
     * @return {bemap.Map} this
     */
    bemap.Map.prototype.setDragPan = function(active, options) {
      return this;
    };

    /**
     * Move map to new coordinate.
     * @public
     * @abstract
     * @param {double} lon Longitude in degres decimal (WGS84).
     * @param {double} lat Latitude in degres decimal (WGS84).
     * @param {int} zoom Zoom level (optional).
     * @param {Object} options Options (optional).
     * @return {bemap.Map} this
     */
    bemap.Map.prototype.move = function(lon, lat, zoom, options) {
      return this;
    };

    /**
     * Set the center and the zoom of the map to fit the bounding box.
     * @param {bemap.BoundingBox} boundingBox the bounding box to fit.
     * @param {Object} options Options (optional).
     * @return {bemap.Map} this.
     */
    bemap.Map.prototype.moveToBoundingBox = function(boundingBox, options) {
      return this;
    };

    /**
     * Move map and zoom on data contains in layers.
     * @public
     * @abstract
     * @param {bemap.Layer} layer Layer.
     * @param {Object} options Options (optional).
     * @return {bemap.Map} this
     */
    bemap.Map.prototype.moveToLayerData = function(layer, options) {
      return this;
    };

    /**
     * Zoom on map, set new zoom level.
     * @public
     * @abstract
     * @param {int} zoom Zoom level (optional).
     * @param {Object} options Options (optional).
     * @return {bemap.Map} this
     */
    bemap.Map.prototype.zoom = function(zoom, options) {
      return this;
    };

    /**
     * Get current zoom of map.
     * @public
     * @return {int} -1 if not supported.
     */
    bemap.Map.prototype.getZoom = function() {
      return -1;
    };

    /**
     * Rotation of map, set new angle of map.
     * @public
     * @abstract
     * @param {int} angle in degrees.
     * @param {Object} options Options (optional).
     * @return {bemap.Map} this
     */
    bemap.Map.prototype.rotation = function(angle, options) {
      return this;
    };

    /**
     * Get current rotation angle of map.
     * @public
     * @return {int} -1 if not supported.
     */
    bemap.Map.prototype.getRotation = function() {
      return -1;
    };

    /**
     * Refresh map.
     * @public
     * @abstract
     * @param {Object} options Options (optional).
     * @return {bemap.Map} this
     */
    bemap.Map.prototype.refresh = function(options) {
      return this;
    };

    /**
     * Build icon resource.
     * @public
     * @abstract
     * @param {bemap.Icon} icon
     * @param {object} options
     * @return {bemap.Map} this
     */
    bemap.Map.prototype.buildIcon = function(icon, options) {
      return this;
    };

    /**
     * Add a marker to the layer
     * @public
     * @abstract
     * @param {bemap.Marker} marker
     * @param {object} options
     * @return {bemap.Map} this
     */
    bemap.Map.prototype.addMarker = function(marker, options) {
      return this;
    };

    /**
     * Remove a marker from the layer
     * @public
     * @abstract
     * @param {bemap.Marker} marker
     * @return {bemap.Map} this
     */
    bemap.Map.prototype.removeMarker = function(marker) {
      return this;
    };

    /**
     * Add a multipoint to the layer
     * @public
     * @abstract
     * @param {bemap.MultiPoint} multipoint
     * @param {object} options
     * @return {bemap.Map} this
     */
    bemap.Map.prototype.addMultiMarker = function(multipoint, options) {
      return this;
    };

    /**
     * Remove a multimarker from the layer
     * @public
     * @abstract
     * @param {bemap.MultiMarker} multimarker
     * @return {bemap.Map} this
     */
    bemap.Map.prototype.removeMultimarker = function(multimarker) {
      return this;
    };

    /**
     * Build LineStyle resource.
     * @public
     * @abstract
     * @param {bemap.LineStyle} LineStyle
     * @param {object} options
     * @return {bemap.Map} this
     */
    bemap.Map.prototype.buildLineStyle = function(style, options) {
      return this;
    };

    /**
     * Add a Polyline to the layer
     * @public
     * @abstract
     * @param {bemap.Polyline} Polyline
     * @param {object} options
     * @return {bemap.Map} this
     */
    bemap.Map.prototype.addPolyline = function(multiline, options) {
      return this;
    };

    /**
     * Remove a polyline from the layer
     * @public
     * @abstract
     * @param {bemap.Polyline} polyline
     * @return {bemap.Map} this
     */
    bemap.Map.prototype.removePolyline = function(polyline) {
      return this;
    };

    /**
     * Refresh all objects from a layer.
     * @public
     * @param {bemap.Layer} layer the layer object to refresh.
     * @return {bemap.Map} this
     */
    bemap.Map.prototype.refreshLayer = function(layer) {
      return this;
    };

    /**
     * Remove all objects from a layer.
     * @public
     * @abstract
     * @param {bemap.Layer} layer the layer object to clear.
     * @return {bemap.Map} this
     */
    bemap.Map.prototype.clearLayer = function(layer) {
      return this;
    };

    /**
     * Set the visibility of the layer.
     * @public
     * @abstract
     * @param {bemap.Layer} layer the layer of wich to set the visibility.
     * @param {boolean} visible.
     * @return {bemap.Map} return this.
     */
    bemap.Map.prototype.visibleLayer = function(layer, visible) {
      return this;
    };

    /**
     * Remove a layer from the map.
     * @public
     * @abstract
     * @param {bemap.Layer} layer layer to remove from the map.
     * @return {bemap.Map} this.
     */
    bemap.Map.prototype.removeLayer = function(layer) {
      return this;
    };

    /**
     * Set the listner when an specified eventType occur on bemap.Map.
     * @public
     * @abstract
     * @param {bemap.Map.EventType} eventType Event type.
     * @param {function} callback Function will be called when the specified eventType is occur.
     * @param {object} options options.
     * @return {bemap.Listener} this.
     */
    bemap.Map.prototype.on = function(eventType, callback, options) {
      return new bemap.Listener();
    };

    /**
     * Set the listner when an specified eventType occur on bemap.Marker.
     * @public
     * @abstract
     * @param {bemap.Marker} marker
     * @param {bemap.Map.EventType} eventType Event type.
     * @param {function} callback Function will be called when the specified eventType is occur.
     * @param {object} options options.
     * @return {bemap.Listener} this.
     */
    bemap.Map.prototype.onMarker = function(marker, eventType, callback, options) {
      return new bemap.Listener();
    };

    /**
     * Set the listner when an specified eventType occur on all bemap.Marker.
     * @public
     * @abstract
     * @param {bemap.Map.EventType} eventType Event type.
     * @param {function} callback Function will be called when the specified eventType is occur.
     * @param {object} options options.
     * @return {bemap.Listener} this.
     */
    bemap.Map.prototype.onMarkers = function(eventType, callback, options) {
      return new bemap.Listener();
    };

    /**
     * Set the listner when an specified eventType occur on all bemap.MultiMarker.
     * @public
     * @abstract
     * @param {bemap.Map.EventType} eventType Event type.
     * @param {function} callback Function will be called when the specified eventType is occur.
     * @param {object} options options.
     * @return {bemap.Listener} this.
     */
    bemap.Map.prototype.onMultiMarkers = function(eventType, callback, options) {
      return new bemap.Listener();
    };

    /**
     * Set the listner when an specified eventType occur on bemap.Polyline.
     * @public
     * @abstract
     * @param {bemap.Polyline} polyline
     * @param {bemap.Map.EventType} eventType Event type.
     * @param {function} callback Function will be called when the specified eventType is occur.
     * @param {object} options options.
     * @return {bemap.Listener} this.
     */
    bemap.Map.prototype.onPolyline = function(polyline, eventType, callback, options) {
      return new bemap.Listener();
    };

    /**
     * Set the listner when an specified eventType occur on all bemap.Polyline.
     * @public
     * @abstract
     * @param {bemap.Map.EventType} eventType Event type.
     * @param {function} callback Function will be called when the specified eventType is occur.
     * @param {object} options options.
     * @return {bemap.Listener} this.
     */
    bemap.Map.prototype.onPolylines = function(eventType, callback, options) {
      return new bemap.Listener();
    };

    /**
     * Set get feature info call back.
     * @param {bemap.Layer} layer set the bemap layer.
     * @param {object} options options.
     * @param {function} options.beforeCallback callback called at data reception and before display the popup.
     * @param {function} options.afterCallback callback called after display the popup.
     * @return {bemap.Listener} listener;
     */
    bemap.Map.prototype.onGetFeatureInfo = function(layer, options) {
      console.log("onGetFeatureInfo is not supported by this browser");
      return new bemap.Listener();
    };

    /**
     * Define the draggable capability for bemap.Marker.
     * @protected
     * @param {bemap.Marker} marker bemap object.
     * @param {function} callback Function will be called when the specified eventType is occur.
     * @param {object} options Options.
     * @param {bemap.Layer} options.layerFilter set the bemap layer used as filter.
     * @return {bemap.Listener} bemap.listener.
     */
    bemap.Map.prototype.draggableMarker = function(marker, callback, options) {
      return new bemap.Listener();
    };

    /**
     * Define the draggable capability for all bemap.Marker.
     * @protected
     * @param {function} callback Function will be called when the specified eventType is occur.
     * @param {object} options Options.
     * @param {bemap.Layer} options.layerFilter set the bemap layer used as filter.
     * @return {bemap.Listener} bemap.listener.
     */
    bemap.Map.prototype.draggableMarkers = function(callback, options) {
      return new bemap.listener();
    };

    /**
     * Define the draggable capability for all bemap.MultiMarkers.
     * @protected
     * @param {function} callback Function will be called when the specified eventType is occur.
     * @param {object} options Options.
     * @param {bemap.Layer} options.layerFilter set the bemap layer used as filter.
     * @return {bemap.Listener} bemap.listener.
     */
    bemap.Map.prototype.draggableMultiMarkers = function(callback, options) {
      return new bemap.listener();
    };

    /**
     * Define the draggable capability for bemap.Polyline.
     * @protected
     * @param {bemap.Polyline} polyline bemap object.
     * @param {function} callback Function will be called when the specified eventType is occur.
     * @param {object} options Options.
     * @param {bemap.Layer} options.layerFilter set the bemap layer used as filter.
     * @return {bemap.Listener} bemap.listener.
     */
    bemap.Map.prototype.draggablePolyline = function(polyline, callback, options) {
      return new bemap.listener();
    };

    /**
     * Define the draggable capability for all bemap.Polyline.
     * @protected
     * @param {function} callback Function will be called when the specified eventType is occur.
     * @param {object} options Options.
     * @param {bemap.Layer} options.layerFilter set the bemap layer used as filter.
     * @return {bemap.Listener} bemap.listener.
     */
    bemap.Map.prototype.draggablePolylines = function(callback, options) {
      return new bemap.listener();
    };

    /**
     * Add a popup to the map
     * @public
     * @param {bemap.Popup} popup
     * @param {object} options
     * @return {bemap.Map} this
     */
    bemap.Map.prototype.addPopup = function(popup, options) {
      return this;
    };

    /**
     * Remove a popup from the map.
     * @public
     * @param {bemap.Popup} popup the popup to remove from the map.
     * @return {bemap.Map} this;
     */
    bemap.Map.prototype.removePopup = function(popup) {
      return this;
    };

    /**
     * Set the visiblility of the popup.
     * @param {bemap.Popup} popup the popup.
     * @param {Boolean} visible true for visible and false for hidden.
     * @return {bemap.Popup} this.
     */
    bemap.Map.prototype.setVisiblePopup = function(popup, visible) {
      return this;
    };

    /**
     * Remove all the popups from the map.
     * @return {bemap.Map} this;
     */
    bemap.Map.prototype.clearPopup = function() {
      return this;
    };

    /**
     * Set the coordinate of the popup.
     * @param {bemap.Popup} popup the popup of wich to set the coordinate.
     * @param {bemap.Coordinate} coordinate the new coordinate.
     * @param {object} options Options.
     * @param {bemap.Layer} options.panningMap enable the map panning animation. move map from the current position to the popup anchor at the center of map.
     * @return {bemap.Map} this.
     */
    bemap.Map.prototype.setCoordinatePopup = function(popup, coordinate, options) {
      return this;
    };

    /**
     * Get the center of the map in bemap.Coordinate.
     * @return {bemap.Coordinate} the center of the map.
     */
    bemap.Map.prototype.getCenter = function() {
      return new bemap.Coordinate();
    };

    /**
     * Get the limits of the map on the current zoom.
     * @return {bemap.BoundingBox} the bounding box containing the limits.
     */
    bemap.Map.prototype.getBoundingBox = function() {
      return new bemap.BoundingBox();
    };