{-# LANGUAGE DeriveAnyClass  #-}
{-# LANGUAGE DeriveGeneric   #-}
{-# LANGUAGE TemplateHaskell #-}

module Language.ATS.Package.Config ( UserConfig (..)
                                   , mkUserConfig
                                   , cfgBin
                                   ) where

import qualified Data.ByteString.Lazy as BSL
import           Data.FileEmbed
import qualified Data.Text            as T
import           Quaalude

data UserConfig = UserConfig { UserConfig -> Text
defaultPkgs    :: Text
                             , UserConfig -> Maybe Text
path           :: Maybe Text
                             , UserConfig -> Text
githubUsername :: Text
                             , UserConfig -> Bool
filterErrors   :: Bool
                             } deriving ((forall x. UserConfig -> Rep UserConfig x)
-> (forall x. Rep UserConfig x -> UserConfig) -> Generic UserConfig
forall x. Rep UserConfig x -> UserConfig
forall x. UserConfig -> Rep UserConfig x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep UserConfig x -> UserConfig
$cfrom :: forall x. UserConfig -> Rep UserConfig x
Generic, InputNormalizer -> Decoder UserConfig
(InputNormalizer -> Decoder UserConfig) -> FromDhall UserConfig
forall a. (InputNormalizer -> Decoder a) -> FromDhall a
autoWith :: InputNormalizer -> Decoder UserConfig
$cautoWith :: InputNormalizer -> Decoder UserConfig
FromDhall, Get UserConfig
[UserConfig] -> Put
UserConfig -> Put
(UserConfig -> Put)
-> Get UserConfig -> ([UserConfig] -> Put) -> Binary UserConfig
forall t. (t -> Put) -> Get t -> ([t] -> Put) -> Binary t
putList :: [UserConfig] -> Put
$cputList :: [UserConfig] -> Put
get :: Get UserConfig
$cget :: Get UserConfig
put :: UserConfig -> Put
$cput :: UserConfig -> Put
Binary)

cfgFile :: String
cfgFile :: String
cfgFile = $(embedStringFile ("dhall" </> "config.dhall"))

defaultFileConfig :: IO ()
defaultFileConfig :: IO ()
defaultFileConfig = do
    String
dir <- XdgDirectory -> String -> IO String
getXdgDirectory XdgDirectory
XdgConfig String
"atspkg"
    Bool -> String -> IO ()
createDirectoryIfMissing Bool
True String
dir
    String -> String -> IO ()
writeFile (String
dir String -> String -> String
</> String
"config.dhall") String
cfgFile

cfgBin :: (MonadIO m) => m FilePath
cfgBin :: m String
cfgBin = IO String -> m String
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO String -> m String) -> IO String -> m String
forall a b. (a -> b) -> a -> b
$ String -> IO String
getAppUserDataDirectory (String
"atspkg" String -> String -> String
</> String
"config")

mkUserConfig :: Rules ()
mkUserConfig :: Rules ()
mkUserConfig = do

    String
cfgBin' <- Rules String
forall (m :: * -> *). MonadIO m => m String
cfgBin

    Rules (Rules ()) -> Rules ()
forall (m :: * -> *) a. Monad m => m (m a) -> m a
join (Bool -> Rules () -> Rules ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless
        (Bool -> Rules () -> Rules ())
-> Rules Bool -> Rules (Rules () -> Rules ())
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO Bool -> Rules Bool
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (String -> IO Bool
doesFileExist String
cfgBin')
        Rules (Rules () -> Rules ())
-> Rules (Rules ()) -> Rules (Rules ())
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Rules () -> Rules (Rules ())
forall (f :: * -> *) a. Applicative f => a -> f a
pure (String -> Rules ()
g String
cfgBin'))

    where g :: String -> Rules ()
g String
cfgBin' = do

            String
cfg <- IO String -> Rules String
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (XdgDirectory -> String -> IO String
getXdgDirectory XdgDirectory
XdgConfig (String
"atspkg" String -> String -> String
</> String
"config.dhall"))

            Partial => [String] -> Rules ()
[String] -> Rules ()
want [String
cfgBin']

            String -> Rules ()
readUserConfig String
cfg

            String
cfgBin' Partial => String -> (String -> Action ()) -> Rules ()
String -> (String -> Action ()) -> Rules ()
%> \String
_ -> do
                Partial => [String] -> Action ()
[String] -> Action ()
need [String
cfg]
                UserConfig
cfgContents <- IO UserConfig -> Action UserConfig
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO UserConfig -> Action UserConfig)
-> IO UserConfig -> Action UserConfig
forall a b. (a -> b) -> a -> b
$ Decoder UserConfig -> Text -> IO UserConfig
forall a. Decoder a -> Text -> IO a
input Decoder UserConfig
forall a. FromDhall a => Decoder a
auto (String -> Text
T.pack String
cfg)
                IO () -> Action ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> Action ()) -> IO () -> Action ()
forall a b. (a -> b) -> a -> b
$ String -> ByteString -> IO ()
BSL.writeFile String
cfgBin' (UserConfig -> ByteString
forall a. Binary a => a -> ByteString
encode (UserConfig
cfgContents :: UserConfig))

readUserConfig :: FilePath -> Rules ()
readUserConfig :: String -> Rules ()
readUserConfig String
cfg = do

    Partial => [String] -> Rules ()
[String] -> Rules ()
want [String
cfg]

    Bool
e <- IO Bool -> Rules Bool
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Bool -> Rules Bool) -> IO Bool -> Rules Bool
forall a b. (a -> b) -> a -> b
$ String -> IO Bool
doesFileExist String
cfg

    String
cfg Partial => String -> (String -> Action ()) -> Rules ()
String -> (String -> Action ()) -> Rules ()
%> \String
_ -> Bool -> Action () -> Action ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless Bool
e (Action () -> Action ()) -> Action () -> Action ()
forall a b. (a -> b) -> a -> b
$
        IO () -> Action ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO ()
defaultFileConfig