# Source: bemap-leaflet/bemap-map-leaflet-marker.js

    /**
     * Add a marker to the layer
     * @public
     * @param {bemap.Marker} marker
     * @param {object} options
     * @return {bemap.LeafletMap} this
     */

    bemap.LeafletMap.prototype.addMarker = function(marker, options) {
      if (marker !== null && bemap.inheritsof(marker, bemap.Marker)) {
        var opts = options || {};
        var l = null;

        if (opts.layer !== undefined && (bemap.inheritsof(opts.layer, bemap.VectorLayer) || bemap.inheritsof(opts.layer, bemap.ClusterLayer))) {
          l = opts.layer;
        } else {
          l = this.getLayerByName(bemap.Map.DEFAULT_LAYER.MARKER);
          if (l === null) {
            l = new bemap.VectorLayer({
              name: bemap.Map.DEFAULT_LAYER.MARKER
            });
            this.addLayer(l);
          }
        }

        var icon = marker.getIcon();
        var nativeIcon = null;

        if (icon) {
           if (!icon.native) {
             nativeIcon = L.icon({
               iconUrl: icon.getSrc(),
               iconSize: icon.scale && icon.height && icon.width ? [icon.width * icon.scale, icon.height * icon.scale] : '',
               iconAnchor: [icon.width * icon.scale * icon.getAnchorX(), icon.height * icon.scale * icon.getAnchorY()]
             });

             icon.native = nativeIcon;
           }

         } else if (bemap.inheritsof(l, bemap.ClusterLayer)) {

           icon = l.style.icon;
           if (icon && !icon.native) {
             nativeIcon = L.icon({
               iconUrl: icon.getSrc(),
               iconSize: icon.scale && icon.height && icon.width ? [icon.width * icon.scale, icon.height * icon.scale] : '',
               iconAnchor: [icon.width * icon.scale * icon.getAnchorX(), icon.height * icon.scale * icon.getAnchorY()]//piotr
             });

             icon.native = nativeIcon;

           }
         }

        if (!icon || !icon.native) {
          console.error("PLease set a icon!");
        }

        marker.native = L.marker(marker.getCoordinate().getLatLonArray(), {
          icon: icon.native
        });

        if (marker.map === null) {
          marker.map = this;
        }

        if (marker.layer === null) {
          marker.layer = l;
        }

        marker.native.addTo(l.native);
      }

      return this;
    };

    /**
     * Set the coordinates of the marker.
     * @protected
     * @param {bemap.Marker} marker the marker object to remove.
     * @return {bemap.LeafletMap} this
     */
    bemap.LeafletMap.prototype.setCoordinateMarker = function(marker) {
      var c = marker.getCoordinate();
      marker.native.setLatLng(L.latLng(c.getLat(), c.getLon()));

      return this;
    };

    /**
     * Remove a marker from his layer.
     * @param {bemap.Marker} marker the marker object to remove.
     * @return {bemap.LeafletMap} this
     */
    bemap.LeafletMap.prototype.removeMarker = function(marker) {
      if (marker !== null && bemap.inheritsof(marker, bemap.Marker) && marker.layer && marker.layer.native) {
        marker.map.native.removeLayer(marker.native);
        marker.layer = null;
        marker.map = null;
      }
      return this;
    };

    /**
     * Set the listner when an specified eventType occur on bemap.Marker.
     * @public
     * @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.LeafletMap.prototype.onMarker = function(marker, eventType, callback, options) {
      var opts = options ? options : {};

      var nativeListener = marker.native.on(eventType, function(evt) {
        var mapEvent = new bemap.MapEvent({
          native: evt,
          bemapObject: marker,
          x: evt.containerPoint ? evt.containerPoint.x : undefined,
          y: evt.containerPoint ? evt.containerPoint.y : undefined,
          coordinate: evt.latlng ? new bemap.Coordinate(evt.latlng.lng, evt.latlng.lat) : undefined,
          properties: options,
          map: this
        });
        callback(mapEvent);
      });
      var listener = new bemap.Listener({
        native: nativeListener,
        callback: callback,
        key: eventType,
        bemapObject: marker
      });
      return 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.LeafletMap.prototype.draggableMarker = function(marker, callback, options) {
      var _this = this,
        opts = options ? options : {},
        startPixel, startCoordinate;

      marker.native.on('mousedown', function(evt) {
        _this.native.dragging.disable();
        startPixel = evt.containerPoint;

        var latlng = marker.native._latlng;
        var markerStartingLat = latlng.lat;
        var markerStartingLng = latlng.lng;

        startCoordinate = new bemap.Coordinate(markerStartingLat, markerStartingLng);

        latlng = evt.latlng;
        var mouseStartingLat = latlng.lat;
        var mouseStartingLng = latlng.lng;

        _this.native.on('mousemove', function(evt) {
          latlng = evt.latlng;
          var mouseNewLat = latlng.lat;
          var mouseNewLng = latlng.lng;

          var latDifference = mouseStartingLat - mouseNewLat;
          var lngDifference = mouseStartingLng - mouseNewLng;
          var center = [markerStartingLat - latDifference, markerStartingLng - lngDifference];
          marker.native.setLatLng(center);
        });
      });

      this.native.on('mouseup', function(evt) {
        _this.native.dragging.enable();
        _this.native.removeEventListener('mousemove');

        var mapEvent = new bemap.MapEvent({
          native: evt,
          bemapObject: marker,
          x: evt.containerPoint ? evt.containerPoint.x : undefined,
          y: evt.containerPoint ? evt.containerPoint.y : undefined,
          coordinate: evt.latlng ? new bemap.Coordinate(evt.latlng.lat, evt.latlng.lng) : undefined,
          //startX: startPixel.x,
          //startY: startPixel.y,
          //startCoordinate: startCoordinate,
          properties: options,
          map: this
        });

        callback(mapEvent);
      });

      this.events.dragFeature = new bemap.Listener({
        native: null,
        key: "dragFeature",
        bemapObject: marker
      });

      return this.events.dragFeature;
    };