content: -- |
  -- Module      : AOC.Run.Config
  -- Copyright   : (c) Justin Le 2018
  -- License     : BSD3
  --
  -- Maintainer  : justin@jle.im
  -- Stability   : experimental
  -- Portability : non-portable
  --
  -- Utilities for loading configuration file.
  --
  
  
  module AOC.Run.Config (
      Config(..), configFile, defConfPath
    , session
    ) where
  
  import           Control.Exception
  import           Control.Monad
  import           Data.Default.Class
  import           GHC.Generics      (Generic)
  import           System.IO.Error
  import           Text.Printf
  import qualified Data.Aeson        as A
  import qualified Data.ByteString   as BS
  import qualified Data.Yaml         as Y
  
  
  -- | Configuration for auto-runner.
  data Config = Cfg
      { _cfgSession :: Maybe String     -- ^ Default: 'Nothing'
      , _cfgYear    :: Integer          -- ^ Default: 2015
      }
    deriving (Generic)
  
  -- | No session key, and 2015.
  instance Default Config where
      def = Cfg { _cfgSession = Nothing
                , _cfgYear    = 2015
                }
  
  -- | Default math to find a configuration file.
  defConfPath :: FilePath
  defConfPath = "aoc-conf.yaml"
  
  -- | Load a 'Config' from a given filepath.
  configFile :: FilePath -> IO Config
  configFile fp = do
      cfgInp <- tryJust (guard . isDoesNotExistError)
              $ BS.readFile fp
      case cfgInp of
        Left () -> do
          Y.encodeFile @Config fp def
          return def
        Right b ->
          case Y.decodeEither' b of
            Left e -> do
              printf "Configuration file at %s could not be parsed:\n" fp
              print e
              return def
            Right cfg -> return cfg
  
  -- | Load a session token from the configuration file at a given filepath.
  session :: FilePath -> IO (Maybe String)
  session = fmap _cfgSession . configFile
  
  configJSON :: A.Options
  configJSON = A.defaultOptions
      { A.fieldLabelModifier = A.camelTo2 '-' . drop 4 }
  
  instance A.ToJSON Config where
      toJSON     = A.genericToJSON configJSON
      toEncoding = A.genericToEncoding configJSON
  instance A.FromJSON Config where
      parseJSON  = A.genericParseJSON configJSON
  