content: {-# LANGUAGE OverloadedStrings, DeriveGeneric #-}
  {-|
  Module      : Lucid.Leaflet
  Description : LeafletJS bindings
  Copyright   : (c) Tom Nielsen, Marco Zocca, 2019
  License     : GPL-3
  Maintainer  : ocramz fripost org
  Stability   : experimental
  Portability : POSIX
  
  Bindings to the LeafletJS map API.
  
  See https://leafletjs.com/ for usage details
  -}
  module Lucid.Leaflet (
    -- * CDN declarations
    leafletCDN, leafletCssCDN,
    -- * Utilities
    leafletMap, osmTileLayer,
    -- * Types
    LMap(..), LMapElement(..), TileLayerProperties(..)
    ) where
  
  import qualified Data.Aeson as Aeson
  import qualified Data.ByteString.Lazy as BSL
  import Lucid
  import qualified Data.Text as T
  import qualified Data.Text.Encoding as T
  import Lucid.PreEscaped
  import Data.Monoid
  import GHC.Generics
  
  
  
  -- | Statement for embedding the LeafletJS javascript blob.
  leafletCDN :: Monad m => HtmlT m ()
  leafletCDN 
    =  scriptSrc "https://unpkg.com/leaflet@1.2.0/dist/leaflet.js"
  
  data LMap = LMap T.Text | SetView (Double, Double) Double LMap deriving (Eq, Show)
  
  data LMapElement = TileLayer T.Text TileLayerProperties
                   | Marker (Double, Double)
                   | BindPopup T.Text LMapElement deriving (Eq, Show)
  
  newtype TileLayerProperties = TileLayerProperties { attribution :: T.Text } deriving (Eq, Show, Generic)
  instance Aeson.ToJSON TileLayerProperties 
  
  mapElementToJS :: LMapElement -> T.Text
  mapElementToJS e' = "\n" <> f e' <> ".addTo(lmap);" where
   tshow = T.pack . show
   f (Marker (x, y)) = "L.marker(["<> tshow x<>", "<> tshow y<>"])"
   f (BindPopup t e) = f e <> ".bindPopup('"<>t<>"')"
   f (TileLayer url ps) = "L.tileLayer('"<>url<>"',"<>g ps<>")"
   g = T.decodeUtf8 . BSL.toStrict . Aeson.encode
  
  
  -- | OpenStreetMap tile layer
  osmTileLayer :: LMapElement 
  osmTileLayer 
     = TileLayer "http://{s}.tile.osm.org/{z}/{x}/{y}.png" 
       $ TileLayerProperties "&copy; <a href=\"http://osm.org/copyright\">OpenStreetMap</a> contributors"
  
  -- | Statement for embedding the LeafletJS CSS stylesheet.
  leafletCssCDN :: Monad m => HtmlT m ()
  leafletCssCDN =
    link_ [rel_ "stylesheet",
           href_ "https://unpkg.com/leaflet@1.2.0/dist/leaflet.css"]
  
  -- | @\<SCRIPT\>@ section that declares a LeafletJS map
  leafletMap ::  Monad m => LMap -> [LMapElement] -> HtmlT m ()
  leafletMap mp elms = script_ $ writeMap mp <> writeElems elms where
    writeMap m = "\nvar lmap = " <> writeMap' m <> ";"
    writeMap' (LMap e) = "L.map('"<>e<>"')"
    writeMap' (SetView (x,y) z m) = writeMap' m <> ".setView(["<> tshow x<>", "<> tshow y<>"], "<> tshow z<>")"
    writeElems = T.unlines . map mapElementToJS 
    tshow = T.pack . show
  
  