Source: Map.js

import {capitalize, sprintf} from 'utils'
import Tool from 'Tool'

// default options
const _dftOpts = {
  center: [45, 7],
  zoom: 8,
  tools: {},
  fullscreen: true,
  clearMapCtrl: 'default',
  exportMapCtrl: 'default',
  exportMapCb: null,
  geocoderMapField: true,
  tipsMapCtrl: 'default'
}

/**
 * Google maps drawing class, provides tools for drawing over a google map canvas, and export drawn data.
 *
 *      <p>This class handles the drawing tools used to draw over a google map and allows
 *      data exportation.</p>
 *      <p>The map manages also some controllers</p>
 *      <ul>
 *      <li>clear map controller</li>
 *      <li>export map controller</li>
 *      <li>geocoder text field controller</li>
 *      <li>tips controller</li>
 *      </ul>
 *      <p>Moreover every drawing tool has its own controller, which may be specifically set or used in
 *      its default form.</p>
 *      <p>Each map controller may be specified as custom, may be removed by setting the
 *      related option to <code>null</code> or used in its default form.</p>
 *      <p>Once instantiated the class and set the tools by options or instantiating direclty
 *      the drawing tool classes and adding them to the map,
 *      see {@link Map#addTool}, call the render method in order to render the widget.<br />
 *      It is possible to continue configuring the widget adding or removing tools and
 *      customize the google map instance which is returned by the {@link Map#gmap} method.</p>
 *      <p>When defining specific map controllers, be sure to make them handle the proper map methods.</p>
 *      <p>Very important: be sure to load the google maps library yourself in the head of the document!</p>
 *
 *
 * @example
 * var mymap = new geodrawer.Map('my_map_canvas_id', {
 *   tools: {
 *     point: {
 *       options: {
 *         max_items: 5
 *       }
 *     },
 *     circle: {}
 *   }
 * });
 *
 */
