content: {-# language OverloadedStrings, ExtendedDefaultRules #-}
  {-|
  Module      : Lucid.VegaLite
  Description : Vega-lite bindings
  Copyright   : (c) Tom Nielsen, Marco Zocca, 2019
  License     : GPL-3
  Maintainer  : ocramz fripost org
  Stability   : experimental
  Portability : POSIX
  
  Bindings to the vega-lite visualization and infographics API.
  
  See https://vega.github.io/ for usage details
  -}
  module Lucid.VegaLite (
    -- * Standalone
    mkVegaHtml
    -- * Utilities
    , vegaEmbedHead, vegaEmbedBodyScript) where
  
  import Lucid
  import Lucid.PreEscaped (scriptSrc)
  
  import qualified Data.Aeson as A
  
  -- import qualified Data.Text as T
  import qualified Data.Text.Encoding as T (decodeUtf8)
  
  import qualified Data.ByteString.Lazy as LBS
  
  import Data.Monoid
  
  vegaCDN, vegaLiteCDN, vegaEmbedCDN :: Monad m => HtmlT m ()
  vegaCDN = scriptSrc "https://cdn.jsdelivr.net/npm/vega@3"
  vegaLiteCDN = scriptSrc "https://cdn.jsdelivr.net/npm/vega-lite@2.5.0"
  vegaEmbedCDN = scriptSrc "https://cdn.jsdelivr.net/npm/vega-embed@3"
  
  -- | Construct a standalone HTML page that can render a vega-lite plot. The plot will be rendered by the vega-embed library.
  --
  -- NB: the 'A.Value' parameter must contain a vega-lite JSON payload
  mkVegaHtml :: A.Value -> Html ()
  mkVegaHtml vl = doctypehtml_ $ html_ $ do
    meta_ [charset_ "UTF-8"]
    head_ vegaEmbedHead
    with div_ [id_ "vis"] ""
    body_ $ vegaEmbedBodyScript vl 
  
  -- | The statements for downloading the vega javascript blobs from the CDN. Must be in the document \<HEAD\>
  vegaEmbedHead :: Html ()
  vegaEmbedHead = do
      vegaCDN
      vegaLiteCDN
      vegaEmbedCDN
  
  -- | The statement for embedding the vega JSON payload and initializing vega-embed. Must be in the \<BODY\> block and referenced by a \<div id="vis"\>\</div\>
  vegaEmbedBodyScript :: A.Value -> Html ()
  vegaEmbedBodyScript vl = 
      script_ $ T.decodeUtf8 $ LBS.toStrict ("const spec =" <> A.encode vl <> "; vegaEmbed('#vis', spec).then(result => console.log(result)).catch(console.warn);" :: LBS.ByteString)     
  