import React, { Component } from 'react'
import { isBrowser } from '../util'
import styles from 'css/components/map.css'
import { MAP_TOOLTIP_ZOOM_LEVEL } from '../constants'

// conditionally import Leaflet + plugins -> requires `window`
let L
if (isBrowser) {

  L = require('leaflet')
  require('leaflet.markercluster')

}

export default class Map extends Component {

  constructor() {

    super()

    this.onMapDragEnd = this.onMapDragEnd.bind(this)
    this.onMapZoomEnd = this.onMapZoomEnd.bind(this)
    this.onMarkerClick = this.onMarkerClick.bind(this)

  }

  componentDidMount() {

    this.initMap()

  }

  componentDidUpdate() {

    const { markers } = this.props

    // clear pubs
    this.clearMarkers()

    // TODO - really should check if markers != prevProps.markers
    this.plotMarkers(markers, this.generateMarkerIcon())

  }

  initMap() {

    const { markers, mapOptions, tileOptions, tileURL } = this.props

    // init Leaflet map
    this.map = L.map('map', mapOptions)

    // add map events
    this.map.on('dragend', this.onMapDragEnd)
    this.map.on('zoomend', this.onMapZoomEnd)

    // configure Leaflet
    L.tileLayer(tileURL, tileOptions).addTo(this.map)

    // clear pubs
    this.clearMarkers()

    // plot pubs
    this.plotMarkers(markers, this.generateMarkerIcon())

  }

  generateClusterIcon(cluster) {

    return L.divIcon({ html: `<span>${cluster.getChildCount()}</span>`, className: styles.cluster, iconSize: [ 30, 30 ] })

  }

  generateMarkerIcon() {

    return L.divIcon({ className: styles.icon, iconSize: [ 40, 40 ] })

  }

  plotMarkers(markers, icon) {

    // init layers
    this.tooltipLayer = L.layerGroup()
    this.markerLayer = L.markerClusterGroup({ iconCreateFunction: this.generateClusterIcon })

    markers.map( ({ coordinates: [ lng, lat ], name }, index) => {

      // init tooltip
      let tooltip = new L.tooltip({ direction: 'bottom', offset: [ 0, 20 ], permanent: true })
        .setLatLng([ lat, lng ])
        .setContent(name)

      // add tooltip to layer
      this.tooltipLayer.addLayer(tooltip)

      // init marker
      let marker = new L.marker([ lat, lng ], { icon })
        .bindPopup(name)

      // marker events
      marker.on('click', () => this.onMarkerClick(index))

      // add marker to layer
      return this.markerLayer.addLayer(marker)

    } )

    // add layer to map
    this.markerLayer.addTo(this.map)

    // TODO - center/zoom map based on markerLayer bounds

  }

  clearMarkers() {

    this.markerLayer && this.markerLayer.clearLayers()

  }

  toggleTooltips() {

    const zoomLevel = this.map.getZoom()
    const tooltipLayer = this.tooltipLayer
    const isLayerOnMap = this.map.hasLayer(tooltipLayer)
    const isTooltipZoomLevel = zoomLevel >= MAP_TOOLTIP_ZOOM_LEVEL

    if (isTooltipZoomLevel && !isLayerOnMap) return tooltipLayer.addTo(this.map)
    else if (!isTooltipZoomLevel && isLayerOnMap) return tooltipLayer.removeFrom(this.map)

  }

  onMapDragEnd() {

    const { setPoint } = this.props
    const { lat, lng } = this.map.getCenter()

    setPoint([ lng, lat ])

  }

  onMapZoomEnd() {

    this.toggleTooltips()

  }

  onMarkerClick(index) {

    const { setSelectedResult } = this.props

    setSelectedResult(index)

  }

  render() {

    return (
      <div id='map' className={styles.base}></div>
    )

  }

}

@@ -1309,32 +1309,118 @@
 erIcon())%0A%0A  %7D%0A%0A
+  fitMapToBounds(bounds) %7B%0A%0A    const %7B map %7D = this%0A%0A    map.fitBounds(bounds)%0A%0A  %7D%0A%0A
   generateCluste
@@ -1697,24 +1697,83 @@
 s, icon) %7B%0A%0A
+    // no markers? abort!%0A    if (!markers.length) return%0A%0A
     // init 
@@ -2571,22 +2571,93 @@
 %0A    // 
-TODO -
+get layer bounds%0A    const layerBounds = this.markerLayer.getBounds()%0A%0A    //
  center/
@@ -2669,16 +2669,10 @@
 map 
-based on
+to
  mar
@@ -2686,16 +2686,53 @@
 r bounds
+%0A    this.fitMapToBounds(layerBounds)
 %0A%0A  %7D%0A%0A 

add fit map to bounds