const Map = class {

  /**
   * @summary Constrcuts a Map
   *
   * @param {Element|String} canvas
   *    The map container element as selector or jQuery element
   * @param {Object} [options]
   *    A class options object
   * @param {Array} [options.center=new Array(45, 7)]
   *    The initial map center coordinates, (lat, lng).
   * @param {Number} [options.zoom=8]
   *    The the initial map zoom level.
   * @param {Object} [options.tools={}]
   *    The object containing the tool's names and options to be activated
   *    when initializing the map.
   *    It's a shortcut to easily define set and active tools objects.
   * @param {Number} [options.fullscreen=true]
   *    Whether or not to enable fullscreen functionality
   * @param {Object} [options.tools.point=undefined]
   *    The point tool init object
   * @param {String|Element} [options.tools.point.ctrl=undefined]
   *    The selector or jQuery element
   *    which controls the tool, default the built-in menu voice
   * @param {Object} [options.tools.point.options=undefined]
   *    The tool options object,
   *    see {@link PointTool} for available properties
   * @param {Object} [options.tools.polyline=undefined]
   *    The polyline tool init object
   * @param {String|Element} [options.tools.polyline.ctrl=undefined]
   *    The selector or jQuery element which controls the tool,
   *    default the built-in menu voice
   * @param {Object} [options.tools.polyline.options=undefined]
   *    The tool options object, see {@link PolylineTool} for available properties
   * @param {Object} [options.tools.polygon=undefined]
   *    The polygon tool init object
   * @param {String|Element} [options.tools.polygon.ctrl=undefined]
   *    The selector or jQuery element which controls the tool, default the built-in menu voice
   * @param {Object} [options.tools.polygon.options=undefined]
   *    The tool options object, see {@link PolygonTool} for available properties
   * @param {Object} [options.tools.circle=undefined]
   *    The circle tool init object
   * @param {String|Element} [options.tools.circle.ctrl=undefined]
   *    The selctor or jQuery element which controls the tool, default the built-in menu voice
   * @param {Object} [options.tools.circle.options=undefined]
   *    The tool options object, see {@link CircleTool} for available properties
   * @param {String|Element} [options.clearMapCtrl='default']
   *    The clear map controller (clears all drawings over the map).
   *    If 'default' the built-in controller is used, if <code>null</code> the clear map
   *    functionality is removed. If id attribute or an element the clear map functionality is attached to the element.
   * @param {String|Element} [options.exportMapCtrl='default']
   *    The export map controller (exports all shapes drawed over the map).
   *    If 'default' the built-in controller is used, if <code>null</code> the export map
   *    functionality is removed. If id attribute or an element the clear map functionality is attached to the element.
   * @param {Function} [options.exportMapCb=null]
   *    The callback function to call when the export map button is pressed.
   *    The callback function receives one argument, the exported data as
   *    returned by the geodrawer.Map#exportMap method.
   * @param {Boolean} [options.geocoderMapField=true]
   *    Whether or not to add the gecoder functionality which allows to center the map in a point
   *    defined through an address, or to pass the lat,lng coordinates found to the map click handlers
   *    (exactly as click over the map in a lat,lng point).
   * @param {String|Element} [options.tipsMapCtrl='default']
   *    The help tips map controller (shows tips about drawing tools).
   *    If 'default' the built-in controller is used, if <code>null</code> the tips box is not shown,
   *    if id attribute or an element the functionality is attached to the element.
   */
  constructor (canvas, options) {
    this._dom = {}
    this._dom.canvas = jQuery(canvas).addClass('geodrawer-map-canvas')
    // check canvas exists
    if (!this._dom.canvas.length) {
      throw new Error('Canvas container not found!')
    }

    // wrap canvas inside a container and add controllers container
    this._dom.container = jQuery('<div />', {'class': 'geodrawer-container'})
      .css({
        width: this._dom.canvas.css('width')
      })
    this._dom.controllersContainer = jQuery('<div />', {'class': 'geodrawer-ctrls-container'})
    this._dom.toolsCtrlsContainer = jQuery('<div />', {'class': 'geodrawer-ctrls-tools-container'})
    this._dom.actionsCtrlsContainer = jQuery('<div />', {'class': 'geodrawer-ctrls-actions-container'})
    this._dom.geocoderCtrlsContainer = jQuery('<div />', {'class': 'geodrawer-ctrls-geocoder-container'})
    this._dom.screenCtrlsContainer = jQuery('<div />', {'class': 'geodrawer-ctrls-screen-container'})
    this._dom.controllersContainer.append(
      this._dom.toolsCtrlsContainer,
      this._dom.geocoderCtrlsContainer,
      this._dom.actionsCtrlsContainer,
      this._dom.screenCtrlsContainer
    )
    this._dom.container = this._dom.canvas.wrap(this._dom.container)
      .before(this._dom.controllersContainer)
      .parent()

    // let's extend default options
    this._options = jQuery.extend({}, _dftOpts, options)

    this._supportedTools = [
      'point',
      'polyline',
      'polygon',
      'circle'
    ]

    // internal state
    this._state = {
      drawingTool: null, // actual drawing tool
      tools: [] // available tools
    }

    this._map = null
    // when importing data we need bounds to fit them into the map
    this._bounds = new google.maps.LatLngBounds()

    // controllers
    this._ctrlContainer = null
    this._controllers = {
      clearMap: null,
      clearMapCb: null,
      exportMap: null,
      exportMapCb: null,
      tipsMap: null,
      geocoder: null,
      geocoderField: null,
      geocoderCenterButton: null,
      geocoderDrawButton: null,
      fullscreen: null
    }

    // check options!
    this._processOptions()
  };

  /**
   * @summary Processes the options object setting properly some class properties
   * @ignore
   * @return void
   */
  _processOptions () {
    // init tools
    var self = this
    this._supportedTools.reverse().forEach(
      (toolName, index) => {
        if (self._options.tools.hasOwnProperty(toolName)) {
          var handler = null
          var ctrl = self._options.tools[toolName].ctrl || null
          // set tool
          if (ctrl) {
            handler = jQuery(ctrl)
            if (!handler.length) {
              throw new Error(sprintf('The given control handler for the {0} tool is not a DOM element', toolName))
            }
          }
          // add the tool
          self.addTool(
            new geodrawer[capitalize(toolName) + 'Tool'](
              self, handler, self._options.tools[toolName].options || null
            )
          )
        }
      }
    )
  }

  /**
   * @summary Initializes the google map and its events
   * @ignore
   * @return void
   */
  _initMap () {
    let mapCenter = new google.maps.LatLng(this._options.center[0], this._options.center[1])
    let mapOptions = {
      center: mapCenter,
      zoom: this._options.zoom,
      zoomControlOptions: {
        style: google.maps.ZoomControlStyle.LARGE,
        position: google.maps.ControlPosition.RIGHT_CENTER
      },
      panControl: false,
      mapTypeControl: true,
      mapTypeControlOptions: {
        position: google.maps.ControlPosition.LEFT_BOTTOM
      },
      mapTypeId: google.maps.MapTypeId.ROADMAP
    }

    this._map = new google.maps.Map(this._dom.canvas[0], mapOptions)
    this._geocoder = new google.maps.Geocoder()

    google.maps.event.addListener(this._map, 'click', (evt) => {
      this._mapClick(evt)
    })
  }

  /**
   * @summary Initializes all the map controllers
   * @ignore
   * @return void
   */
  _initControllers () {
    if (this._options.clearMapCtrl) {
      this._setClearMapController()
    }

    if (this._options.exportMapCtrl && this._options.exportMapCb) {
      this._setExportMapController()
    }

    if (this._options.geocoderMapField) {
      this._setGeocoderMapFieldController()
    }

    if (this._options.fullscreen) {
      this._setFullscreenController()
    }

    if (this._options.tipsMapCtrl) {
      this._setTipsMapController()
    }
  }

  /**
   * @summary Initializes the map set tools
   * @ignore
   * @return void
   */
  _initTools () {
    for (let k in this._state.tools) {
      if (this._supportedTools.indexOf(k) !== -1) {
        this._state.tools[k].activate()
      }
    }
  }

  /**
   * @summary Sets the clear map controller depending on the options.clearMapCtrl value
   * @ignore
   * @return void
   */
  _setClearMapController () {
    if (this._options.clearMapCtrl === 'default') {
      this._controllers.clearMap = jQuery('<div />', {'class': 'geodrawer-ctrl-clear-map'})
        .attr('title', 'clear map')
        .appendTo(this._dom.actionsCtrlsContainer)
    } else if (this._options.clearMapCtrl) {
      this._controllers.clearMap = jQuery(this._options.clearMapCtrl)
      if (!this._controllers.clearMap) {
        throw new Error('The given clear map controller is not a DOM element')
      }
    }
    this._controllers.clearMapCb = this.clearMap.bind(this)
    this._controllers.clearMap.on('click', this._controllers.clearMapCb)
  }

  /**
   * @summary Removes the clear map event and the controller if the default one
   * @ignore
   * @return void
   */
  _removeClearMapController () {
    // @TODO check me
    this._controllers.clearMap.off('click', null, this._controllers.clearMapCb)
    if (this._options.clearMapCtrl === 'default') {
      this._controllers.clearMap.remove()
    }
  }

  /**
   * @summary Sets the export map controller depending on the options.exportMapCtrl value
   * @ignore
   * @return void
   */
  _setExportMapController () {
    if (this._options.exportMapCtrl === 'default') {
      this._controllers.exportMap = jQuery('<div />', {'class': 'geodrawer-ctrl-export-map'})
        .attr('title', 'export map')
        .appendTo(this._dom.actionsCtrlsContainer)
    } else if (this._options.exportMapCtrl) {
      this._controllers.exportMap = jQuery(this._options.exportMapCtrl)
      if (!this._controllers.exportMap.length) {
        throw new Error('The given export map controller is not a DOM element')
      }
    }

    this._controllers.exportMapCb = function () { this._options.exportMapCb(this.exportMap()) }.bind(this)
    this._controllers.exportMap.on('click', this._controllers.exportMapCb)
  }

  /**
   * @summary Removes the export map event and the controller if the default one
   * @ignore
   * @return void
   */
  _removeExportMapController () {
    this._controllers.exportMap.off('click', null, this._controllers.exportMapCb)
    if (this._options.exportMapCtrl === 'default') {
      this._controllers.exportMap.remove()
    }
  }

  /**
   * @summary Sets the help tips map controller depending on the options.tips_map_ctrl value
   * @ignore
   * @return void
   */
  _setTipsMapController () {
    if (this._options.tipsMapCtrl === 'default') {
      this._controllers.tipsMap = jQuery('<div />', {'class': 'geodrawer-tips-map'})
        .appendTo(this._dom.controllersContainer)
    } else if (this._options.tipsMapCtrl) {
      this._controllers.tipsMap = jQuery(this._options.tipsMapCtrl)
      if (!this._controllers.tipsMap.length) {
        throw new Error('The given tips map controller is not a DOM element')
      }
    }

    if (this._controllers.tipsMap.length) {
      this.updateTips(this._initMapTips())
    }
  }

  /**
   * @summary Removes the tips map controller if the default one
   * @ignore
   * @return void
   */
  _removeTipsMapController () {
    if (this._options.tipsMapCtrl === 'default') {
      this._controllers.tipsMap.remove()
    }
  }

  /**
   * @summary Sets the geocoder input text field and its controllers
   * @ignore
   * @return void
   */
  _setGeocoderMapFieldController () {
    this._controllers.geocoderField = jQuery('<input />', {
      'class': 'geodrawer-geocoder-field',
      type: 'text',
      placeholder: 'insert an address'
    }).on('focus', () => {
      this.updateTips('Write an address in the field, then center the map in the calculated point, ' +
                      'or use it to draw the selected shape (acts as a click on the map).')
    })

    this._controllers.geocoderCenterButton = jQuery('<div />', {
      'class': 'geodrawer-ctrl-geocoder-center-btn',
      title: 'center in geolocalized point'
    })

    this._controllers.geocoderDrawButton = jQuery('<div />', {
      'class': 'geodrawer-ctrl-geocoder-draw-btn',
      title: 'draw the geolocalized point'
    })

    this._controllers.geocoderCenterButton.on('click', this.geocoderCenter.bind(this))
    this._controllers.geocoderDrawButton.on('click', this.geocoderDraw.bind(this))

    this._dom.geocoderCtrlsContainer.append(
      this._controllers.geocoderField,
      this._controllers.geocoderCenterButton,
      this._controllers.geocoderDrawButton
    )
  }

  /**
   * @summary Removes the geocoder input text field and its controllers
   * @ignore
   * @return void
   */
  _removeGeocoderMapField () {
    this._controllers.geocoderCenterButton.off()
    this._controllers.geocoderDrawButton.off()
    this._controllers.geocoderField.remove()
    this._controllers.geocoderCenterButton.remove()
    this._controllers.geocoderDrawButton.remove()
  }

  /**
   * @summary Sets the fullscreen controller
   * @ignore
   * @return void
   */
  _setFullscreenController () {
    this._controllers.fullscreen = jQuery('<div />', {
      'class': 'geodrawer-ctrl-fullscreen',
      title: 'fullscreen'
    }).appendTo(this._dom.screenCtrlsContainer)
      .on('click', () => {
        this._dom.container.toggleClass('geodrawer-fullscreen')
        this._controllers.fullscreen.attr('title', this._controllers.fullscreen.attr('title') === 'fullscreen'
          ? 'exit fullscreen'
          : 'fullscreen')
        google.maps.event.trigger(this._map, 'resize')
      })
  }

  /**
   * @summary Removes the fullscreen controller
   * @ignore
   * @return void
   */
  _removeFullscreenController () {
    this._controllers.fullscreen.off()
    this._controllers.fullscreen.remove()
  }

  /**
   * @summary Returns the init text shown in the tips controller
   * @ignore
   * @return {String} text The initial tip text
   */
  _initMapTips () {
    return 'Displays help tips about drawing tools.'
  }

  /**
   * @summary Handles the click event over the map, calling the active tool handler
   * @ignore
   * @param {Object} point The callback parameter returned by the google.maps event handler
   * @return void
   */
  _mapClick (point) {
    if (this._state.drawingTool === null) {
      return false
    }
    this._state.drawingTool.clickHandler(point)
  }

  // PUBLIC METHODS (to be intended as public ;)

  /**
   * @summary Adds a drawing tool
   * @param {geodrawer.Tool} tool The tool object
   * @return {Map} map object
   */
  addTool (tool) {
    if (!(tool instanceof Tool)) {
      throw new Error('The given tool object is not of the proper type')
    }

    let toolName = tool.getToolName()

    if (this._supportedTools.indexOf(toolName) === -1) {
      throw new Error(sprintf('The tool {0} is not supported', toolName))
    }
    this._state.tools[toolName] = tool
    return this
  }

  /**
   * @summary Gets a tool object giving its name
   * @param {String} toolName One of the supported tools name
   * @return {geodrawer.Tool | null} The tool object if set or null
   */
  getTool (toolName) {
    if (this._supportedTools.indexOf(toolName) === -1) {
      throw new Error(sprintf('The {0} tool is not supported', toolName))
    }
    return this._state.tools[toolName]
  }

  /**
   * @summary Removes a drawing tool
   * @param {String} toolName The name of the tool to be removed
   * @param {geodrawer.Tool} tool The tool object
   * @return {Map} map object
   */
  removeTool (toolName) {
    if (toolName && this._supportedTools.indexOf(toolName) === -1) {
      throw new Error(sprintf('The {0} tool is not supported', toolName))
    }
    if (this._state.tools[toolName]) {
      this._state.tools[toolName].deactivate(true)
      delete this._state.tools[toolName]
    }
    return this
  }

  /**
   * @summary Gets the active drawing tool
   * @return {geodrawer.Tool} The drawing tool
   */
  getDrawingTool () {
    return this._state.drawingTool
  }

  /**
   * @summary Sets the active drawing tool name
   * @param {geodrawer.Tool|null} tool The actual drawing tool, null to have no active tool
   * @return {Map} map object
   */
  setDrawingTool (tool) {
    if (tool !== null && !this._state.tools.hasOwnProperty(tool.getToolName())) {
      throw new Error('Can\'t set the drawing tool since it\'s not active')
    }
    Object.keys(this._state.tools).forEach((k) => this._state.tools[k].setUnselected())
    this._state.drawingTool = tool
    if (tool) {
      tool.setSelected()
    }
    return this
  }

  /**
   * @summary Renders the widget
   * @return {Map} map object
   */
  render () {
    // map initialization
    this._initMap()
    // add controllers
    this._initControllers()
    // init tools
    this._initTools()

    return this
  }

  /**
   * @summary Adds a controller in the default controllers container
   * @param {Object} ctrl The jQuery controller element to be added
   * @return void
   */
  addDefaultCtrl (ctrl) {
    if (!ctrl.length) {
      throw new Error('The given controller is not an element')
    }
    ctrl.prependTo(this._dom.toolsCtrlsContainer)
  }

  /**
   * @summary Clears the map
   * @return {Map} map object
   */
  clearMap () {
    for (let k in this._state.tools) {
      if (this._supportedTools.indexOf(k) !== -1) {
        this._state.tools[k].clear()
      }
    }
    console.info('geodrawer: map cleared')
    return this
  }

  /**
   * @summary Updates the text displayed in the tips controller
   * @param {String} html The tip text
   * @return void
   */
  updateTips (html) {
    if (this._controllers.tipsMap.length) {
      this._controllers.tipsMap.html(html)
    }
  }

  /**
   * @summary Returns the google map instance google.maps.Map
   * @description The google map class instance allows to customize direclty some map properties using
   *              the google.maps.Map public interface
   * @return {google.maps.Map} The google map instance
   */
  gmap () {
    return this._map
  }

  /**
   * @summary Sets the center of the map
   * @param {Array} center The [lat, lng] coordinates array
   * @return {Map} map object
   */
  setCenter (center) {
    this._options.center = center
    if (this._map) {
      this._map.setCenter(new google.maps.LatLng(center[0], center[1]))
    }
    return this
  }

  /**
   * @summary Sets the zoom of the map
   * @param {Number} zoom The zoom level
   * @return {Map} map object
   */
  setZoom (zoom) {
    this._options.zoom = zoom
    if (this._map) {
      this._map.setZoom(zoom)
    }
    return this
  }

  /**
   * @summary Sets the clear map controller
   * @param {String|Element} ctrl
   *    The clear map controller.
   *    If 'default' the built-in controller is used, if <code>null</code> the clear map
   *    functionality is removed. If selctor or jQuery element the clear map functionality
   *    is attached to the element.
   * @return {Map} map object
   */
  setClearMapCtrl (ctrl) {
    if (ctrl !== this._options.clearMapCtrl) {
      this._removeClearMapController()
    }
    this._options.clearMapCtrl = ctrl
    this._setClearMapController()
    return this
  }

  /**
   * @summary Sets the export map controller
   * @param {String|Element} ctrl
   *    The clear map controller.
   *    If 'default' the built-in controller is used, if <code>null</code> the export map
   *    functionality is removed. If selctor or jQuery element the export map functionality
   *    is attached to the element.
   * @return {Map} map object
   */
  setExportMapCtrl (ctrl) {
    if (ctrl !== this._options.exportMapCtrl) {
      this._removeExportMapController()
    }
    this._options.exportMapCtrl = ctrl
    this._setExportMapController()
    return this
  }

  /**
   * @summary Sets the geocoder map field option
   * @param {Boolean} activate Whether or not to activate the geocoder functionality
   * @return {Map} map object
   */
  setGeocoderMapField (activate) {
    this._options.geocoderMapField = activate
    if (!activate) {
      this._removeGeocoderMapField()
    } else {
      this._setGeocoderMapFieldController()
    }
    return this
  }

  /**
   * @summary Sets the tips map controller
   * @param {String|Element} ctrl
   *    The help tips map controller (shows tips about drawing tools).
   *    If 'default' the built-in controller is used, if <code>null</code> the tips box is not shown,
   *    if selector or jQuery element the functionality is attached to the element
   * @return {Map} map object
   */
  setTipsMapCtrl (ctrl) {
    if (ctrl !== this._options.tipsMapCtrl) {
      this._removeTipsMapController()
    }
    this._options.tipsMapCtrl = ctrl
    this._setTipsMapController()
    return this
  }

  /**
   * @summary Sets the fullscreen option
   * @param {Boolean} activate Whether or not to activate the fullscreen functionality
   * @return {Map} map object
   */
  setFullscreen (activate) {
    this._options.fullscreen = activate
    if (!activate) {
      this._removeFullscreenController()
    } else {
      this._setFullscreenController()
    }
    return this
  }

  /**
   * @summary Exports the map drawed shapes as data points
   * @return {Object} data The drawed data
   * @example
   * // exported data
   * {
   *  'point': [
   *    {lat: 45, lng: 12},
   *    {lat: 43, lng: 16}
   *  ],
   *  'polyline': [
   *    [
   *      {lat: 45, lng: 12},
   *      {lat: 42, lng: 12},
   *      {lat: 42.6, lng: 11}
   *    ],
   *    [
   *      {lat: 36.7, lng: 11.2},
   *      {lat: 39, lng: 12}
   *    ],
   *  ],
   *  'circle': [
   *    {lat: 45, lng: 12, radius: 10000},
   *    {lat: 44, lng: 11, radius: 230000}
   *  ]
   * }
   */
  exportMap () {
    let data = {}
    for (var k in this._state.tools) {
      if (this._supportedTools.indexOf(k) !== -1) {
        data[k] = this._state.tools[k].exportData()
      }
    }
    console.info('geodrawer: exporting data')
    return data
  }

  /**
   * @summary Imports data
   * @description Data must be in the same format as the exported ones, see {@link Map#exportMap}
   * @param {Object} data The data object
   * @return {Map} map object
   */
  importMap (data) {
    this._supportedTools.forEach(
      (toolName) => {
        if (typeof data[toolName] !== 'undefined') {
          if (this.getTool(toolName) === null) {
            let Cls = capitalize(toolName) + 'Tool'
            let ntool = new Cls(this, null)
            this.addTool(ntool)
            ntool.activate()
          }
          this.getTool(toolName).importData(data[toolName])
          this.getTool(toolName).extendBounds(this._bounds)
        }
      }
    )
    this._map.fitBounds(this._bounds)
    return this
  }

  /**
   * @summary Sets the map center converting the geocoder field input address in a LatLng point
   * @return {Map} map object
   */
  geocoderCenter () {
    let self = this
    let request = {
      address: this._controllers.geocoderField.val()
    }
    this._geocoder.geocode(request, (results, status) => {
      let result = results[0]
      if (status === 'OK') {
        self._map.setCenter(result.geometry.location)
      } else {
        console.log('geodrawer: geocoder response status: ' + status)
        alert(status)
      }
    })
    return this
  }

  /**
   * @summary Fires a map click in a LatLng point converted from the geocoder field input address
   * @return {Map} map object
   */
  geocoderDraw () {
    let self = this
    let request = {
      address: this._controllers.geocoderField.val()
    }

    this._geocoder.geocode(request, (results, status) => {
      let result = results[0]
      if (status === 'OK') {
        if (self._state.drawingTool === null) {
          alert('select a drawing tool')
        }
        self._mapClick({
          latLng: result.geometry.location
        })
      } else {
        console.log('geodrawer: geocoder response status: ' + status)
        alert(status)
      }
    })
    return this
  }
}

export default Map