{-# LANGUAGE TemplateHaskellQuotes, DeriveLift, DeriveGeneric #-}
module Metadata.Drasil.DrasilMeta where

import Data.Aeson (decodeFileStrict, FromJSON, ToJSON)
import GHC.Generics (Generic)
import Language.Haskell.TH.Syntax (Lift, addDependentFile)
import Language.Haskell.TH (Exp, Q, runIO)

{- 
  Thank you to the following people for their helpful public resources.
   - 'leftaroundabout': https://stackoverflow.com/a/44369564/16760741
   - Mark Karpov: https://markkarpov.com/tutorial/th.html
-}

-- | Create DrasilMeta newtype
newtype DrasilMeta = DrasilMeta {DrasilMeta -> String
version :: String} deriving (forall x. Rep DrasilMeta x -> DrasilMeta
forall x. DrasilMeta -> Rep DrasilMeta x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep DrasilMeta x -> DrasilMeta
$cfrom :: forall x. DrasilMeta -> Rep DrasilMeta x
Generic, Int -> DrasilMeta -> ShowS
[DrasilMeta] -> ShowS
DrasilMeta -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [DrasilMeta] -> ShowS
$cshowList :: [DrasilMeta] -> ShowS
show :: DrasilMeta -> String
$cshow :: DrasilMeta -> String
showsPrec :: Int -> DrasilMeta -> ShowS
$cshowsPrec :: Int -> DrasilMeta -> ShowS
Show, forall t.
(forall (m :: * -> *). Quote m => t -> m Exp)
-> (forall (m :: * -> *). Quote m => t -> Code m t) -> Lift t
forall (m :: * -> *). Quote m => DrasilMeta -> m Exp
forall (m :: * -> *). Quote m => DrasilMeta -> Code m DrasilMeta
liftTyped :: forall (m :: * -> *). Quote m => DrasilMeta -> Code m DrasilMeta
$cliftTyped :: forall (m :: * -> *). Quote m => DrasilMeta -> Code m DrasilMeta
lift :: forall (m :: * -> *). Quote m => DrasilMeta -> m Exp
$clift :: forall (m :: * -> *). Quote m => DrasilMeta -> m Exp
Lift)

instance ToJSON DrasilMeta

instance FromJSON DrasilMeta

-- | Configures drasilMeta at compile-time
drasilMetaCfg :: Q Exp
drasilMetaCfg :: Q Exp
drasilMetaCfg = do
  let fp :: String
fp = String
"lib/Metadata/Drasil/DrasilMetadata.json"
  Maybe DrasilMeta
maybeDM <- forall a. IO a -> Q a
runIO (forall a. FromJSON a => String -> IO (Maybe a)
decodeFileStrict String
fp :: IO (Maybe DrasilMeta))
  String -> Q ()
addDependentFile String
fp
  [|fromMaybe (error "could not read in the drasil metadata file") maybeDM|]