content: {-# LANGUAGE TemplateHaskell #-}
  {-# LANGUAGE QuasiQuotes #-}
  {-# LANGUAGE FlexibleInstances #-}
  
  module QuickPlot.Plotly (
        plotly
      , PlotlyJSON (..)
      , PlotlyData
      , PlotlyLayout
  ) where
  
  import QuickPlot
  import QuickPlot.IPC.Protocol
  import QuickPlot.IPC.QQParser
  import Language.Haskell.TH
  import Language.Haskell.TH.Syntax
  import Language.Haskell.TH.Quote
  import Data.Aeson hiding (json)
  
  
  type PlotlyData = PlotlyJSON
  type PlotlyLayout = PlotlyJSON
  
  
  instance Plottable PlotlyData where
      plottableToJSON (PlotlyJSON trace) = [json|{
                                      data : [ #{ trace } ]
                                  }|]
      whichLibrary _ = Plotly
  
  instance Plottable [PlotlyData] where
      plottableToJSON traces = [json|{
                          data : #{ traces }
                      }|]
      whichLibrary _ = Plotly
  
  instance Plottable (PlotlyData, PlotlyLayout) where
      plottableToJSON (traces, layout) = [json|{
                                    data : [ #{ traces } ]
                                  , layout : #{ layout }
                                }|]
      whichLibrary _ = Plotly
  
  instance Plottable ([PlotlyData], PlotlyLayout) where
      plottableToJSON (traces, layout) = [json|{
                                    data : #{ traces }
                                  , layout : #{ layout }
                                }|]
      whichLibrary _ = Plotly
  
  
  -- This quasiquoter is the same as json but it wraps the value with PlotlyJSON
  -- It makes writing code more clear when using multiple libraries
  plotly :: QuasiQuoter
  plotly = QuasiQuoter { quoteExp  = plotlyExp
                       , quotePat  = const $ error "No quotePat defined for jsonQQ"
                       , quoteType = const $ error "No quoteType defined for jsonQQ"
                       , quoteDec  = const $ error "No quoteDec defined for jsonQQ"
                       }
  
  plotlyExp :: String -> ExpQ
  plotlyExp string =
      case parseTHJSON string of
          Left errorInfo  -> error $ "JSON is invalid: " ++ show errorInfo
          Right value     -> [| PlotlyJSON value |]
  
  
  data PlotlyJSON = PlotlyJSON Value
  
  instance ToJSON PlotlyJSON where
      toJSON (PlotlyJSON value) = value
  
  instance Lift PlotlyJSON where
      lift (PlotlyJSON value) = [| PlotlyJSON value |]
  